MercTicketManager.java 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  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 net.sf.l2j.gameserver.instancemanager;
  16. import java.sql.PreparedStatement;
  17. import java.sql.ResultSet;
  18. import java.util.List;
  19. import java.util.logging.Logger;
  20. import javolution.util.FastList;
  21. import net.sf.l2j.L2DatabaseFactory;
  22. import net.sf.l2j.gameserver.ThreadPoolManager;
  23. import net.sf.l2j.gameserver.datatables.NpcTable;
  24. import net.sf.l2j.gameserver.idfactory.IdFactory;
  25. import net.sf.l2j.gameserver.model.AutoChatHandler;
  26. import net.sf.l2j.gameserver.model.L2ItemInstance;
  27. import net.sf.l2j.gameserver.model.L2World;
  28. import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
  29. import net.sf.l2j.gameserver.model.actor.instance.L2SiegeGuardInstance;
  30. import net.sf.l2j.gameserver.model.entity.Castle;
  31. import net.sf.l2j.gameserver.templates.L2NpcTemplate;
  32. /**
  33. * @author yellowperil & Fulminus
  34. * This class is similar to the SiegeGuardManager, except it handles
  35. * the loading of the mercenary tickets that are dropped on castle floors
  36. * by the castle lords.
  37. * These tickets (aka badges) need to be readded after each server reboot
  38. * except when the server crashed in the middle of an ongoig siege.
  39. * In addition, this class keeps track of the added tickets, in order to
  40. * properly limit the number of mercenaries in each castle and the
  41. * number of mercenaries from each mercenary type.
  42. * Finally, we provide auxilary functions to identify the castle in
  43. * which each item (and its corresponding NPC) belong to, in order to
  44. * help avoid mixing them up.
  45. *
  46. */
  47. public class MercTicketManager
  48. {
  49. protected static final Logger _log = Logger.getLogger(CastleManager.class.getName());
  50. // =========================================================
  51. private static MercTicketManager _instance;
  52. public static final MercTicketManager getInstance()
  53. {
  54. //CastleManager.getInstance();
  55. if (_instance == null)
  56. {
  57. _log.info("Initializing MercTicketManager");
  58. _instance = new MercTicketManager();
  59. _instance.load();
  60. }
  61. return _instance;
  62. }
  63. // =========================================================
  64. // =========================================================
  65. // Data Field
  66. private List<L2ItemInstance> _droppedTickets; // to keep track of items on the ground
  67. //TODO move all these values into siege.properties
  68. // max tickets per merc type = 10 + (castleid * 2)?
  69. // max ticker per castle = 40 + (castleid * 20)?
  70. private static final int[] MAX_MERC_PER_TYPE = {
  71. 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, // Gludio
  72. 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, // Dion
  73. 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, // Giran
  74. 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, // Oren
  75. 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // Aden
  76. 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // Innadril
  77. 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // Goddard
  78. 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // Rune
  79. 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 // Schuttgart
  80. };
  81. private static final int[] MERCS_MAX_PER_CASTLE = {
  82. 100, // Gludio
  83. 150, // Dion
  84. 200, // Giran
  85. 300, // Oren
  86. 400, // Aden
  87. 400, // Innadril
  88. 400, // Goddard
  89. 400, // Rune
  90. 400 // Schuttgart
  91. };
  92. private static final int[] ITEM_IDS = {
  93. 3960, 3961, 3962, 3963, 3964, 3965, 3966, 3967, 3968, 3969, 6115, 6116, 6117, 6118, 6119, 6120, 6121, 6122, 6123, 6124, 6038, 6039, 6040, 6041, 6042, 6043, 6044, 6045, 6046, 6047, 6175, 6176, 6177, 6178, 6179, 6180, 6181, 6182, 6183, 6184, 6235, 6236, 6237, 6238, 6239, 6240, 6241, 6242, 6243, 6244, 6295, 6296, // Gludio
  94. 3973, 3974, 3975, 3976, 3977, 3978, 3979, 3980, 3981, 3982, 6125, 6126, 6127, 6128, 6129, 6130, 6131, 6132, 6133, 6134, 6051, 6052, 6053, 6054, 6055, 6056, 6057, 6058, 6059, 6060, 6185, 6186, 6187, 6188, 6189, 6190, 6191, 6192, 6193, 6194, 6245, 6246, 6247, 6248, 6249, 6250, 6251, 6252, 6253, 6254, 6297, 6298, // Dion
  95. 3986, 3987, 3988, 3989, 3990, 3991, 3992, 3993, 3994, 3995, 6135, 6136, 6137, 6138, 6139, 6140, 6141, 6142, 6143, 6144, 6064, 6065, 6066, 6067, 6068, 6069, 6070, 6071, 6072, 6073, 6195, 6196, 6197, 6198, 6199, 6200, 6201, 6202, 6203, 6204, 6255, 6256, 6257, 6258, 6259, 6260, 6261, 6262, 6263, 6264, 6299, 6300, // Giran
  96. 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 6145, 6146, 6147, 6148, 6149, 6150, 6151, 6152, 6153, 6154, 6077, 6078, 6079, 6080, 6081, 6082, 6083, 6084, 6085, 6086, 6205, 6206, 6207, 6208, 6209, 6210, 6211, 6212, 6213, 6214, 6265, 6266, 6267, 6268, 6269, 6270, 6271, 6272, 6273, 6274, 6301, 6302, // Oren
  97. 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 6155, 6156, 6157, 6158, 6159, 6160, 6161, 6162, 6163, 6164, 6090, 6091, 6092, 6093, 6094, 6095, 6096, 6097, 6098, 6099, 6215, 6216, 6217, 6218, 6219, 6220, 6221, 6222, 6223, 6224, 6275, 6276, 6277, 6278, 6279, 6280, 6281, 6282, 6283, 6284, 6303, 6304, // Aden
  98. 5205, 5206, 5207, 5208, 5209, 5210, 5211, 5212, 5213, 5214, 6165, 6166, 6167, 6168, 6169, 6170, 6171, 6172, 6173, 6174, 6105, 6106, 6107, 6108, 6109, 6110, 6111, 6112, 6113, 6114, 6225, 6226, 6227, 6228, 6229, 6230, 6231, 6232, 6233, 6234, 6285, 6286, 6287, 6288, 6289, 6290, 6291, 6292, 6293, 6294, 6305, 6306, // Innadril
  99. 6779, 6780, 6781, 6782, 6783, 6784, 6785, 6786, 6787, 6788, 6802, 6803, 6804, 6805, 6806, 6807, 6808, 6809, 6810, 6811, 6792, 6793, 6794, 6795, 6796, 6797, 6798, 6799, 6800, 6801, 6812, 6813, 6814, 6815, 6816, 6817, 6818, 6819, 6820, 6821, 6822, 6823, 6824, 6825, 6826, 6827, 6828, 6829, 6830, 6831, 6832, 6833, // Goddard
  100. 7973, 7974, 7975, 7976, 7977, 7978, 7979, 7980, 7981, 7982, 7998, 7999, 8000, 8001, 8002, 8003, 8004, 8005, 8006, 8007, 7988, 7989, 7990, 7991, 7992, 7993, 7994, 7995, 7996, 7997, 8008, 8009, 8010, 8011, 8012, 8013, 8014, 8015, 8016, 8017, 8018, 8019, 8020, 8021, 8022, 8023, 8024, 8025, 8026, 8027, 8028, 8029, // Rune
  101. 7918, 7919, 7920, 7921, 7922, 7923, 7924, 7925, 7926, 7927, 7941, 7942, 7943, 7944, 7945, 7946, 7947, 7948, 7949, 7950, 7931, 7932, 7933, 7934, 7935, 7936, 7937, 7938, 7939, 7940, 7951, 7952, 7953, 7954, 7955, 7956, 7957, 7958, 7959, 7960, 7961, 7962, 7963, 7964, 7965, 7966, 7967, 7968, 7969, 7970, 7971, 7972 // Schuttgart
  102. };
  103. private static final int[] NPC_IDS = {
  104. 35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 3502, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Gludio
  105. 35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 3502, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Dion
  106. 35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 3502, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Giran
  107. 35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 3502, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Oren
  108. 35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 3502, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Aden
  109. 35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 3502, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Innadril
  110. 35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 3502, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Goddard
  111. 35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 3502, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Rune
  112. 35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 3502, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Schuttgart
  113. };
  114. // =========================================================
  115. // Constructor
  116. public MercTicketManager()
  117. {
  118. }
  119. // =========================================================
  120. // Method - Public
  121. // returns the castleId for the passed ticket item id
  122. public int getTicketCastleId(int itemId)
  123. {
  124. int GUARDIAN_TYPES_COUNT = 52;
  125. for (int i = 0; i < 9; i++) //CastleID`s from 1 to 9 minus;
  126. {
  127. for (int i2 = 0; i2 < 50; i2 += 10) //Simplified if statement;
  128. if ((itemId >= ITEM_IDS[i2 + i*GUARDIAN_TYPES_COUNT] && itemId <= ITEM_IDS[i2 + 9 + i*GUARDIAN_TYPES_COUNT]))
  129. return i + 1;
  130. if (itemId >= ITEM_IDS[50] && itemId <= ITEM_IDS[51])
  131. return i + 1;
  132. }
  133. return -1;
  134. }
  135. public void reload()
  136. {
  137. getDroppedTickets().clear();
  138. load();
  139. }
  140. // =========================================================
  141. // Method - Private
  142. private final void load()
  143. {
  144. java.sql.Connection con = null;
  145. // load merc tickets into the world
  146. try
  147. {
  148. PreparedStatement statement;
  149. ResultSet rs;
  150. con = L2DatabaseFactory.getInstance().getConnection();
  151. statement = con.prepareStatement("SELECT * FROM castle_siege_guards Where isHired = 1");
  152. rs = statement.executeQuery();
  153. int npcId;
  154. int itemId;
  155. int x,y,z;
  156. int mercPlaced[] = new int[20];
  157. // start index to begin the search for the itemId corresponding to this NPC
  158. // this will help with:
  159. // a) skip unnecessary iterations in the search loop
  160. // b) avoid finding the wrong itemId whenever tickets of different spawn the same npc!
  161. int startindex = 0;
  162. while (rs.next())
  163. {
  164. npcId = rs.getInt("npcId");
  165. x = rs.getInt("x");
  166. y = rs.getInt("y");
  167. z = rs.getInt("z");
  168. Castle castle = CastleManager.getInstance().getCastle(x,y,z);
  169. if(castle != null)
  170. {
  171. startindex = 20*(castle.getCastleId()-1);
  172. mercPlaced[castle.getCastleId()-1] += 1;
  173. if (mercPlaced[castle.getCastleId()-1] > MERCS_MAX_PER_CASTLE[castle.getCastleId()-1])
  174. break;
  175. }
  176. // find the FIRST ticket itemId with spawns the saved NPC in the saved location
  177. for (int i=startindex;i<NPC_IDS.length;i++)
  178. if (NPC_IDS[i] == npcId) // Find the index of the item used
  179. {
  180. // only handle tickets if a siege is not ongoing in this npc's castle
  181. if((castle != null) && !(castle.getSiege().getIsInProgress()))
  182. {
  183. itemId = ITEM_IDS[i];
  184. // create the ticket in the gameworld
  185. L2ItemInstance dropticket = new L2ItemInstance(IdFactory.getInstance().getNextId(), itemId);
  186. dropticket.setLocation(L2ItemInstance.ItemLocation.INVENTORY);
  187. dropticket.dropMe(null, x, y, z);
  188. dropticket.setDropTime(0); //avoids it from beeing removed by the auto item destroyer
  189. L2World.getInstance().storeObject(dropticket);
  190. getDroppedTickets().add(dropticket);
  191. }
  192. break;
  193. }
  194. }
  195. statement.close();
  196. _log.info("Loaded: " + getDroppedTickets().size() + " Mercenary Tickets");
  197. }
  198. catch (Exception e)
  199. {
  200. _log.warning("Exception: loadMercenaryData(): " + e.getMessage());
  201. e.printStackTrace();
  202. }
  203. finally {try { con.close(); } catch (Exception e) {}}
  204. }
  205. // =========================================================
  206. // Property - Public
  207. /**
  208. * Checks if the passed item has reached the limit of number of dropped
  209. * tickets that this SPECIFIC item may have in its castle
  210. */
  211. public boolean isAtTypeLimit(int itemId)
  212. {
  213. int limit = -1;
  214. // find the max value for this item
  215. for (int i=0;i<ITEM_IDS.length;i++)
  216. if (ITEM_IDS[i] == itemId) // Find the index of the item used
  217. {
  218. limit = MAX_MERC_PER_TYPE[i];
  219. break;
  220. }
  221. if (limit <= 0)
  222. return true;
  223. int count = 0;
  224. L2ItemInstance ticket;
  225. for(int i=0; i<getDroppedTickets().size(); i++)
  226. {
  227. ticket = getDroppedTickets().get(i);
  228. if ( ticket != null && ticket.getItemId() == itemId)
  229. count++;
  230. }
  231. if(count >= limit)
  232. return true;
  233. return false;
  234. }
  235. /**
  236. * Checks if the passed item belongs to a castle which has reached its limit
  237. * of number of dropped tickets.
  238. */
  239. public boolean isAtCasleLimit(int itemId)
  240. {
  241. int castleId = getTicketCastleId(itemId);
  242. if (castleId <= 0)
  243. return true;
  244. int limit = MERCS_MAX_PER_CASTLE[castleId-1];
  245. if (limit <= 0)
  246. return true;
  247. int count = 0;
  248. L2ItemInstance ticket;
  249. for(int i=0; i<getDroppedTickets().size(); i++)
  250. {
  251. ticket = getDroppedTickets().get(i);
  252. if ( (ticket != null) && (getTicketCastleId(ticket.getItemId()) == castleId) )
  253. count++;
  254. }
  255. if(count >= limit)
  256. return true;
  257. return false;
  258. }
  259. public int getMaxAllowedMerc(int castleId)
  260. {
  261. return MERCS_MAX_PER_CASTLE[castleId-1];
  262. }
  263. public boolean isTooCloseToAnotherTicket(int x, int y, int z)
  264. {
  265. for (L2ItemInstance item : getDroppedTickets())
  266. {
  267. double dx = x - item.getX();
  268. double dy = y - item.getY();
  269. double dz = z - item.getZ();
  270. if ((dx*dx + dy*dy + dz*dz) < 25*25) return true;
  271. }
  272. return false;
  273. }
  274. /**
  275. * addTicket actions
  276. * 1) find the npc that needs to be saved in the mercenary spawns, given this item
  277. * 2) Use the passed character's location info to add the spawn
  278. * 3) create a copy of the item to drop in the world
  279. * returns the id of the mercenary npc that was added to the spawn
  280. * returns -1 if this fails.
  281. */
  282. public int addTicket(int itemId, L2PcInstance activeChar, String[] messages)
  283. {
  284. int x = activeChar.getX();
  285. int y = activeChar.getY();
  286. int z = activeChar.getZ();
  287. int heading = activeChar.getHeading();
  288. Castle castle = CastleManager.getInstance().getCastle(activeChar);
  289. if (castle == null) //this should never happen at this point
  290. return -1;
  291. for (int i = 0; i < ITEM_IDS.length; i++)
  292. {
  293. if (ITEM_IDS[i] == itemId) // Find the index of the item used
  294. {
  295. spawnMercenary(NPC_IDS[i], x, y, z, 3000, messages, 0);
  296. // Hire merc for this caslte. NpcId is at the same index as the item used.
  297. castle.getSiege().getSiegeGuardManager().hireMerc(x, y, z, heading, NPC_IDS[i]);
  298. // create the ticket in the gameworld
  299. L2ItemInstance dropticket = new L2ItemInstance(IdFactory.getInstance().getNextId(), itemId);
  300. dropticket.setLocation(L2ItemInstance.ItemLocation.INVENTORY);
  301. dropticket.dropMe(null, x, y, z);
  302. dropticket.setDropTime(0); //avoids it from beeing removed by the auto item destroyer
  303. L2World.getInstance().storeObject(dropticket); //add to the world
  304. // and keep track of this ticket in the list
  305. _droppedTickets.add(dropticket);
  306. return NPC_IDS[i];
  307. }
  308. }
  309. return -1;
  310. }
  311. private void spawnMercenary(int npcId, int x, int y, int z, int despawnDelay, String[] messages, int chatDelay)
  312. {
  313. L2NpcTemplate template = NpcTable.getInstance().getTemplate(npcId);
  314. if (template != null)
  315. {
  316. final L2SiegeGuardInstance npc = new L2SiegeGuardInstance(IdFactory.getInstance().getNextId(), template);
  317. npc.setCurrentHpMp(npc.getMaxHp(), npc.getMaxMp());
  318. npc.setDecayed(false);
  319. npc.spawnMe(x, y, (z+20));
  320. if (messages != null && messages.length >0 )
  321. AutoChatHandler.getInstance().registerChat(npc, messages, chatDelay);
  322. if (despawnDelay > 0)
  323. {
  324. ThreadPoolManager.getInstance().scheduleGeneral(new Runnable() {
  325. public void run()
  326. {
  327. npc.deleteMe();
  328. }
  329. }, despawnDelay);
  330. }
  331. }
  332. }
  333. /**
  334. * Delete all tickets from a castle;
  335. * remove the items from the world and remove references to them from this class
  336. */
  337. public void deleteTickets(int castleId)
  338. {
  339. int i = 0;
  340. while ( i<getDroppedTickets().size() )
  341. {
  342. L2ItemInstance item = getDroppedTickets().get(i);
  343. if ((item != null) && (getTicketCastleId(item.getItemId()) == castleId))
  344. {
  345. item.decayMe();
  346. L2World.getInstance().removeObject(item);
  347. // remove from the list
  348. getDroppedTickets().remove(i);
  349. }
  350. else
  351. i++;
  352. }
  353. }
  354. /**
  355. * remove a single ticket and its associated spawn from the world
  356. * (used when the castle lord picks up a ticket, for example)
  357. */
  358. public void removeTicket(L2ItemInstance item)
  359. {
  360. int itemId = item.getItemId();
  361. int npcId = -1;
  362. // find the FIRST ticket itemId with spawns the saved NPC in the saved location
  363. for (int i=0;i<ITEM_IDS.length;i++)
  364. if (ITEM_IDS[i] == itemId) // Find the index of the item used
  365. {
  366. npcId = NPC_IDS[i];
  367. break;
  368. }
  369. // find the castle where this item is
  370. Castle castle = CastleManager.getInstance().getCastleById(getTicketCastleId(itemId));
  371. if (npcId > 0 && castle != null)
  372. {
  373. (new SiegeGuardManager(castle)).removeMerc(npcId, item.getX(), item.getY(), item.getZ());
  374. }
  375. getDroppedTickets().remove(item);
  376. }
  377. public int[] getItemIds()
  378. {
  379. return ITEM_IDS;
  380. }
  381. public final List<L2ItemInstance> getDroppedTickets()
  382. {
  383. if (_droppedTickets == null) _droppedTickets = new FastList<L2ItemInstance>();
  384. return _droppedTickets;
  385. }
  386. }