Inventory.java 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768
  1. /*
  2. * Copyright (C) 2004-2015 L2J Server
  3. *
  4. * This file is part of L2J Server.
  5. *
  6. * L2J Server is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * L2J Server is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package com.l2jserver.gameserver.model.itemcontainer;
  20. import java.sql.Connection;
  21. import java.sql.PreparedStatement;
  22. import java.sql.ResultSet;
  23. import java.util.ArrayList;
  24. import java.util.List;
  25. import java.util.logging.Level;
  26. import java.util.logging.Logger;
  27. import com.l2jserver.Config;
  28. import com.l2jserver.commons.database.pool.impl.ConnectionFactory;
  29. import com.l2jserver.gameserver.data.xml.impl.ArmorSetsData;
  30. import com.l2jserver.gameserver.datatables.ItemTable;
  31. import com.l2jserver.gameserver.enums.ItemLocation;
  32. import com.l2jserver.gameserver.enums.PrivateStoreType;
  33. import com.l2jserver.gameserver.model.L2ArmorSet;
  34. import com.l2jserver.gameserver.model.L2World;
  35. import com.l2jserver.gameserver.model.PcCondOverride;
  36. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  37. import com.l2jserver.gameserver.model.holders.SkillHolder;
  38. import com.l2jserver.gameserver.model.items.L2Item;
  39. import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
  40. import com.l2jserver.gameserver.model.items.type.EtcItemType;
  41. import com.l2jserver.gameserver.model.items.type.WeaponType;
  42. import com.l2jserver.gameserver.model.skills.Skill;
  43. import com.l2jserver.gameserver.network.serverpackets.SkillCoolTime;
  44. import com.l2jserver.util.StringUtil;
  45. /**
  46. * This class manages inventory
  47. * @version $Revision: 1.13.2.9.2.12 $ $Date: 2005/03/29 23:15:15 $ rewritten 23.2.2006 by Advi
  48. */
  49. public abstract class Inventory extends ItemContainer
  50. {
  51. protected static final Logger _log = Logger.getLogger(Inventory.class.getName());
  52. public interface PaperdollListener
  53. {
  54. public void notifyEquiped(int slot, L2ItemInstance inst, Inventory inventory);
  55. public void notifyUnequiped(int slot, L2ItemInstance inst, Inventory inventory);
  56. }
  57. // Common Items
  58. public static final int ADENA_ID = 57;
  59. public static final int ANCIENT_ADENA_ID = 5575;
  60. public static final long MAX_ADENA = Config.MAX_ADENA;
  61. public static final int PAPERDOLL_UNDER = 0;
  62. public static final int PAPERDOLL_HEAD = 1;
  63. public static final int PAPERDOLL_HAIR = 2;
  64. public static final int PAPERDOLL_HAIR2 = 3;
  65. public static final int PAPERDOLL_NECK = 4;
  66. public static final int PAPERDOLL_RHAND = 5;
  67. public static final int PAPERDOLL_CHEST = 6;
  68. public static final int PAPERDOLL_LHAND = 7;
  69. public static final int PAPERDOLL_REAR = 8;
  70. public static final int PAPERDOLL_LEAR = 9;
  71. public static final int PAPERDOLL_GLOVES = 10;
  72. public static final int PAPERDOLL_LEGS = 11;
  73. public static final int PAPERDOLL_FEET = 12;
  74. public static final int PAPERDOLL_RFINGER = 13;
  75. public static final int PAPERDOLL_LFINGER = 14;
  76. public static final int PAPERDOLL_LBRACELET = 15;
  77. public static final int PAPERDOLL_RBRACELET = 16;
  78. public static final int PAPERDOLL_DECO1 = 17;
  79. public static final int PAPERDOLL_DECO2 = 18;
  80. public static final int PAPERDOLL_DECO3 = 19;
  81. public static final int PAPERDOLL_DECO4 = 20;
  82. public static final int PAPERDOLL_DECO5 = 21;
  83. public static final int PAPERDOLL_DECO6 = 22;
  84. public static final int PAPERDOLL_CLOAK = 23;
  85. public static final int PAPERDOLL_BELT = 24;
  86. public static final int PAPERDOLL_TOTALSLOTS = 25;
  87. // Speed percentage mods
  88. public static final double MAX_ARMOR_WEIGHT = 12000;
  89. private final L2ItemInstance[] _paperdoll;
  90. private final List<PaperdollListener> _paperdollListeners;
  91. // protected to be accessed from child classes only
  92. protected int _totalWeight;
  93. // used to quickly check for using of items of special type
  94. private int _wearedMask;
  95. // Recorder of alterations in inventory
  96. private static final class ChangeRecorder implements PaperdollListener
  97. {
  98. private final Inventory _inventory;
  99. private final List<L2ItemInstance> _changed;
  100. /**
  101. * Constructor of the ChangeRecorder
  102. * @param inventory
  103. */
  104. ChangeRecorder(Inventory inventory)
  105. {
  106. _inventory = inventory;
  107. _changed = new ArrayList<>();
  108. _inventory.addPaperdollListener(this);
  109. }
  110. /**
  111. * Add alteration in inventory when item equipped
  112. * @param slot
  113. * @param item
  114. * @param inventory
  115. */
  116. @Override
  117. public void notifyEquiped(int slot, L2ItemInstance item, Inventory inventory)
  118. {
  119. if (!_changed.contains(item))
  120. {
  121. _changed.add(item);
  122. }
  123. }
  124. /**
  125. * Add alteration in inventory when item unequipped
  126. * @param slot
  127. * @param item
  128. * @param inventory
  129. */
  130. @Override
  131. public void notifyUnequiped(int slot, L2ItemInstance item, Inventory inventory)
  132. {
  133. if (!_changed.contains(item))
  134. {
  135. _changed.add(item);
  136. }
  137. }
  138. /**
  139. * Returns alterations in inventory
  140. * @return L2ItemInstance[] : array of altered items
  141. */
  142. public L2ItemInstance[] getChangedItems()
  143. {
  144. return _changed.toArray(new L2ItemInstance[_changed.size()]);
  145. }
  146. }
  147. private static final class BowCrossRodListener implements PaperdollListener
  148. {
  149. private static BowCrossRodListener instance = new BowCrossRodListener();
  150. public static BowCrossRodListener getInstance()
  151. {
  152. return instance;
  153. }
  154. @Override
  155. public void notifyUnequiped(int slot, L2ItemInstance item, Inventory inventory)
  156. {
  157. if (slot != PAPERDOLL_RHAND)
  158. {
  159. return;
  160. }
  161. if (item.getItemType() == WeaponType.BOW)
  162. {
  163. L2ItemInstance arrow = inventory.getPaperdollItem(PAPERDOLL_LHAND);
  164. if (arrow != null)
  165. {
  166. inventory.setPaperdollItem(PAPERDOLL_LHAND, null);
  167. }
  168. }
  169. else if (item.getItemType() == WeaponType.CROSSBOW)
  170. {
  171. L2ItemInstance bolts = inventory.getPaperdollItem(PAPERDOLL_LHAND);
  172. if (bolts != null)
  173. {
  174. inventory.setPaperdollItem(PAPERDOLL_LHAND, null);
  175. }
  176. }
  177. else if (item.getItemType() == WeaponType.FISHINGROD)
  178. {
  179. L2ItemInstance lure = inventory.getPaperdollItem(PAPERDOLL_LHAND);
  180. if (lure != null)
  181. {
  182. inventory.setPaperdollItem(PAPERDOLL_LHAND, null);
  183. }
  184. }
  185. }
  186. @Override
  187. public void notifyEquiped(int slot, L2ItemInstance item, Inventory inventory)
  188. {
  189. if (slot != PAPERDOLL_RHAND)
  190. {
  191. return;
  192. }
  193. if (item.getItemType() == WeaponType.BOW)
  194. {
  195. L2ItemInstance arrow = inventory.findArrowForBow(item.getItem());
  196. if (arrow != null)
  197. {
  198. inventory.setPaperdollItem(PAPERDOLL_LHAND, arrow);
  199. }
  200. }
  201. else if (item.getItemType() == WeaponType.CROSSBOW)
  202. {
  203. L2ItemInstance bolts = inventory.findBoltForCrossBow(item.getItem());
  204. if (bolts != null)
  205. {
  206. inventory.setPaperdollItem(PAPERDOLL_LHAND, bolts);
  207. }
  208. }
  209. }
  210. }
  211. private static final class StatsListener implements PaperdollListener
  212. {
  213. private static StatsListener instance = new StatsListener();
  214. public static StatsListener getInstance()
  215. {
  216. return instance;
  217. }
  218. @Override
  219. public void notifyUnequiped(int slot, L2ItemInstance item, Inventory inventory)
  220. {
  221. inventory.getOwner().removeStatsOwner(item);
  222. }
  223. @Override
  224. public void notifyEquiped(int slot, L2ItemInstance item, Inventory inventory)
  225. {
  226. inventory.getOwner().addStatFuncs(item.getStatFuncs(inventory.getOwner()));
  227. }
  228. }
  229. private static final class ItemSkillsListener implements PaperdollListener
  230. {
  231. private static ItemSkillsListener instance = new ItemSkillsListener();
  232. public static ItemSkillsListener getInstance()
  233. {
  234. return instance;
  235. }
  236. @Override
  237. public void notifyUnequiped(int slot, L2ItemInstance item, Inventory inventory)
  238. {
  239. if (!(inventory.getOwner() instanceof L2PcInstance))
  240. {
  241. return;
  242. }
  243. final L2PcInstance player = (L2PcInstance) inventory.getOwner();
  244. Skill enchant4Skill, itemSkill;
  245. L2Item it = item.getItem();
  246. boolean update = false;
  247. boolean updateTimeStamp = false;
  248. // Remove augmentation bonuses on unequip
  249. if (item.isAugmented())
  250. {
  251. item.getAugmentation().removeBonus(player);
  252. }
  253. item.removeElementAttrBonus(player);
  254. // Remove skills bestowed from +4 armor
  255. if (item.getEnchantLevel() >= 4)
  256. {
  257. enchant4Skill = it.getEnchant4Skill();
  258. if (enchant4Skill != null)
  259. {
  260. player.removeSkill(enchant4Skill, false, enchant4Skill.isPassive());
  261. update = true;
  262. }
  263. }
  264. item.clearEnchantStats();
  265. final SkillHolder[] skills = it.getSkills();
  266. if (skills != null)
  267. {
  268. for (SkillHolder skillInfo : skills)
  269. {
  270. if (skillInfo == null)
  271. {
  272. continue;
  273. }
  274. itemSkill = skillInfo.getSkill();
  275. if (itemSkill != null)
  276. {
  277. player.removeSkill(itemSkill, false, itemSkill.isPassive());
  278. update = true;
  279. }
  280. else
  281. {
  282. _log.warning("Inventory.ItemSkillsListener.Weapon: Incorrect skill: " + skillInfo + ".");
  283. }
  284. }
  285. }
  286. if (item.isArmor())
  287. {
  288. for (L2ItemInstance itm : inventory.getItems())
  289. {
  290. if (!itm.isEquipped() || (itm.getItem().getSkills() == null) || itm.equals(item))
  291. {
  292. continue;
  293. }
  294. for (SkillHolder sk : itm.getItem().getSkills())
  295. {
  296. if (player.getSkillLevel(sk.getSkillId()) != -1)
  297. {
  298. continue;
  299. }
  300. itemSkill = sk.getSkill();
  301. if (itemSkill != null)
  302. {
  303. player.addSkill(itemSkill, false);
  304. if (itemSkill.isActive())
  305. {
  306. if (!player.hasSkillReuse(itemSkill.getReuseHashCode()))
  307. {
  308. int equipDelay = item.getEquipReuseDelay();
  309. if (equipDelay > 0)
  310. {
  311. player.addTimeStamp(itemSkill, equipDelay);
  312. player.disableSkill(itemSkill, equipDelay);
  313. }
  314. }
  315. updateTimeStamp = true;
  316. }
  317. update = true;
  318. }
  319. }
  320. }
  321. }
  322. // Apply skill, if weapon have "skills on unequip"
  323. Skill unequipSkill = it.getUnequipSkill();
  324. if (unequipSkill != null)
  325. {
  326. unequipSkill.activateSkill(player, player);
  327. }
  328. if (update)
  329. {
  330. player.sendSkillList();
  331. if (updateTimeStamp)
  332. {
  333. player.sendPacket(new SkillCoolTime(player));
  334. }
  335. }
  336. }
  337. @Override
  338. public void notifyEquiped(int slot, L2ItemInstance item, Inventory inventory)
  339. {
  340. if (!(inventory.getOwner() instanceof L2PcInstance))
  341. {
  342. return;
  343. }
  344. final L2PcInstance player = (L2PcInstance) inventory.getOwner();
  345. Skill enchant4Skill, itemSkill;
  346. L2Item it = item.getItem();
  347. boolean update = false;
  348. boolean updateTimeStamp = false;
  349. // Apply augmentation bonuses on equip
  350. if (item.isAugmented())
  351. {
  352. item.getAugmentation().applyBonus(player);
  353. }
  354. item.updateElementAttrBonus(player);
  355. // Add skills bestowed from +4 armor
  356. if (item.getEnchantLevel() >= 4)
  357. {
  358. enchant4Skill = it.getEnchant4Skill();
  359. if (enchant4Skill != null)
  360. {
  361. player.addSkill(enchant4Skill, false);
  362. update = true;
  363. }
  364. }
  365. item.applyEnchantStats();
  366. final SkillHolder[] skills = it.getSkills();
  367. if (skills != null)
  368. {
  369. for (SkillHolder skillInfo : skills)
  370. {
  371. if (skillInfo == null)
  372. {
  373. continue;
  374. }
  375. itemSkill = skillInfo.getSkill();
  376. if (itemSkill != null)
  377. {
  378. itemSkill.setReferenceItemId(item.getId());
  379. player.addSkill(itemSkill, false);
  380. if (itemSkill.isActive())
  381. {
  382. if (!player.hasSkillReuse(itemSkill.getReuseHashCode()))
  383. {
  384. int equipDelay = item.getEquipReuseDelay();
  385. if (equipDelay > 0)
  386. {
  387. player.addTimeStamp(itemSkill, equipDelay);
  388. player.disableSkill(itemSkill, equipDelay);
  389. }
  390. }
  391. updateTimeStamp = true;
  392. }
  393. update = true;
  394. }
  395. else
  396. {
  397. _log.warning("Inventory.ItemSkillsListener.Weapon: Incorrect skill: " + skillInfo + ".");
  398. }
  399. }
  400. }
  401. if (update)
  402. {
  403. player.sendSkillList();
  404. if (updateTimeStamp)
  405. {
  406. player.sendPacket(new SkillCoolTime(player));
  407. }
  408. }
  409. }
  410. }
  411. private static final class ArmorSetListener implements PaperdollListener
  412. {
  413. private static ArmorSetListener instance = new ArmorSetListener();
  414. public static ArmorSetListener getInstance()
  415. {
  416. return instance;
  417. }
  418. @Override
  419. public void notifyEquiped(int slot, L2ItemInstance item, Inventory inventory)
  420. {
  421. if (!(inventory.getOwner() instanceof L2PcInstance))
  422. {
  423. return;
  424. }
  425. final L2PcInstance player = (L2PcInstance) inventory.getOwner();
  426. // Checks if player is wearing a chest item
  427. final L2ItemInstance chestItem = inventory.getPaperdollItem(PAPERDOLL_CHEST);
  428. if (chestItem == null)
  429. {
  430. return;
  431. }
  432. // Checks for armor set for the equipped chest.
  433. if (!ArmorSetsData.getInstance().isArmorSet(chestItem.getId()))
  434. {
  435. return;
  436. }
  437. final L2ArmorSet armorSet = ArmorSetsData.getInstance().getSet(chestItem.getId());
  438. boolean update = false;
  439. boolean updateTimeStamp = false;
  440. // Checks if equipped item is part of set
  441. if (armorSet.containItem(slot, item.getId()))
  442. {
  443. if (armorSet.containAll(player))
  444. {
  445. Skill itemSkill;
  446. final List<SkillHolder> skills = armorSet.getSkills();
  447. if (skills != null)
  448. {
  449. for (SkillHolder holder : skills)
  450. {
  451. itemSkill = holder.getSkill();
  452. if (itemSkill != null)
  453. {
  454. player.addSkill(itemSkill, false);
  455. if (itemSkill.isActive())
  456. {
  457. if (!player.hasSkillReuse(itemSkill.getReuseHashCode()))
  458. {
  459. int equipDelay = item.getEquipReuseDelay();
  460. if (equipDelay > 0)
  461. {
  462. player.addTimeStamp(itemSkill, equipDelay);
  463. player.disableSkill(itemSkill, equipDelay);
  464. }
  465. }
  466. updateTimeStamp = true;
  467. }
  468. update = true;
  469. }
  470. else
  471. {
  472. _log.warning("Inventory.ArmorSetListener: Incorrect skill: " + holder + ".");
  473. }
  474. }
  475. }
  476. if (armorSet.containShield(player)) // has shield from set
  477. {
  478. for (SkillHolder holder : armorSet.getShieldSkillId())
  479. {
  480. if (holder.getSkill() != null)
  481. {
  482. player.addSkill(holder.getSkill(), false);
  483. update = true;
  484. }
  485. else
  486. {
  487. _log.warning("Inventory.ArmorSetListener: Incorrect skill: " + holder + ".");
  488. }
  489. }
  490. }
  491. if (armorSet.isEnchanted6(player)) // has all parts of set enchanted to 6 or more
  492. {
  493. for (SkillHolder holder : armorSet.getEnchant6skillId())
  494. {
  495. if (holder.getSkill() != null)
  496. {
  497. player.addSkill(holder.getSkill(), false);
  498. update = true;
  499. }
  500. else
  501. {
  502. _log.warning("Inventory.ArmorSetListener: Incorrect skill: " + holder + ".");
  503. }
  504. }
  505. }
  506. }
  507. }
  508. else if (armorSet.containShield(item.getId()))
  509. {
  510. for (SkillHolder holder : armorSet.getShieldSkillId())
  511. {
  512. if (holder.getSkill() != null)
  513. {
  514. player.addSkill(holder.getSkill(), false);
  515. update = true;
  516. }
  517. else
  518. {
  519. _log.warning("Inventory.ArmorSetListener: Incorrect skill: " + holder + ".");
  520. }
  521. }
  522. }
  523. if (update)
  524. {
  525. player.sendSkillList();
  526. if (updateTimeStamp)
  527. {
  528. player.sendPacket(new SkillCoolTime(player));
  529. }
  530. }
  531. }
  532. @Override
  533. public void notifyUnequiped(int slot, L2ItemInstance item, Inventory inventory)
  534. {
  535. if (!(inventory.getOwner() instanceof L2PcInstance))
  536. {
  537. return;
  538. }
  539. final L2PcInstance player = (L2PcInstance) inventory.getOwner();
  540. boolean remove = false;
  541. Skill itemSkill;
  542. List<SkillHolder> skills = null;
  543. List<SkillHolder> shieldSkill = null; // shield skill
  544. List<SkillHolder> skillId6 = null; // enchant +6 skill
  545. if (slot == PAPERDOLL_CHEST)
  546. {
  547. if (!ArmorSetsData.getInstance().isArmorSet(item.getId()))
  548. {
  549. return;
  550. }
  551. final L2ArmorSet armorSet = ArmorSetsData.getInstance().getSet(item.getId());
  552. remove = true;
  553. skills = armorSet.getSkills();
  554. shieldSkill = armorSet.getShieldSkillId();
  555. skillId6 = armorSet.getEnchant6skillId();
  556. }
  557. else
  558. {
  559. L2ItemInstance chestItem = inventory.getPaperdollItem(PAPERDOLL_CHEST);
  560. if (chestItem == null)
  561. {
  562. return;
  563. }
  564. L2ArmorSet armorSet = ArmorSetsData.getInstance().getSet(chestItem.getId());
  565. if (armorSet == null)
  566. {
  567. return;
  568. }
  569. if (armorSet.containItem(slot, item.getId())) // removed part of set
  570. {
  571. remove = true;
  572. skills = armorSet.getSkills();
  573. shieldSkill = armorSet.getShieldSkillId();
  574. skillId6 = armorSet.getEnchant6skillId();
  575. }
  576. else if (armorSet.containShield(item.getId())) // removed shield
  577. {
  578. remove = true;
  579. shieldSkill = armorSet.getShieldSkillId();
  580. }
  581. }
  582. if (remove)
  583. {
  584. if (skills != null)
  585. {
  586. for (SkillHolder holder : skills)
  587. {
  588. itemSkill = holder.getSkill();
  589. if (itemSkill != null)
  590. {
  591. player.removeSkill(itemSkill, false, itemSkill.isPassive());
  592. }
  593. else
  594. {
  595. _log.warning("Inventory.ArmorSetListener: Incorrect skill: " + holder + ".");
  596. }
  597. }
  598. }
  599. if (shieldSkill != null)
  600. {
  601. for (SkillHolder holder : shieldSkill)
  602. {
  603. itemSkill = holder.getSkill();
  604. if (itemSkill != null)
  605. {
  606. player.removeSkill(itemSkill, false, itemSkill.isPassive());
  607. }
  608. else
  609. {
  610. _log.warning("Inventory.ArmorSetListener: Incorrect skill: " + holder + ".");
  611. }
  612. }
  613. }
  614. if (skillId6 != null)
  615. {
  616. for (SkillHolder holder : skillId6)
  617. {
  618. itemSkill = holder.getSkill();
  619. if (itemSkill != null)
  620. {
  621. player.removeSkill(itemSkill, false, itemSkill.isPassive());
  622. }
  623. else
  624. {
  625. _log.warning("Inventory.ArmorSetListener: Incorrect skill: " + holder + ".");
  626. }
  627. }
  628. }
  629. player.checkItemRestriction();
  630. player.sendSkillList();
  631. }
  632. }
  633. }
  634. private static final class BraceletListener implements PaperdollListener
  635. {
  636. private static BraceletListener instance = new BraceletListener();
  637. public static BraceletListener getInstance()
  638. {
  639. return instance;
  640. }
  641. @Override
  642. public void notifyUnequiped(int slot, L2ItemInstance item, Inventory inventory)
  643. {
  644. if (item.getItem().getBodyPart() == L2Item.SLOT_R_BRACELET)
  645. {
  646. inventory.unEquipItemInSlot(PAPERDOLL_DECO1);
  647. inventory.unEquipItemInSlot(PAPERDOLL_DECO2);
  648. inventory.unEquipItemInSlot(PAPERDOLL_DECO3);
  649. inventory.unEquipItemInSlot(PAPERDOLL_DECO4);
  650. inventory.unEquipItemInSlot(PAPERDOLL_DECO5);
  651. inventory.unEquipItemInSlot(PAPERDOLL_DECO6);
  652. }
  653. }
  654. // Note (April 3, 2009): Currently on equip, talismans do not display properly, do we need checks here to fix this?
  655. @Override
  656. public void notifyEquiped(int slot, L2ItemInstance item, Inventory inventory)
  657. {
  658. }
  659. }
  660. /**
  661. * Constructor of the inventory
  662. */
  663. protected Inventory()
  664. {
  665. _paperdoll = new L2ItemInstance[PAPERDOLL_TOTALSLOTS];
  666. _paperdollListeners = new ArrayList<>();
  667. if (this instanceof PcInventory)
  668. {
  669. addPaperdollListener(ArmorSetListener.getInstance());
  670. addPaperdollListener(BowCrossRodListener.getInstance());
  671. addPaperdollListener(ItemSkillsListener.getInstance());
  672. addPaperdollListener(BraceletListener.getInstance());
  673. }
  674. // common
  675. addPaperdollListener(StatsListener.getInstance());
  676. }
  677. protected abstract ItemLocation getEquipLocation();
  678. /**
  679. * Returns the instance of new ChangeRecorder
  680. * @return ChangeRecorder
  681. */
  682. private ChangeRecorder newRecorder()
  683. {
  684. return new ChangeRecorder(this);
  685. }
  686. /**
  687. * Drop item from inventory and updates database
  688. * @param process : String Identifier of process triggering this action
  689. * @param item : L2ItemInstance to be dropped
  690. * @param actor : L2PcInstance Player requesting the item drop
  691. * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
  692. * @return L2ItemInstance corresponding to the destroyed item or the updated item in inventory
  693. */
  694. public L2ItemInstance dropItem(String process, L2ItemInstance item, L2PcInstance actor, Object reference)
  695. {
  696. if (item == null)
  697. {
  698. return null;
  699. }
  700. synchronized (item)
  701. {
  702. if (!_items.contains(item))
  703. {
  704. return null;
  705. }
  706. removeItem(item);
  707. item.setOwnerId(process, 0, actor, reference);
  708. item.setItemLocation(ItemLocation.VOID);
  709. item.setLastChange(L2ItemInstance.REMOVED);
  710. item.updateDatabase();
  711. refreshWeight();
  712. }
  713. return item;
  714. }
  715. /**
  716. * Drop item from inventory by using its <B>objectID</B> and updates database
  717. * @param process : String Identifier of process triggering this action
  718. * @param objectId : int Item Instance identifier of the item to be dropped
  719. * @param count : int Quantity of items to be dropped
  720. * @param actor : L2PcInstance Player requesting the item drop
  721. * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
  722. * @return L2ItemInstance corresponding to the destroyed item or the updated item in inventory
  723. */
  724. public L2ItemInstance dropItem(String process, int objectId, long count, L2PcInstance actor, Object reference)
  725. {
  726. L2ItemInstance item = getItemByObjectId(objectId);
  727. if (item == null)
  728. {
  729. return null;
  730. }
  731. synchronized (item)
  732. {
  733. if (!_items.contains(item))
  734. {
  735. return null;
  736. }
  737. // Adjust item quantity and create new instance to drop
  738. // Directly drop entire item
  739. if (item.getCount() > count)
  740. {
  741. item.changeCount(process, -count, actor, reference);
  742. item.setLastChange(L2ItemInstance.MODIFIED);
  743. item.updateDatabase();
  744. item = ItemTable.getInstance().createItem(process, item.getId(), count, actor, reference);
  745. item.updateDatabase();
  746. refreshWeight();
  747. return item;
  748. }
  749. }
  750. return dropItem(process, item, actor, reference);
  751. }
  752. /**
  753. * Adds item to inventory for further adjustments and Equip it if necessary (itemlocation defined)
  754. * @param item : L2ItemInstance to be added from inventory
  755. */
  756. @Override
  757. protected void addItem(L2ItemInstance item)
  758. {
  759. super.addItem(item);
  760. if (item.isEquipped())
  761. {
  762. equipItem(item);
  763. }
  764. }
  765. /**
  766. * Removes item from inventory for further adjustments.
  767. * @param item : L2ItemInstance to be removed from inventory
  768. */
  769. @Override
  770. protected boolean removeItem(L2ItemInstance item)
  771. {
  772. // Unequip item if equiped
  773. for (int i = 0; i < _paperdoll.length; i++)
  774. {
  775. if (_paperdoll[i] == item)
  776. {
  777. unEquipItemInSlot(i);
  778. }
  779. }
  780. return super.removeItem(item);
  781. }
  782. /**
  783. * @param slot the slot.
  784. * @return the item in the paperdoll slot
  785. */
  786. public L2ItemInstance getPaperdollItem(int slot)
  787. {
  788. return _paperdoll[slot];
  789. }
  790. /**
  791. * @param slot the slot.
  792. * @return {@code true} if specified paperdoll slot is empty, {@code false} otherwise
  793. */
  794. public boolean isPaperdollSlotEmpty(int slot)
  795. {
  796. return _paperdoll[slot] == null;
  797. }
  798. public static int getPaperdollIndex(int slot)
  799. {
  800. switch (slot)
  801. {
  802. case L2Item.SLOT_UNDERWEAR:
  803. return PAPERDOLL_UNDER;
  804. case L2Item.SLOT_R_EAR:
  805. return PAPERDOLL_REAR;
  806. case L2Item.SLOT_LR_EAR:
  807. case L2Item.SLOT_L_EAR:
  808. return PAPERDOLL_LEAR;
  809. case L2Item.SLOT_NECK:
  810. return PAPERDOLL_NECK;
  811. case L2Item.SLOT_R_FINGER:
  812. case L2Item.SLOT_LR_FINGER:
  813. return PAPERDOLL_RFINGER;
  814. case L2Item.SLOT_L_FINGER:
  815. return PAPERDOLL_LFINGER;
  816. case L2Item.SLOT_HEAD:
  817. return PAPERDOLL_HEAD;
  818. case L2Item.SLOT_R_HAND:
  819. case L2Item.SLOT_LR_HAND:
  820. return PAPERDOLL_RHAND;
  821. case L2Item.SLOT_L_HAND:
  822. return PAPERDOLL_LHAND;
  823. case L2Item.SLOT_GLOVES:
  824. return PAPERDOLL_GLOVES;
  825. case L2Item.SLOT_CHEST:
  826. case L2Item.SLOT_FULL_ARMOR:
  827. case L2Item.SLOT_ALLDRESS:
  828. return PAPERDOLL_CHEST;
  829. case L2Item.SLOT_LEGS:
  830. return PAPERDOLL_LEGS;
  831. case L2Item.SLOT_FEET:
  832. return PAPERDOLL_FEET;
  833. case L2Item.SLOT_BACK:
  834. return PAPERDOLL_CLOAK;
  835. case L2Item.SLOT_HAIR:
  836. case L2Item.SLOT_HAIRALL:
  837. return PAPERDOLL_HAIR;
  838. case L2Item.SLOT_HAIR2:
  839. return PAPERDOLL_HAIR2;
  840. case L2Item.SLOT_R_BRACELET:
  841. return PAPERDOLL_RBRACELET;
  842. case L2Item.SLOT_L_BRACELET:
  843. return PAPERDOLL_LBRACELET;
  844. case L2Item.SLOT_DECO:
  845. return PAPERDOLL_DECO1; // return first we deal with it later
  846. case L2Item.SLOT_BELT:
  847. return PAPERDOLL_BELT;
  848. }
  849. return -1;
  850. }
  851. /**
  852. * Returns the item in the paperdoll L2Item slot
  853. * @param slot identifier
  854. * @return L2ItemInstance
  855. */
  856. public L2ItemInstance getPaperdollItemByL2ItemId(int slot)
  857. {
  858. int index = getPaperdollIndex(slot);
  859. if (index == -1)
  860. {
  861. return null;
  862. }
  863. return _paperdoll[index];
  864. }
  865. /**
  866. * Returns the ID of the item in the paperdoll slot
  867. * @param slot : int designating the slot
  868. * @return int designating the ID of the item
  869. */
  870. public int getPaperdollItemId(int slot)
  871. {
  872. L2ItemInstance item = _paperdoll[slot];
  873. if (item != null)
  874. {
  875. return item.getId();
  876. }
  877. return 0;
  878. }
  879. /**
  880. * Returns the ID of the item in the paperdoll slot
  881. * @param slot : int designating the slot
  882. * @return int designating the ID of the item
  883. */
  884. public int getPaperdollItemDisplayId(int slot)
  885. {
  886. final L2ItemInstance item = _paperdoll[slot];
  887. return (item != null) ? item.getDisplayId() : 0;
  888. }
  889. public int getPaperdollAugmentationId(int slot)
  890. {
  891. final L2ItemInstance item = _paperdoll[slot];
  892. return ((item != null) && (item.getAugmentation() != null)) ? item.getAugmentation().getAugmentationId() : 0;
  893. }
  894. /**
  895. * Returns the objectID associated to the item in the paperdoll slot
  896. * @param slot : int pointing out the slot
  897. * @return int designating the objectID
  898. */
  899. public int getPaperdollObjectId(int slot)
  900. {
  901. final L2ItemInstance item = _paperdoll[slot];
  902. return (item != null) ? item.getObjectId() : 0;
  903. }
  904. /**
  905. * Adds new inventory's paperdoll listener.
  906. * @param listener the new listener
  907. */
  908. public synchronized void addPaperdollListener(PaperdollListener listener)
  909. {
  910. assert !_paperdollListeners.contains(listener);
  911. _paperdollListeners.add(listener);
  912. }
  913. /**
  914. * Removes a paperdoll listener.
  915. * @param listener the listener to be deleted
  916. */
  917. public synchronized void removePaperdollListener(PaperdollListener listener)
  918. {
  919. _paperdollListeners.remove(listener);
  920. }
  921. /**
  922. * Equips an item in the given slot of the paperdoll.<br>
  923. * <U><I>Remark :</I></U> The item <B>must be</B> in the inventory already.
  924. * @param slot : int pointing out the slot of the paperdoll
  925. * @param item : L2ItemInstance pointing out the item to add in slot
  926. * @return L2ItemInstance designating the item placed in the slot before
  927. */
  928. public synchronized L2ItemInstance setPaperdollItem(int slot, L2ItemInstance item)
  929. {
  930. L2ItemInstance old = _paperdoll[slot];
  931. if (old != item)
  932. {
  933. if (old != null)
  934. {
  935. _paperdoll[slot] = null;
  936. // Put old item from paperdoll slot to base location
  937. old.setItemLocation(getBaseLocation());
  938. old.setLastChange(L2ItemInstance.MODIFIED);
  939. // Get the mask for paperdoll
  940. int mask = 0;
  941. for (int i = 0; i < PAPERDOLL_TOTALSLOTS; i++)
  942. {
  943. L2ItemInstance pi = _paperdoll[i];
  944. if (pi != null)
  945. {
  946. mask |= pi.getItem().getItemMask();
  947. }
  948. }
  949. _wearedMask = mask;
  950. // Notify all paperdoll listener in order to unequip old item in slot
  951. for (PaperdollListener listener : _paperdollListeners)
  952. {
  953. if (listener == null)
  954. {
  955. continue;
  956. }
  957. listener.notifyUnequiped(slot, old, this);
  958. }
  959. old.updateDatabase();
  960. }
  961. // Add new item in slot of paperdoll
  962. if (item != null)
  963. {
  964. _paperdoll[slot] = item;
  965. item.setItemLocation(getEquipLocation(), slot);
  966. item.setLastChange(L2ItemInstance.MODIFIED);
  967. _wearedMask |= item.getItem().getItemMask();
  968. for (PaperdollListener listener : _paperdollListeners)
  969. {
  970. if (listener == null)
  971. {
  972. continue;
  973. }
  974. listener.notifyEquiped(slot, item, this);
  975. }
  976. item.updateDatabase();
  977. }
  978. }
  979. return old;
  980. }
  981. /**
  982. * @return the mask of wore item
  983. */
  984. public int getWearedMask()
  985. {
  986. return _wearedMask;
  987. }
  988. public int getSlotFromItem(L2ItemInstance item)
  989. {
  990. int slot = -1;
  991. final int location = item.getLocationSlot();
  992. switch (location)
  993. {
  994. case PAPERDOLL_UNDER:
  995. slot = L2Item.SLOT_UNDERWEAR;
  996. break;
  997. case PAPERDOLL_LEAR:
  998. slot = L2Item.SLOT_L_EAR;
  999. break;
  1000. case PAPERDOLL_REAR:
  1001. slot = L2Item.SLOT_R_EAR;
  1002. break;
  1003. case PAPERDOLL_NECK:
  1004. slot = L2Item.SLOT_NECK;
  1005. break;
  1006. case PAPERDOLL_RFINGER:
  1007. slot = L2Item.SLOT_R_FINGER;
  1008. break;
  1009. case PAPERDOLL_LFINGER:
  1010. slot = L2Item.SLOT_L_FINGER;
  1011. break;
  1012. case PAPERDOLL_HAIR:
  1013. slot = L2Item.SLOT_HAIR;
  1014. break;
  1015. case PAPERDOLL_HAIR2:
  1016. slot = L2Item.SLOT_HAIR2;
  1017. break;
  1018. case PAPERDOLL_HEAD:
  1019. slot = L2Item.SLOT_HEAD;
  1020. break;
  1021. case PAPERDOLL_RHAND:
  1022. slot = L2Item.SLOT_R_HAND;
  1023. break;
  1024. case PAPERDOLL_LHAND:
  1025. slot = L2Item.SLOT_L_HAND;
  1026. break;
  1027. case PAPERDOLL_GLOVES:
  1028. slot = L2Item.SLOT_GLOVES;
  1029. break;
  1030. case PAPERDOLL_CHEST:
  1031. slot = item.getItem().getBodyPart();
  1032. break;
  1033. case PAPERDOLL_LEGS:
  1034. slot = L2Item.SLOT_LEGS;
  1035. break;
  1036. case PAPERDOLL_CLOAK:
  1037. slot = L2Item.SLOT_BACK;
  1038. break;
  1039. case PAPERDOLL_FEET:
  1040. slot = L2Item.SLOT_FEET;
  1041. break;
  1042. case PAPERDOLL_LBRACELET:
  1043. slot = L2Item.SLOT_L_BRACELET;
  1044. break;
  1045. case PAPERDOLL_RBRACELET:
  1046. slot = L2Item.SLOT_R_BRACELET;
  1047. break;
  1048. case PAPERDOLL_DECO1:
  1049. case PAPERDOLL_DECO2:
  1050. case PAPERDOLL_DECO3:
  1051. case PAPERDOLL_DECO4:
  1052. case PAPERDOLL_DECO5:
  1053. case PAPERDOLL_DECO6:
  1054. slot = L2Item.SLOT_DECO;
  1055. break;
  1056. case PAPERDOLL_BELT:
  1057. slot = L2Item.SLOT_BELT;
  1058. break;
  1059. }
  1060. return slot;
  1061. }
  1062. /**
  1063. * Unequips item in body slot and returns alterations.<BR>
  1064. * <B>If you dont need return value use {@link Inventory#unEquipItemInBodySlot(int)} instead</B>
  1065. * @param slot : int designating the slot of the paperdoll
  1066. * @return L2ItemInstance[] : list of changes
  1067. */
  1068. public L2ItemInstance[] unEquipItemInBodySlotAndRecord(int slot)
  1069. {
  1070. Inventory.ChangeRecorder recorder = newRecorder();
  1071. try
  1072. {
  1073. unEquipItemInBodySlot(slot);
  1074. }
  1075. finally
  1076. {
  1077. removePaperdollListener(recorder);
  1078. }
  1079. return recorder.getChangedItems();
  1080. }
  1081. /**
  1082. * Sets item in slot of the paperdoll to null value
  1083. * @param pdollSlot : int designating the slot
  1084. * @return L2ItemInstance designating the item in slot before change
  1085. */
  1086. public L2ItemInstance unEquipItemInSlot(int pdollSlot)
  1087. {
  1088. return setPaperdollItem(pdollSlot, null);
  1089. }
  1090. /**
  1091. * Unequips item in slot and returns alterations<BR>
  1092. * <B>If you dont need return value use {@link Inventory#unEquipItemInSlot(int)} instead</B>
  1093. * @param slot : int designating the slot
  1094. * @return L2ItemInstance[] : list of items altered
  1095. */
  1096. public L2ItemInstance[] unEquipItemInSlotAndRecord(int slot)
  1097. {
  1098. Inventory.ChangeRecorder recorder = newRecorder();
  1099. try
  1100. {
  1101. unEquipItemInSlot(slot);
  1102. if (getOwner() instanceof L2PcInstance)
  1103. {
  1104. ((L2PcInstance) getOwner()).refreshExpertisePenalty();
  1105. }
  1106. }
  1107. finally
  1108. {
  1109. removePaperdollListener(recorder);
  1110. }
  1111. return recorder.getChangedItems();
  1112. }
  1113. /**
  1114. * Unequips item in slot (i.e. equips with default value)
  1115. * @param slot : int designating the slot
  1116. * @return {@link L2ItemInstance} designating the item placed in the slot
  1117. */
  1118. public L2ItemInstance unEquipItemInBodySlot(int slot)
  1119. {
  1120. if (Config.DEBUG)
  1121. {
  1122. _log.info(Inventory.class.getSimpleName() + ": Unequip body slot:" + slot);
  1123. }
  1124. int pdollSlot = -1;
  1125. switch (slot)
  1126. {
  1127. case L2Item.SLOT_L_EAR:
  1128. pdollSlot = PAPERDOLL_LEAR;
  1129. break;
  1130. case L2Item.SLOT_R_EAR:
  1131. pdollSlot = PAPERDOLL_REAR;
  1132. break;
  1133. case L2Item.SLOT_NECK:
  1134. pdollSlot = PAPERDOLL_NECK;
  1135. break;
  1136. case L2Item.SLOT_R_FINGER:
  1137. pdollSlot = PAPERDOLL_RFINGER;
  1138. break;
  1139. case L2Item.SLOT_L_FINGER:
  1140. pdollSlot = PAPERDOLL_LFINGER;
  1141. break;
  1142. case L2Item.SLOT_HAIR:
  1143. pdollSlot = PAPERDOLL_HAIR;
  1144. break;
  1145. case L2Item.SLOT_HAIR2:
  1146. pdollSlot = PAPERDOLL_HAIR2;
  1147. break;
  1148. case L2Item.SLOT_HAIRALL:
  1149. setPaperdollItem(PAPERDOLL_HAIR, null);
  1150. pdollSlot = PAPERDOLL_HAIR;
  1151. break;
  1152. case L2Item.SLOT_HEAD:
  1153. pdollSlot = PAPERDOLL_HEAD;
  1154. break;
  1155. case L2Item.SLOT_R_HAND:
  1156. case L2Item.SLOT_LR_HAND:
  1157. pdollSlot = PAPERDOLL_RHAND;
  1158. break;
  1159. case L2Item.SLOT_L_HAND:
  1160. pdollSlot = PAPERDOLL_LHAND;
  1161. break;
  1162. case L2Item.SLOT_GLOVES:
  1163. pdollSlot = PAPERDOLL_GLOVES;
  1164. break;
  1165. case L2Item.SLOT_CHEST:
  1166. case L2Item.SLOT_ALLDRESS:
  1167. case L2Item.SLOT_FULL_ARMOR:
  1168. pdollSlot = PAPERDOLL_CHEST;
  1169. break;
  1170. case L2Item.SLOT_LEGS:
  1171. pdollSlot = PAPERDOLL_LEGS;
  1172. break;
  1173. case L2Item.SLOT_BACK:
  1174. pdollSlot = PAPERDOLL_CLOAK;
  1175. break;
  1176. case L2Item.SLOT_FEET:
  1177. pdollSlot = PAPERDOLL_FEET;
  1178. break;
  1179. case L2Item.SLOT_UNDERWEAR:
  1180. pdollSlot = PAPERDOLL_UNDER;
  1181. break;
  1182. case L2Item.SLOT_L_BRACELET:
  1183. pdollSlot = PAPERDOLL_LBRACELET;
  1184. break;
  1185. case L2Item.SLOT_R_BRACELET:
  1186. pdollSlot = PAPERDOLL_RBRACELET;
  1187. break;
  1188. case L2Item.SLOT_DECO:
  1189. pdollSlot = PAPERDOLL_DECO1;
  1190. break;
  1191. case L2Item.SLOT_BELT:
  1192. pdollSlot = PAPERDOLL_BELT;
  1193. break;
  1194. default:
  1195. _log.info("Unhandled slot type: " + slot);
  1196. _log.info(StringUtil.getTraceString(Thread.currentThread().getStackTrace()));
  1197. }
  1198. if (pdollSlot >= 0)
  1199. {
  1200. L2ItemInstance old = setPaperdollItem(pdollSlot, null);
  1201. if (old != null)
  1202. {
  1203. if (getOwner() instanceof L2PcInstance)
  1204. {
  1205. ((L2PcInstance) getOwner()).refreshExpertisePenalty();
  1206. }
  1207. }
  1208. return old;
  1209. }
  1210. return null;
  1211. }
  1212. /**
  1213. * Equips item and returns list of alterations<BR>
  1214. * <B>If you don't need return value use {@link Inventory#equipItem(L2ItemInstance)} instead</B>
  1215. * @param item : L2ItemInstance corresponding to the item
  1216. * @return L2ItemInstance[] : list of alterations
  1217. */
  1218. public L2ItemInstance[] equipItemAndRecord(L2ItemInstance item)
  1219. {
  1220. Inventory.ChangeRecorder recorder = newRecorder();
  1221. try
  1222. {
  1223. equipItem(item);
  1224. }
  1225. finally
  1226. {
  1227. removePaperdollListener(recorder);
  1228. }
  1229. return recorder.getChangedItems();
  1230. }
  1231. /**
  1232. * Equips item in slot of paperdoll.
  1233. * @param item : L2ItemInstance designating the item and slot used.
  1234. */
  1235. public void equipItem(L2ItemInstance item)
  1236. {
  1237. if ((getOwner() instanceof L2PcInstance) && (((L2PcInstance) getOwner()).getPrivateStoreType() != PrivateStoreType.NONE))
  1238. {
  1239. return;
  1240. }
  1241. if (getOwner() instanceof L2PcInstance)
  1242. {
  1243. L2PcInstance player = (L2PcInstance) getOwner();
  1244. if (!player.canOverrideCond(PcCondOverride.ITEM_CONDITIONS) && !player.isHero() && item.isHeroItem())
  1245. {
  1246. return;
  1247. }
  1248. }
  1249. int targetSlot = item.getItem().getBodyPart();
  1250. // Check if player is using Formal Wear and item isn't Wedding Bouquet.
  1251. L2ItemInstance formal = getPaperdollItem(PAPERDOLL_CHEST);
  1252. if ((item.getId() != 21163) && (formal != null) && (formal.getItem().getBodyPart() == L2Item.SLOT_ALLDRESS))
  1253. {
  1254. // only chest target can pass this
  1255. switch (targetSlot)
  1256. {
  1257. case L2Item.SLOT_LR_HAND:
  1258. case L2Item.SLOT_L_HAND:
  1259. case L2Item.SLOT_R_HAND:
  1260. case L2Item.SLOT_LEGS:
  1261. case L2Item.SLOT_FEET:
  1262. case L2Item.SLOT_GLOVES:
  1263. case L2Item.SLOT_HEAD:
  1264. return;
  1265. }
  1266. }
  1267. switch (targetSlot)
  1268. {
  1269. case L2Item.SLOT_LR_HAND:
  1270. {
  1271. setPaperdollItem(PAPERDOLL_LHAND, null);
  1272. setPaperdollItem(PAPERDOLL_RHAND, item);
  1273. break;
  1274. }
  1275. case L2Item.SLOT_L_HAND:
  1276. {
  1277. L2ItemInstance rh = getPaperdollItem(PAPERDOLL_RHAND);
  1278. if ((rh != null) && (rh.getItem().getBodyPart() == L2Item.SLOT_LR_HAND) && !(((rh.getItemType() == WeaponType.BOW) && (item.getItemType() == EtcItemType.ARROW)) || ((rh.getItemType() == WeaponType.CROSSBOW) && (item.getItemType() == EtcItemType.BOLT)) || ((rh.getItemType() == WeaponType.FISHINGROD) && (item.getItemType() == EtcItemType.LURE))))
  1279. {
  1280. setPaperdollItem(PAPERDOLL_RHAND, null);
  1281. }
  1282. setPaperdollItem(PAPERDOLL_LHAND, item);
  1283. break;
  1284. }
  1285. case L2Item.SLOT_R_HAND:
  1286. {
  1287. // don't care about arrows, listener will unequip them (hopefully)
  1288. setPaperdollItem(PAPERDOLL_RHAND, item);
  1289. break;
  1290. }
  1291. case L2Item.SLOT_L_EAR:
  1292. case L2Item.SLOT_R_EAR:
  1293. case L2Item.SLOT_LR_EAR:
  1294. {
  1295. if (_paperdoll[PAPERDOLL_LEAR] == null)
  1296. {
  1297. setPaperdollItem(PAPERDOLL_LEAR, item);
  1298. }
  1299. else if (_paperdoll[PAPERDOLL_REAR] == null)
  1300. {
  1301. setPaperdollItem(PAPERDOLL_REAR, item);
  1302. }
  1303. else
  1304. {
  1305. setPaperdollItem(PAPERDOLL_LEAR, item);
  1306. }
  1307. break;
  1308. }
  1309. case L2Item.SLOT_L_FINGER:
  1310. case L2Item.SLOT_R_FINGER:
  1311. case L2Item.SLOT_LR_FINGER:
  1312. {
  1313. if (_paperdoll[PAPERDOLL_LFINGER] == null)
  1314. {
  1315. setPaperdollItem(PAPERDOLL_LFINGER, item);
  1316. }
  1317. else if (_paperdoll[PAPERDOLL_RFINGER] == null)
  1318. {
  1319. setPaperdollItem(PAPERDOLL_RFINGER, item);
  1320. }
  1321. else
  1322. {
  1323. setPaperdollItem(PAPERDOLL_LFINGER, item);
  1324. }
  1325. break;
  1326. }
  1327. case L2Item.SLOT_NECK:
  1328. setPaperdollItem(PAPERDOLL_NECK, item);
  1329. break;
  1330. case L2Item.SLOT_FULL_ARMOR:
  1331. setPaperdollItem(PAPERDOLL_LEGS, null);
  1332. setPaperdollItem(PAPERDOLL_CHEST, item);
  1333. break;
  1334. case L2Item.SLOT_CHEST:
  1335. setPaperdollItem(PAPERDOLL_CHEST, item);
  1336. break;
  1337. case L2Item.SLOT_LEGS:
  1338. {
  1339. // handle full armor
  1340. L2ItemInstance chest = getPaperdollItem(PAPERDOLL_CHEST);
  1341. if ((chest != null) && (chest.getItem().getBodyPart() == L2Item.SLOT_FULL_ARMOR))
  1342. {
  1343. setPaperdollItem(PAPERDOLL_CHEST, null);
  1344. }
  1345. setPaperdollItem(PAPERDOLL_LEGS, item);
  1346. break;
  1347. }
  1348. case L2Item.SLOT_FEET:
  1349. setPaperdollItem(PAPERDOLL_FEET, item);
  1350. break;
  1351. case L2Item.SLOT_GLOVES:
  1352. setPaperdollItem(PAPERDOLL_GLOVES, item);
  1353. break;
  1354. case L2Item.SLOT_HEAD:
  1355. setPaperdollItem(PAPERDOLL_HEAD, item);
  1356. break;
  1357. case L2Item.SLOT_HAIR:
  1358. L2ItemInstance hair = getPaperdollItem(PAPERDOLL_HAIR);
  1359. if ((hair != null) && (hair.getItem().getBodyPart() == L2Item.SLOT_HAIRALL))
  1360. {
  1361. setPaperdollItem(PAPERDOLL_HAIR2, null);
  1362. }
  1363. else
  1364. {
  1365. setPaperdollItem(PAPERDOLL_HAIR, null);
  1366. }
  1367. setPaperdollItem(PAPERDOLL_HAIR, item);
  1368. break;
  1369. case L2Item.SLOT_HAIR2:
  1370. L2ItemInstance hair2 = getPaperdollItem(PAPERDOLL_HAIR);
  1371. if ((hair2 != null) && (hair2.getItem().getBodyPart() == L2Item.SLOT_HAIRALL))
  1372. {
  1373. setPaperdollItem(PAPERDOLL_HAIR, null);
  1374. }
  1375. else
  1376. {
  1377. setPaperdollItem(PAPERDOLL_HAIR2, null);
  1378. }
  1379. setPaperdollItem(PAPERDOLL_HAIR2, item);
  1380. break;
  1381. case L2Item.SLOT_HAIRALL:
  1382. setPaperdollItem(PAPERDOLL_HAIR2, null);
  1383. setPaperdollItem(PAPERDOLL_HAIR, item);
  1384. break;
  1385. case L2Item.SLOT_UNDERWEAR:
  1386. setPaperdollItem(PAPERDOLL_UNDER, item);
  1387. break;
  1388. case L2Item.SLOT_BACK:
  1389. setPaperdollItem(PAPERDOLL_CLOAK, item);
  1390. break;
  1391. case L2Item.SLOT_L_BRACELET:
  1392. setPaperdollItem(PAPERDOLL_LBRACELET, item);
  1393. break;
  1394. case L2Item.SLOT_R_BRACELET:
  1395. setPaperdollItem(PAPERDOLL_RBRACELET, item);
  1396. break;
  1397. case L2Item.SLOT_DECO:
  1398. equipTalisman(item);
  1399. break;
  1400. case L2Item.SLOT_BELT:
  1401. setPaperdollItem(PAPERDOLL_BELT, item);
  1402. break;
  1403. case L2Item.SLOT_ALLDRESS:
  1404. // formal dress
  1405. setPaperdollItem(PAPERDOLL_LEGS, null);
  1406. setPaperdollItem(PAPERDOLL_LHAND, null);
  1407. setPaperdollItem(PAPERDOLL_RHAND, null);
  1408. setPaperdollItem(PAPERDOLL_RHAND, null);
  1409. setPaperdollItem(PAPERDOLL_LHAND, null);
  1410. setPaperdollItem(PAPERDOLL_HEAD, null);
  1411. setPaperdollItem(PAPERDOLL_FEET, null);
  1412. setPaperdollItem(PAPERDOLL_GLOVES, null);
  1413. setPaperdollItem(PAPERDOLL_CHEST, item);
  1414. break;
  1415. default:
  1416. _log.warning("Unknown body slot " + targetSlot + " for Item ID:" + item.getId());
  1417. }
  1418. }
  1419. /**
  1420. * Refresh the weight of equipment loaded
  1421. */
  1422. @Override
  1423. protected void refreshWeight()
  1424. {
  1425. long weight = 0;
  1426. for (L2ItemInstance item : _items)
  1427. {
  1428. if ((item != null) && (item.getItem() != null))
  1429. {
  1430. weight += item.getItem().getWeight() * item.getCount();
  1431. }
  1432. }
  1433. _totalWeight = (int) Math.min(weight, Integer.MAX_VALUE);
  1434. }
  1435. /**
  1436. * @return the totalWeight.
  1437. */
  1438. public int getTotalWeight()
  1439. {
  1440. return _totalWeight;
  1441. }
  1442. /**
  1443. * Return the L2ItemInstance of the arrows needed for this bow.
  1444. * @param bow : L2Item designating the bow
  1445. * @return L2ItemInstance pointing out arrows for bow
  1446. */
  1447. public L2ItemInstance findArrowForBow(L2Item bow)
  1448. {
  1449. if (bow == null)
  1450. {
  1451. return null;
  1452. }
  1453. L2ItemInstance arrow = null;
  1454. for (L2ItemInstance item : getItems())
  1455. {
  1456. if (item.isEtcItem() && (item.getItem().getItemGradeSPlus() == bow.getItemGradeSPlus()) && (item.getEtcItem().getItemType() == EtcItemType.ARROW))
  1457. {
  1458. arrow = item;
  1459. break;
  1460. }
  1461. }
  1462. // Get the L2ItemInstance corresponding to the item identifier and return it
  1463. return arrow;
  1464. }
  1465. /**
  1466. * Return the L2ItemInstance of the bolts needed for this crossbow.
  1467. * @param crossbow : L2Item designating the crossbow
  1468. * @return L2ItemInstance pointing out bolts for crossbow
  1469. */
  1470. public L2ItemInstance findBoltForCrossBow(L2Item crossbow)
  1471. {
  1472. L2ItemInstance bolt = null;
  1473. for (L2ItemInstance item : getItems())
  1474. {
  1475. if (item.isEtcItem() && (item.getItem().getItemGradeSPlus() == crossbow.getItemGradeSPlus()) && (item.getEtcItem().getItemType() == EtcItemType.BOLT))
  1476. {
  1477. bolt = item;
  1478. break;
  1479. }
  1480. }
  1481. // Get the L2ItemInstance corresponding to the item identifier and return it
  1482. return bolt;
  1483. }
  1484. /**
  1485. * Get back items in inventory from database
  1486. */
  1487. @Override
  1488. public void restore()
  1489. {
  1490. try (Connection con = ConnectionFactory.getInstance().getConnection();
  1491. PreparedStatement ps = con.prepareStatement("SELECT object_id, item_id, count, enchant_level, loc, loc_data, custom_type1, custom_type2, mana_left, time FROM items WHERE owner_id=? AND (loc=? OR loc=?) ORDER BY loc_data"))
  1492. {
  1493. ps.setInt(1, getOwnerId());
  1494. ps.setString(2, getBaseLocation().name());
  1495. ps.setString(3, getEquipLocation().name());
  1496. try (ResultSet inv = ps.executeQuery())
  1497. {
  1498. L2ItemInstance item;
  1499. while (inv.next())
  1500. {
  1501. item = L2ItemInstance.restoreFromDb(getOwnerId(), inv);
  1502. if (item == null)
  1503. {
  1504. continue;
  1505. }
  1506. if (getOwner() instanceof L2PcInstance)
  1507. {
  1508. L2PcInstance player = (L2PcInstance) getOwner();
  1509. if (!player.canOverrideCond(PcCondOverride.ITEM_CONDITIONS) && !player.isHero() && item.isHeroItem())
  1510. {
  1511. item.setItemLocation(ItemLocation.INVENTORY);
  1512. }
  1513. }
  1514. L2World.getInstance().storeObject(item);
  1515. // If stackable item is found in inventory just add to current quantity
  1516. if (item.isStackable() && (getItemByItemId(item.getId()) != null))
  1517. {
  1518. addItem("Restore", item, getOwner().getActingPlayer(), null);
  1519. }
  1520. else
  1521. {
  1522. addItem(item);
  1523. }
  1524. }
  1525. }
  1526. refreshWeight();
  1527. }
  1528. catch (Exception e)
  1529. {
  1530. _log.log(Level.WARNING, "Could not restore inventory: " + e.getMessage(), e);
  1531. }
  1532. }
  1533. public int getTalismanSlots()
  1534. {
  1535. return getOwner().getActingPlayer().getStat().getTalismanSlots();
  1536. }
  1537. private void equipTalisman(L2ItemInstance item)
  1538. {
  1539. if (getTalismanSlots() == 0)
  1540. {
  1541. return;
  1542. }
  1543. // find same (or incompatible) talisman type
  1544. for (int i = PAPERDOLL_DECO1; i < (PAPERDOLL_DECO1 + getTalismanSlots()); i++)
  1545. {
  1546. if (_paperdoll[i] != null)
  1547. {
  1548. if (getPaperdollItemId(i) == item.getId())
  1549. {
  1550. // overwtite
  1551. setPaperdollItem(i, item);
  1552. return;
  1553. }
  1554. }
  1555. }
  1556. // no free slot found - put on first free
  1557. for (int i = PAPERDOLL_DECO1; i < (PAPERDOLL_DECO1 + getTalismanSlots()); i++)
  1558. {
  1559. if (_paperdoll[i] == null)
  1560. {
  1561. setPaperdollItem(i, item);
  1562. return;
  1563. }
  1564. }
  1565. // no free slots - put on first
  1566. setPaperdollItem(PAPERDOLL_DECO1, item);
  1567. }
  1568. public boolean canEquipCloak()
  1569. {
  1570. return getOwner().getActingPlayer().getStat().canEquipCloak();
  1571. }
  1572. /**
  1573. * Re-notify to paperdoll listeners every equipped item
  1574. */
  1575. public void reloadEquippedItems()
  1576. {
  1577. int slot;
  1578. for (L2ItemInstance item : _paperdoll)
  1579. {
  1580. if (item == null)
  1581. {
  1582. continue;
  1583. }
  1584. slot = item.getLocationSlot();
  1585. for (PaperdollListener listener : _paperdollListeners)
  1586. {
  1587. if (listener == null)
  1588. {
  1589. continue;
  1590. }
  1591. listener.notifyUnequiped(slot, item, this);
  1592. listener.notifyEquiped(slot, item, this);
  1593. }
  1594. }
  1595. }
  1596. }