Inventory.java 46 KB

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