Inventory.java 49 KB

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