PageRenderTime 62ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/GameServer/src/gameserver/model/gameobjects/Item.java

http://aionxemu.googlecode.com/
Java | 690 lines | 427 code | 95 blank | 168 comment | 61 complexity | 424290b73cb333ee09955eadcc9dbc44 MD5 | raw file
Possible License(s): GPL-2.0, Apache-2.0, BSD-2-Clause
  1. /**
  2. * This file is part of Aion X Emu <aionxemu.com>
  3. *
  4. * This is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU Lesser Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This software is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Lesser Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser Public License
  15. * along with this software. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. package gameserver.model.gameobjects;
  18. import gameserver.dataholders.DataManager;
  19. import gameserver.itemengine.actions.ItemActions;
  20. import gameserver.model.gameobjects.player.Player;
  21. import gameserver.model.items.FusionStone;
  22. import gameserver.model.items.GodStone;
  23. import gameserver.model.items.ItemStorage;
  24. import gameserver.model.items.ManaStone;
  25. import gameserver.model.templates.item.EquipType;
  26. import gameserver.model.templates.item.ItemQuality;
  27. import gameserver.model.templates.item.ItemTemplate;
  28. import gameserver.model.templates.item.ItemType;
  29. import gameserver.services.ItemService;
  30. import gameserver.services.RentalService;
  31. import gameserver.world.World;
  32. import org.apache.log4j.Logger;
  33. import java.sql.Timestamp;
  34. import java.util.Comparator;
  35. import java.util.Set;
  36. import java.util.TreeSet;
  37. /**
  38. * @author ATracer
  39. */
  40. public class Item extends AionObject {
  41. private static Logger log = Logger.getLogger(Item.class);
  42. private int itemId;
  43. private long itemCount = 1;
  44. private int itemColor = 0;
  45. private ItemTemplate itemTemplate;
  46. private ItemTemplate itemSkinTemplate;
  47. private boolean isEquipped = false;
  48. private int equipmentSlot = ItemStorage.FIRST_AVAILABLE_SLOT;
  49. private PersistentState persistentState;
  50. private Set<ManaStone> manaStones;
  51. private Set<FusionStone> fusionStones;
  52. private int optionalSocket;
  53. private int optionalFusionSocket;
  54. private GodStone godStone;
  55. private boolean isSoulBound = false;
  56. private int itemLocation;
  57. private int enchantLevel;
  58. private String itemCreator;
  59. private int fusionedItemId = 0;
  60. private Timestamp expireTime = null;
  61. /**
  62. * @param objId
  63. * @param itemId
  64. * @param itemTemplate
  65. * @param itemCount
  66. * @param itemCreator
  67. * @param isEquipped
  68. * @param equipmentSlot This constructor should be called from ItemService
  69. * for newly created items and loadedFromDb
  70. */
  71. public Item(int objId, int itemId, ItemTemplate itemTemplate, long itemCount,
  72. String itemCreator, boolean isEquipped, int equipmentSlot)
  73. {
  74. super(objId);
  75. this.itemId = itemId;
  76. this.itemTemplate = itemTemplate;
  77. this.itemCount = itemCount;
  78. this.itemCreator = itemCreator;
  79. this.isEquipped = isEquipped;
  80. this.equipmentSlot = equipmentSlot;
  81. if(itemTemplate.getExpireMinutes() > 0)
  82. this.expireTime = new Timestamp(System.currentTimeMillis() + itemTemplate.getExpireMinutes() * 60 * 1000);
  83. this.persistentState = PersistentState.NEW;
  84. }
  85. /**
  86. * @param objId
  87. * @param itemId
  88. * @param itemCount
  89. * @param itemColor
  90. * @param itemCreator
  91. * @param isEquipped
  92. * @param isSoulBound
  93. * @param equipmentSlot
  94. * @param itemLocation
  95. * @param enchant
  96. * @param itemSkin
  97. * @param fusionedItem
  98. * @param optionalSocket
  99. * @param optionalFusionSocket
  100. *
  101. * This constructor should be called only from DAO while loading from DB.
  102. */
  103. public Item(int objId, int itemId, long itemCount, int itemColor,
  104. String itemCreator, boolean isEquipped, boolean isSoulBound,
  105. int equipmentSlot, int itemLocation, int enchant, int itemSkin,
  106. int fusionedItem, int optionalSocket, int optionalFusionSocket, Timestamp expireTime)
  107. {
  108. super(objId);
  109. this.itemTemplate = DataManager.ITEM_DATA.getItemTemplate(itemId);
  110. this.itemId = itemId;
  111. this.itemCount = itemCount;
  112. this.itemColor = itemColor;
  113. this.itemCreator = itemCreator;
  114. this.isEquipped = isEquipped;
  115. this.isSoulBound = isSoulBound;
  116. this.equipmentSlot = equipmentSlot;
  117. this.itemLocation = itemLocation;
  118. this.enchantLevel = enchant;
  119. this.fusionedItemId = fusionedItem;
  120. this.itemSkinTemplate = DataManager.ITEM_DATA.getItemTemplate(itemSkin);
  121. this.optionalSocket = optionalSocket;
  122. this.optionalFusionSocket = optionalFusionSocket;
  123. this.expireTime = expireTime;
  124. }
  125. @Override
  126. public String getName() {
  127. //TODO
  128. //item description should return probably string and not id
  129. return String.valueOf(itemTemplate.getNameId());
  130. }
  131. public String getItemName() {
  132. return itemTemplate.getName();
  133. }
  134. public int getOptionalSocket() {
  135. return optionalSocket;
  136. }
  137. public boolean hasOptionalSocket() {
  138. if (optionalSocket == 0)
  139. return false;
  140. return true;
  141. }
  142. public void setOptionalSocket(int optionalSocket) {
  143. this.optionalSocket = optionalSocket;
  144. }
  145. public int getOptionalFusionSocket() {
  146. return optionalFusionSocket;
  147. }
  148. public boolean hasOptionalFusionSocket() {
  149. if (optionalFusionSocket == 0)
  150. return false;
  151. return true;
  152. }
  153. public void setOptionalFusionSocket(int optionalFusionSocket) {
  154. this.optionalFusionSocket = optionalFusionSocket;
  155. }
  156. /**
  157. * @return the itemTemplate
  158. */
  159. public ItemTemplate getItemTemplate() {
  160. if (itemTemplate == null)
  161. log.warn("Item was not populated correctly. Item template is missing" +
  162. ", ItemObjectId: " + getObjectId() +
  163. ", ItemId: " + itemId);
  164. return itemTemplate;
  165. }
  166. /**
  167. * @return the itemAppearanceTemplate
  168. */
  169. public ItemTemplate getItemSkinTemplate() {
  170. if (this.itemSkinTemplate == null)
  171. return this.itemTemplate;
  172. return this.itemSkinTemplate;
  173. }
  174. public void setItemSkinTemplate(ItemTemplate newTemplate) {
  175. this.itemSkinTemplate = newTemplate;
  176. setPersistentState(PersistentState.UPDATE_REQUIRED);
  177. }
  178. /**
  179. * @return the itemColor
  180. */
  181. public int getItemColor() {
  182. return itemColor;
  183. }
  184. /**
  185. * @param itemColor the itemColor to set
  186. */
  187. public void setItemColor(int itemColor) {
  188. this.itemColor = itemColor;
  189. setPersistentState(PersistentState.UPDATE_REQUIRED);
  190. }
  191. /**
  192. * @param itemTemplate the itemTemplate to set
  193. */
  194. public void setItemTemplate(ItemTemplate itemTemplate) {
  195. this.itemTemplate = itemTemplate;
  196. }
  197. /**
  198. * @return the itemCount
  199. * Number of this item in stack. Should be not more than template maxstackcount ?
  200. */
  201. public long getItemCount() {
  202. return itemCount;
  203. }
  204. /**
  205. * @param itemCount the itemCount to set
  206. */
  207. public void setItemCount(long itemCount) {
  208. this.itemCount = itemCount;
  209. setPersistentState(PersistentState.UPDATE_REQUIRED);
  210. }
  211. /**
  212. * This method should be called ONLY from Storage class
  213. * In all other ways it is not guaranteed to be updated in a regular update service
  214. * It is allowed to use this method for newly created items which are not yet in any storage
  215. *
  216. * @param addCount
  217. */
  218. public void increaseItemCount(long addCount) {
  219. if(this.itemCount > 0 && this.itemCount+addCount < 0)
  220. this.itemCount = Long.MAX_VALUE;
  221. else
  222. this.itemCount += addCount;
  223. setPersistentState(PersistentState.UPDATE_REQUIRED);
  224. }
  225. /**
  226. * This method should be called ONLY from Storage class
  227. * In all other ways it is not guaranteed to be updated in a regular update service
  228. * It is allowed to use this method for newly created items which are not yet in any storage
  229. *
  230. * @param remCount
  231. */
  232. public boolean decreaseItemCount(long remCount) {
  233. if (this.itemCount - remCount >= 0) {
  234. this.itemCount -= remCount;
  235. if (itemCount == 0 && !this.itemTemplate.isKinah()) {
  236. setPersistentState(PersistentState.DELETED);
  237. } else {
  238. setPersistentState(PersistentState.UPDATE_REQUIRED);
  239. }
  240. return true;
  241. }
  242. return false;
  243. }
  244. public boolean isReadable() {
  245. ItemActions actions = this.getItemTemplate().getActions();
  246. return actions != null && actions.getReadActions().size() > 0;
  247. }
  248. public boolean canStartQuest() {
  249. ItemActions actions = this.getItemTemplate().getActions();
  250. return actions != null && actions.getQuestStartActions().size() > 0;
  251. }
  252. /**
  253. * @return the isEquipped
  254. */
  255. public boolean isEquipped() {
  256. return isEquipped;
  257. }
  258. /**
  259. * @param isEquipped the isEquipped to set
  260. */
  261. public void setEquipped(boolean isEquipped) {
  262. this.isEquipped = isEquipped;
  263. setPersistentState(PersistentState.UPDATE_REQUIRED);
  264. }
  265. /**
  266. * @return the equipmentSlot
  267. * Equipment slot can be of 2 types - one is the ItemSlot enum type if equipped, second - is position in cube
  268. */
  269. public int getEquipmentSlot() {
  270. return equipmentSlot;
  271. }
  272. /**
  273. * @param equipmentSlot the equipmentSlot to set
  274. */
  275. public void setEquipmentSlot(int equipmentSlot) {
  276. this.equipmentSlot = equipmentSlot;
  277. setPersistentState(PersistentState.UPDATE_REQUIRED);
  278. }
  279. /**
  280. * This method should be used to lazy initialize empty manastone list
  281. *
  282. * @return the itemStones
  283. */
  284. public Set<ManaStone> getItemStones() {
  285. if (manaStones == null)
  286. this.manaStones = new TreeSet<ManaStone>(new Comparator<ManaStone>() {
  287. @Override
  288. public int compare(ManaStone o1, ManaStone o2) {
  289. if (o1.getSlot() == o2.getSlot())
  290. return 0;
  291. return o1.getSlot() > o2.getSlot() ? 1 : -1;
  292. }
  293. });
  294. return manaStones;
  295. }
  296. /**
  297. * This method should be used to lazy initialize empty manastone list
  298. *
  299. * @return the itemStones
  300. */
  301. public Set<FusionStone> getFusionStones() {
  302. if (fusionStones == null)
  303. this.fusionStones = new TreeSet<FusionStone>(new Comparator<FusionStone>() {
  304. @Override
  305. public int compare(FusionStone o1, FusionStone o2) {
  306. if (o1.getSlot() == o2.getSlot())
  307. return 0;
  308. return o1.getSlot() > o2.getSlot() ? 1 : -1;
  309. }
  310. });
  311. return fusionStones;
  312. }
  313. /**
  314. * Check manastones without initialization
  315. *
  316. * @return
  317. */
  318. public boolean hasManaStones() {
  319. return manaStones != null && manaStones.size() > 0;
  320. }
  321. /**
  322. * Check manastones without initialization
  323. *
  324. * @return
  325. */
  326. public boolean hasFusionStones() {
  327. return fusionStones != null && fusionStones.size() > 0;
  328. }
  329. /**
  330. * @return the goodStone
  331. */
  332. public GodStone getGodStone() {
  333. return godStone;
  334. }
  335. /**
  336. * @param itemId
  337. * @return
  338. */
  339. public GodStone addGodStone(int itemId) {
  340. PersistentState state = this.godStone != null ? PersistentState.UPDATE_REQUIRED : PersistentState.NEW;
  341. this.godStone = new GodStone(getObjectId(), itemId, state);
  342. return this.godStone;
  343. }
  344. /**
  345. * @param goodStone the goodStone to set
  346. */
  347. public void setGoodStone(GodStone goodStone) {
  348. this.godStone = goodStone;
  349. }
  350. /**
  351. * @return the echantLevel
  352. */
  353. public int getEnchantLevel() {
  354. return enchantLevel;
  355. }
  356. /**
  357. * @param enchantLevel the echantLevel to set
  358. */
  359. public void setEnchantLevel(int enchantLevel) {
  360. if (enchantLevel > 127)
  361. enchantLevel = 127;
  362. this.enchantLevel = enchantLevel;
  363. setPersistentState(PersistentState.UPDATE_REQUIRED);
  364. }
  365. /**
  366. * @return the persistentState
  367. */
  368. public PersistentState getPersistentState() {
  369. return persistentState;
  370. }
  371. /**
  372. * Possible changes:
  373. * NEW -> UPDATED
  374. * NEW -> UPDATE_REQURIED
  375. * UPDATE_REQUIRED -> DELETED
  376. * UPDATE_REQUIRED -> UPDATED
  377. * UPDATED -> DELETED
  378. * UPDATED -> UPDATE_REQUIRED
  379. *
  380. * @param persistentState the persistentState to set
  381. */
  382. public void setPersistentState(PersistentState persistentState) {
  383. switch (persistentState) {
  384. case DELETED:
  385. if (this.persistentState == PersistentState.NEW) {
  386. this.persistentState = PersistentState.NOACTION;
  387. ItemService.releaseItemId(this);
  388. } else
  389. this.persistentState = PersistentState.DELETED;
  390. break;
  391. case UPDATE_REQUIRED:
  392. if (this.persistentState == PersistentState.NEW)
  393. break;
  394. default:
  395. this.persistentState = persistentState;
  396. }
  397. }
  398. public void setItemLocation(int storageType) {
  399. this.itemLocation = storageType;
  400. setPersistentState(PersistentState.UPDATE_REQUIRED);
  401. }
  402. public int getItemLocation() {
  403. return itemLocation;
  404. }
  405. public int getItemMask() {
  406. return itemTemplate.getMask();
  407. }
  408. public boolean isSoulBound() {
  409. return isSoulBound;
  410. }
  411. public void setSoulBound(boolean isSoulBound) {
  412. this.isSoulBound = isSoulBound;
  413. setPersistentState(PersistentState.UPDATE_REQUIRED);
  414. }
  415. public EquipType getEquipmentType() {
  416. if (itemTemplate.isStigma())
  417. return EquipType.STIGMA;
  418. else
  419. return itemTemplate.getEquipmentType();
  420. }
  421. @Override
  422. public String toString() {
  423. return "Item [equipmentSlot=" + equipmentSlot + ", godStone=" + godStone + ", isEquipped=" + isEquipped
  424. + ", itemColor=" + itemColor + ", itemCount=" + itemCount + ", itemLocation="
  425. + itemLocation + ", itemTemplate=" + itemTemplate + ", manaStones=" + manaStones + ", persistentState="
  426. + persistentState + "]";
  427. }
  428. public int getItemId() {
  429. return itemTemplate.getTemplateId();
  430. }
  431. public int getNameID() {
  432. return itemTemplate.getNameId();
  433. }
  434. public boolean hasFusionedItem() {
  435. return (fusionedItemId != 0);
  436. }
  437. public int getFusionedItem() {
  438. return fusionedItemId;
  439. }
  440. public void setFusionedItem(int itemTemplateId) {
  441. fusionedItemId = itemTemplateId;
  442. }
  443. private static int basicSocket(ItemQuality rarity) {
  444. switch (rarity) {
  445. case COMMON:
  446. return 1;
  447. case RARE:
  448. return 2;
  449. case LEGEND:
  450. return 3;
  451. case UNIQUE:
  452. return 4;
  453. case EPIC:
  454. return 5;
  455. default:
  456. return 1;
  457. }
  458. }
  459. private static int extendedSocket(ItemType type) {
  460. switch (type) {
  461. case NORMAL:
  462. return 0;
  463. case ABYSS:
  464. return 2;
  465. case DRACONIC:
  466. return 0;
  467. case DEVANION:
  468. return 0;
  469. default:
  470. return 0;
  471. }
  472. }
  473. public int getSockets(boolean isFusionItem) {
  474. int numSockets;
  475. if (itemTemplate.isWeapon() || itemTemplate.isArmor()) {
  476. if (isFusionItem) {
  477. ItemTemplate fusedTemp = DataManager.ITEM_DATA.getItemTemplate(getFusionedItem());
  478. numSockets = basicSocket(fusedTemp.getItemQuality());
  479. numSockets += extendedSocket(fusedTemp.getItemType());
  480. numSockets += hasOptionalFusionSocket() ? getOptionalFusionSocket() : 0;
  481. } else {
  482. numSockets = basicSocket(getItemTemplate().getItemQuality());
  483. numSockets += extendedSocket(getItemTemplate().getItemType());
  484. numSockets += hasOptionalSocket() ? getOptionalSocket() : 0;
  485. }
  486. if (numSockets < 6)
  487. return numSockets;
  488. return 6;
  489. }
  490. return 0;
  491. }
  492. public boolean isStorable(int storageType) {
  493. switch (storageType) {
  494. case 0:
  495. return true;
  496. case 1://regular warehouse
  497. if (this.getItemTemplate().isStorableinCharWarehouse())
  498. return true;
  499. break;
  500. case 2://account warehouse
  501. if (this.getItemTemplate().isStorableinAccWarehouse())
  502. return true;
  503. break;
  504. case 3://legion warehouse
  505. if (this.getItemTemplate().isStorableinLegionWarehouse())
  506. return true;
  507. break;
  508. }
  509. return false;
  510. }
  511. /**
  512. * Tests whether the Item is a weapon and has been swapped into the
  513. * non-active hand slot for a given Player.
  514. *
  515. * @param player
  516. * @return Weapon Swapped Outcome.
  517. */
  518. public boolean isWeaponSwapped(final Player player)
  519. {
  520. // Does not add weapon stats if the weapon has been swapped.
  521. if (itemTemplate.isArmor())
  522. return false;
  523. if (itemTemplate.isWeapon() &&
  524. (this == player.getEquipment().getMainHandWeapon() ||
  525. this == player.getEquipment().getOffHandWeapon()))
  526. {
  527. return false;
  528. }
  529. return true;
  530. }
  531. public int getMaxStoneSlots()
  532. {
  533. int slots = 0;
  534. switch(itemTemplate.getItemQuality())
  535. {
  536. case COMMON:
  537. case JUNK:
  538. slots = 1;
  539. break;
  540. case RARE:
  541. slots = 2;
  542. break;
  543. case LEGEND:
  544. slots = 3;
  545. break;
  546. case UNIQUE:
  547. slots = 4;
  548. break;
  549. case EPIC:
  550. slots = 5;
  551. break;
  552. default:
  553. slots = 0;
  554. break;
  555. }
  556. if(itemTemplate.getItemType() == ItemType.DRACONIC)
  557. slots += 1;
  558. if(itemTemplate.getItemType() == ItemType.ABYSS)
  559. slots += 2;
  560. slots += optionalSocket;
  561. if(slots > 6)
  562. slots = 6;
  563. return slots;
  564. }
  565. /**
  566. * @param return itemCreator
  567. */
  568. public String getItemCreator()
  569. {
  570. return itemCreator;
  571. }
  572. /**
  573. * @param itemCreator the itemCreator to set
  574. */
  575. public void setItemCreator(String itemCreator)
  576. {
  577. this.itemCreator = itemCreator;
  578. setPersistentState(PersistentState.UPDATE_REQUIRED);
  579. }
  580. /**
  581. * @param expireTime the expireTime to set
  582. */
  583. public void setExpireTime(Timestamp expireTime)
  584. {
  585. this.expireTime = expireTime;
  586. setPersistentState(PersistentState.UPDATE_REQUIRED);
  587. }
  588. /**
  589. * @return the expireTime
  590. */
  591. public Timestamp getExpireTime()
  592. {
  593. return expireTime;
  594. }
  595. }