Siege.java 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488
  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.model.entity;
  16. import java.sql.Connection;
  17. import java.sql.PreparedStatement;
  18. import java.sql.ResultSet;
  19. import java.util.Calendar;
  20. import java.util.Collection;
  21. import java.util.List;
  22. import java.util.concurrent.ScheduledFuture;
  23. import java.util.logging.Level;
  24. import java.util.logging.Logger;
  25. import javolution.util.FastList;
  26. import net.sf.l2j.Config;
  27. import net.sf.l2j.L2DatabaseFactory;
  28. import net.sf.l2j.gameserver.Announcements;
  29. import net.sf.l2j.gameserver.SevenSigns;
  30. import net.sf.l2j.gameserver.ThreadPoolManager;
  31. import net.sf.l2j.gameserver.datatables.ClanTable;
  32. import net.sf.l2j.gameserver.datatables.MapRegionTable;
  33. import net.sf.l2j.gameserver.datatables.NpcTable;
  34. import net.sf.l2j.gameserver.idfactory.IdFactory;
  35. import net.sf.l2j.gameserver.instancemanager.MercTicketManager;
  36. import net.sf.l2j.gameserver.instancemanager.SiegeGuardManager;
  37. import net.sf.l2j.gameserver.instancemanager.SiegeManager;
  38. import net.sf.l2j.gameserver.instancemanager.SiegeManager.SiegeSpawn;
  39. import net.sf.l2j.gameserver.model.L2Clan;
  40. import net.sf.l2j.gameserver.model.L2Object;
  41. import net.sf.l2j.gameserver.model.L2SiegeClan;
  42. import net.sf.l2j.gameserver.model.L2Spawn;
  43. import net.sf.l2j.gameserver.model.L2World;
  44. import net.sf.l2j.gameserver.model.L2SiegeClan.SiegeClanType;
  45. import net.sf.l2j.gameserver.model.actor.L2Character;
  46. import net.sf.l2j.gameserver.model.actor.L2Npc;
  47. import net.sf.l2j.gameserver.model.actor.instance.L2ControlTowerInstance;
  48. import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
  49. import net.sf.l2j.gameserver.network.SystemMessageId;
  50. import net.sf.l2j.gameserver.network.serverpackets.ExBrExtraUserInfo;
  51. import net.sf.l2j.gameserver.network.serverpackets.RelationChanged;
  52. import net.sf.l2j.gameserver.network.serverpackets.SiegeInfo;
  53. import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
  54. import net.sf.l2j.gameserver.network.serverpackets.UserInfo;
  55. import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
  56. import net.sf.l2j.gameserver.util.Broadcast;
  57. public class Siege
  58. {
  59. protected static final Logger _log = Logger.getLogger(Siege.class.getName());
  60. // ==========================================================================================
  61. // Message to add/check
  62. // id=17 msg=[Castle siege has begun.] c3_attr1=[SystemMsg_k.17]
  63. // id=18 msg=[Castle siege is over.] c3_attr1=[SystemMsg_k.18]
  64. // id=288 msg=[The castle gate has been broken down.]
  65. // id=291 msg=[Clan $s1 is victorious over $s2's castle siege!]
  66. // id=292 msg=[$s1 has announced the castle siege time.]
  67. // - id=293 msg=[The registration term for $s1 has ended.]
  68. // - id=358 msg=[$s1 hour(s) until castle siege conclusion.]
  69. // - id=359 msg=[$s1 minute(s) until castle siege conclusion.]
  70. // - id=360 msg=[Castle siege $s1 second(s) left!]
  71. // id=640 msg=[You have failed to refuse castle defense aid.]
  72. // id=641 msg=[You have failed to approve castle defense aid.]
  73. // id=644 msg=[You are not yet registered for the castle siege.]
  74. // - id=645 msg=[Only clans with Level 4 and higher may register for a castle siege.]
  75. // id=646 msg=[You do not have the authority to modify the castle defender list.]
  76. // - id=688 msg=[The clan that owns the castle is automatically registered on the defending side.]
  77. // id=689 msg=[A clan that owns a castle cannot participate in another siege.]
  78. // id=690 msg=[You cannot register on the attacking side because you are part of an alliance with the clan that owns the castle.]
  79. // id=718 msg=[The castle gates cannot be opened and closed during a siege.]
  80. // - id=295 msg=[$s1's siege was canceled because there were no clans that participated.]
  81. // id=659 msg=[This is not the time for siege registration and so registrations cannot be accepted or rejected.]
  82. // - id=660 msg=[This is not the time for siege registration and so registration and cancellation cannot be done.]
  83. // id=663 msg=[The siege time has been declared for $s. It is not possible to change the time after a siege time has been declared. Do you want to continue?]
  84. // id=667 msg=[You are registering on the attacking side of the $s1 siege. Do you want to continue?]
  85. // id=668 msg=[You are registering on the defending side of the $s1 siege. Do you want to continue?]
  86. // id=669 msg=[You are canceling your application to participate in the $s1 siege battle. Do you want to continue?]
  87. // id=707 msg=[You cannot teleport to a village that is in a siege.]
  88. // - id=711 msg=[The siege of $s1 has started.]
  89. // - id=712 msg=[The siege of $s1 has finished.]
  90. // id=844 msg=[The siege to conquer $s1 has begun.]
  91. // - id=845 msg=[The deadline to register for the siege of $s1 has passed.]
  92. // - id=846 msg=[The siege of $s1 has been canceled due to lack of interest.]
  93. // - id=856 msg=[The siege of $s1 has ended in a draw.]
  94. // id=285 msg=[Clan $s1 has succeeded in engraving the ruler!]
  95. // - id=287 msg=[The opponent clan has begun to engrave the ruler.]
  96. public static enum TeleportWhoType
  97. {
  98. All,
  99. Attacker,
  100. DefenderNotOwner,
  101. Owner,
  102. Spectator
  103. }
  104. private int _controlTowerCount;
  105. private int _controlTowerMaxCount;
  106. // ===============================================================
  107. // Schedule task
  108. public class ScheduleEndSiegeTask implements Runnable
  109. {
  110. private Castle _castleInst;
  111. public ScheduleEndSiegeTask(Castle pCastle)
  112. {
  113. _castleInst = pCastle;
  114. }
  115. public void run()
  116. {
  117. if (!getIsInProgress())
  118. return;
  119. try
  120. {
  121. long timeRemaining = _siegeEndDate.getTimeInMillis() - Calendar.getInstance().getTimeInMillis();
  122. if (timeRemaining > 3600000)
  123. {
  124. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleEndSiegeTask(_castleInst), timeRemaining - 3600000); // Prepare task for 1 hr left.
  125. }
  126. else if ((timeRemaining <= 3600000) && (timeRemaining > 600000))
  127. {
  128. announceToPlayer(Math.round(timeRemaining / 60000) + " minute(s) until " + getCastle().getName() + " siege conclusion.", true);
  129. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleEndSiegeTask(_castleInst), timeRemaining - 600000); // Prepare task for 10 minute left.
  130. }
  131. else if ((timeRemaining <= 600000) && (timeRemaining > 300000))
  132. {
  133. announceToPlayer(Math.round(timeRemaining / 60000) + " minute(s) until " + getCastle().getName() + " siege conclusion.", true);
  134. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleEndSiegeTask(_castleInst), timeRemaining - 300000); // Prepare task for 5 minute left.
  135. }
  136. else if ((timeRemaining <= 300000) && (timeRemaining > 10000))
  137. {
  138. announceToPlayer(Math.round(timeRemaining / 60000) + " minute(s) until " + getCastle().getName() + " siege conclusion.", true);
  139. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleEndSiegeTask(_castleInst), timeRemaining - 10000); // Prepare task for 10 seconds count down
  140. }
  141. else if ((timeRemaining <= 10000) && (timeRemaining > 0))
  142. {
  143. announceToPlayer(getCastle().getName() + " siege " + Math.round(timeRemaining / 1000) + " second(s) left!", true);
  144. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleEndSiegeTask(_castleInst), timeRemaining); // Prepare task for second count down
  145. }
  146. else
  147. {
  148. _castleInst.getSiege().endSiege();
  149. }
  150. }
  151. catch (Exception e)
  152. {
  153. _log.log(Level.SEVERE, "", e);
  154. }
  155. }
  156. }
  157. public class ScheduleStartSiegeTask implements Runnable
  158. {
  159. private Castle _castleInst;
  160. public ScheduleStartSiegeTask(Castle pCastle)
  161. {
  162. _castleInst = pCastle;
  163. }
  164. public void run()
  165. {
  166. _scheduledStartSiegeTask.cancel(false);
  167. if (getIsInProgress())
  168. return;
  169. try
  170. {
  171. if (!getIsTimeRegistrationOver())
  172. {
  173. long regTimeRemaining = getTimeRegistrationOverDate().getTimeInMillis() - Calendar.getInstance().getTimeInMillis();
  174. if (regTimeRemaining > 0)
  175. {
  176. _scheduledStartSiegeTask = ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(_castleInst), regTimeRemaining);
  177. return;
  178. }
  179. else
  180. {
  181. endTimeRegistration(true);
  182. }
  183. }
  184. long timeRemaining = getSiegeDate().getTimeInMillis() - Calendar.getInstance().getTimeInMillis();
  185. if (timeRemaining > 86400000)
  186. {
  187. _scheduledStartSiegeTask = ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(_castleInst), timeRemaining - 86400000); // Prepare task for 24 before siege start to end registration
  188. }
  189. else if ((timeRemaining <= 86400000) && (timeRemaining > 13600000))
  190. {
  191. announceToPlayer("The registration term for " + getCastle().getName() + " has ended.", false);
  192. _isRegistrationOver = true;
  193. clearSiegeWaitingClan();
  194. _scheduledStartSiegeTask = ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(_castleInst), timeRemaining - 13600000); // Prepare task for 1 hr left before siege start.
  195. }
  196. else if ((timeRemaining <= 13600000) && (timeRemaining > 600000))
  197. {
  198. announceToPlayer(Math.round(timeRemaining / 60000) + " minute(s) until " + getCastle().getName() + " siege begin.", false);
  199. _scheduledStartSiegeTask = ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(_castleInst), timeRemaining - 600000); // Prepare task for 10 minute left.
  200. }
  201. else if ((timeRemaining <= 600000) && (timeRemaining > 300000))
  202. {
  203. announceToPlayer(Math.round(timeRemaining / 60000) + " minute(s) until " + getCastle().getName() + " siege begin.", false);
  204. _scheduledStartSiegeTask = ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(_castleInst), timeRemaining - 300000); // Prepare task for 5 minute left.
  205. }
  206. else if ((timeRemaining <= 300000) && (timeRemaining > 10000))
  207. {
  208. announceToPlayer(Math.round(timeRemaining / 60000) + " minute(s) until " + getCastle().getName() + " siege begin.", false);
  209. _scheduledStartSiegeTask = ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(_castleInst), timeRemaining - 10000); // Prepare task for 10 seconds count down
  210. }
  211. else if ((timeRemaining <= 10000) && (timeRemaining > 0))
  212. {
  213. announceToPlayer(getCastle().getName() + " siege " + Math.round(timeRemaining / 1000) + " second(s) to start!", false);
  214. _scheduledStartSiegeTask = ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(_castleInst), timeRemaining); // Prepare task for second count down
  215. }
  216. else
  217. {
  218. _castleInst.getSiege().startSiege();
  219. }
  220. }
  221. catch (Exception e)
  222. {
  223. _log.log(Level.SEVERE, "", e);
  224. }
  225. }
  226. }
  227. // =========================================================
  228. // Data Field
  229. // Attacker and Defender
  230. private List<L2SiegeClan> _attackerClans = new FastList<L2SiegeClan>(); // L2SiegeClan
  231. private List<L2SiegeClan> _defenderClans = new FastList<L2SiegeClan>(); // L2SiegeClan
  232. private List<L2SiegeClan> _defenderWaitingClans = new FastList<L2SiegeClan>(); // L2SiegeClan
  233. // Castle setting
  234. private List<L2ControlTowerInstance> _controlTowers = new FastList<L2ControlTowerInstance>();
  235. private Castle[] _castle;
  236. private boolean _isInProgress = false;
  237. private boolean _isNormalSide = true; // true = Atk is Atk, false = Atk is Def
  238. protected boolean _isRegistrationOver = false;
  239. protected Calendar _siegeEndDate;
  240. private SiegeGuardManager _siegeGuardManager;
  241. protected ScheduledFuture<?> _scheduledStartSiegeTask = null;
  242. // =========================================================
  243. // Constructor
  244. public Siege(Castle[] castle)
  245. {
  246. _castle = castle;
  247. _siegeGuardManager = new SiegeGuardManager(getCastle());
  248. startAutoTask();
  249. }
  250. // =========================================================
  251. // Siege phases
  252. /**
  253. * When siege ends<BR><BR>
  254. */
  255. public void endSiege()
  256. {
  257. if (getIsInProgress())
  258. {
  259. announceToPlayer("The siege of " + getCastle().getName() + " has finished!", false);
  260. if (getCastle().getOwnerId() <= 0)
  261. announceToPlayer("The siege of " + getCastle().getName() + " has ended in a draw.", false);
  262. getCastle().updateClansReputation();
  263. removeFlags(); // Removes all flags. Note: Remove flag before teleporting players
  264. teleportPlayer(Siege.TeleportWhoType.Attacker, MapRegionTable.TeleportWhereType.Town); // Teleport to the second closest town
  265. teleportPlayer(Siege.TeleportWhoType.DefenderNotOwner, MapRegionTable.TeleportWhereType.Town); // Teleport to the second closest town
  266. teleportPlayer(Siege.TeleportWhoType.Spectator, MapRegionTable.TeleportWhereType.Town); // Teleport to the second closest town
  267. _isInProgress = false; // Flag so that siege instance can be started
  268. updatePlayerSiegeStateFlags(true);
  269. saveCastleSiege(); // Save castle specific data
  270. clearSiegeClan(); // Clear siege clan from db
  271. removeControlTower(); // Remove all control tower from this castle
  272. _siegeGuardManager.unspawnSiegeGuard(); // Remove all spawned siege guard from this castle
  273. if (getCastle().getOwnerId() > 0)
  274. _siegeGuardManager.removeMercs();
  275. getCastle().spawnDoor(); // Respawn door to castle
  276. getCastle().getZone().updateZoneStatusForCharactersInside();
  277. }
  278. }
  279. private void removeDefender(L2SiegeClan sc)
  280. {
  281. if (sc != null)
  282. getDefenderClans().remove(sc);
  283. }
  284. private void removeAttacker(L2SiegeClan sc)
  285. {
  286. if (sc != null)
  287. getAttackerClans().remove(sc);
  288. }
  289. private void addDefender(L2SiegeClan sc, SiegeClanType type)
  290. {
  291. if (sc == null)
  292. return;
  293. sc.setType(type);
  294. getDefenderClans().add(sc);
  295. }
  296. private void addAttacker(L2SiegeClan sc)
  297. {
  298. if (sc == null)
  299. return;
  300. sc.setType(SiegeClanType.ATTACKER);
  301. getAttackerClans().add(sc);
  302. }
  303. /**
  304. * When control of castle changed during siege<BR><BR>
  305. */
  306. public void midVictory()
  307. {
  308. if (getIsInProgress()) // Siege still in progress
  309. {
  310. if (getCastle().getOwnerId() > 0)
  311. _siegeGuardManager.removeMercs(); // Remove all merc entry from db
  312. if (getDefenderClans().isEmpty() && // If defender doesn't exist (Pc vs Npc)
  313. getAttackerClans().size() == 1 // Only 1 attacker
  314. )
  315. {
  316. L2SiegeClan sc_newowner = getAttackerClan(getCastle().getOwnerId());
  317. removeAttacker(sc_newowner);
  318. addDefender(sc_newowner, SiegeClanType.OWNER);
  319. endSiege();
  320. return;
  321. }
  322. if (getCastle().getOwnerId() > 0)
  323. {
  324. int allyId = ClanTable.getInstance().getClan(getCastle().getOwnerId()).getAllyId();
  325. if (getDefenderClans().isEmpty()) // If defender doesn't exist (Pc vs Npc)
  326. // and only an alliance attacks
  327. {
  328. // The player's clan is in an alliance
  329. if (allyId != 0)
  330. {
  331. boolean allinsamealliance = true;
  332. for (L2SiegeClan sc : getAttackerClans())
  333. {
  334. if (sc != null)
  335. {
  336. if (ClanTable.getInstance().getClan(sc.getClanId()).getAllyId() != allyId)
  337. allinsamealliance = false;
  338. }
  339. }
  340. if (allinsamealliance)
  341. {
  342. L2SiegeClan sc_newowner = getAttackerClan(getCastle().getOwnerId());
  343. removeAttacker(sc_newowner);
  344. addDefender(sc_newowner, SiegeClanType.OWNER);
  345. endSiege();
  346. return;
  347. }
  348. }
  349. }
  350. for (L2SiegeClan sc : getDefenderClans())
  351. {
  352. if (sc != null)
  353. {
  354. removeDefender(sc);
  355. addAttacker(sc);
  356. }
  357. }
  358. L2SiegeClan sc_newowner = getAttackerClan(getCastle().getOwnerId());
  359. removeAttacker(sc_newowner);
  360. addDefender(sc_newowner, SiegeClanType.OWNER);
  361. // The player's clan is in an alliance
  362. if (allyId != 0)
  363. {
  364. L2Clan[] clanList = ClanTable.getInstance().getClans();
  365. for (L2Clan clan : clanList)
  366. {
  367. if (clan.getAllyId() == allyId)
  368. {
  369. L2SiegeClan sc = getAttackerClan(clan.getClanId());
  370. if (sc != null)
  371. {
  372. removeAttacker(sc);
  373. addDefender(sc, SiegeClanType.DEFENDER);
  374. }
  375. }
  376. }
  377. }
  378. teleportPlayer(Siege.TeleportWhoType.Attacker, MapRegionTable.TeleportWhereType.SiegeFlag); // Teleport to the second closest town
  379. teleportPlayer(Siege.TeleportWhoType.Spectator, MapRegionTable.TeleportWhereType.Town); // Teleport to the second closest town
  380. removeDefenderFlags(); // Removes defenders' flags
  381. getCastle().removeUpgrade(); // Remove all castle upgrade
  382. getCastle().spawnDoor(true); // Respawn door to castle but make them weaker (50% hp)
  383. removeControlTower(); // Remove all control tower from this castle
  384. _controlTowerCount = 0;//Each new siege midvictory CT are completely respawned.
  385. _controlTowerMaxCount = 0;
  386. spawnControlTower(getCastle().getCastleId());
  387. updatePlayerSiegeStateFlags(false);
  388. }
  389. }
  390. }
  391. /**
  392. * When siege starts<BR><BR>
  393. */
  394. public void startSiege()
  395. {
  396. if (!getIsInProgress())
  397. {
  398. if (getAttackerClans().isEmpty())
  399. {
  400. SystemMessage sm;
  401. if (getCastle().getOwnerId() <= 0)
  402. sm = new SystemMessage(SystemMessageId.SIEGE_OF_S1_HAS_BEEN_CANCELED_DUE_TO_LACK_OF_INTEREST);
  403. else
  404. sm = new SystemMessage(SystemMessageId.S1_SIEGE_WAS_CANCELED_BECAUSE_NO_CLANS_PARTICIPATED);
  405. sm.addString(getCastle().getName());
  406. Announcements.getInstance().announceToAll(sm);
  407. saveCastleSiege();
  408. return;
  409. }
  410. _isNormalSide = true; // Atk is now atk
  411. _isInProgress = true; // Flag so that same siege instance cannot be started again
  412. loadSiegeClan(); // Load siege clan from db
  413. updatePlayerSiegeStateFlags(false);
  414. teleportPlayer(Siege.TeleportWhoType.Attacker, MapRegionTable.TeleportWhereType.Town); // Teleport to the closest town
  415. //teleportPlayer(Siege.TeleportWhoType.Spectator, MapRegionTable.TeleportWhereType.Town); // Teleport to the second closest town
  416. _controlTowerCount = 0;
  417. _controlTowerMaxCount = 0;
  418. spawnControlTower(getCastle().getCastleId()); // Spawn control tower
  419. getCastle().spawnDoor(); // Spawn door
  420. spawnSiegeGuard(); // Spawn siege guard
  421. MercTicketManager.getInstance().deleteTickets(getCastle().getCastleId()); // remove the tickets from the ground
  422. getCastle().getZone().updateZoneStatusForCharactersInside();
  423. // Schedule a task to prepare auto siege end
  424. _siegeEndDate = Calendar.getInstance();
  425. _siegeEndDate.add(Calendar.MINUTE, SiegeManager.getInstance().getSiegeLength());
  426. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleEndSiegeTask(getCastle()), 1000); // Prepare auto end task
  427. announceToPlayer("The siege of " + getCastle().getName() + " has started!", false);
  428. }
  429. }
  430. // =========================================================
  431. // Method - Public
  432. /**
  433. * Announce to player.<BR><BR>
  434. * @param message The String of the message to send to player
  435. * @param inAreaOnly The boolean flag to show message to players in area only.
  436. */
  437. public void announceToPlayer(String message, boolean inAreaOnly)
  438. {
  439. if (inAreaOnly)
  440. {
  441. getCastle().getZone().announceToPlayers(message);
  442. return;
  443. }
  444. Broadcast.announceToOnlinePlayers(message);
  445. }
  446. public void updatePlayerSiegeStateFlags(boolean clear)
  447. {
  448. L2Clan clan;
  449. for (L2SiegeClan siegeclan : getAttackerClans())
  450. {
  451. if (siegeclan == null)
  452. continue;
  453. clan = ClanTable.getInstance().getClan(siegeclan.getClanId());
  454. for (L2PcInstance member : clan.getOnlineMembers(0))
  455. {
  456. if (clear)
  457. member.setSiegeState((byte) 0);
  458. else
  459. member.setSiegeState((byte) 1);
  460. member.sendPacket(new UserInfo(member));
  461. member.sendPacket(new ExBrExtraUserInfo(member));
  462. Collection<L2PcInstance> plrs = member.getKnownList().getKnownPlayers().values();
  463. //synchronized (member.getKnownList().getKnownPlayers())
  464. {
  465. for (L2PcInstance player : plrs)
  466. {
  467. player.sendPacket(new RelationChanged(member, member.getRelation(player), member.isAutoAttackable(player)));
  468. if (member.getPet() != null)
  469. player.sendPacket(new RelationChanged(member.getPet(), member.getRelation(player), member.isAutoAttackable(player)));
  470. }
  471. }
  472. }
  473. }
  474. for (L2SiegeClan siegeclan : getDefenderClans())
  475. {
  476. if (siegeclan == null)
  477. continue;
  478. clan = ClanTable.getInstance().getClan(siegeclan.getClanId());
  479. for (L2PcInstance member : clan.getOnlineMembers(0))
  480. {
  481. if (clear)
  482. member.setSiegeState((byte) 0);
  483. else
  484. member.setSiegeState((byte) 2);
  485. member.sendPacket(new UserInfo(member));
  486. member.sendPacket(new ExBrExtraUserInfo(member));
  487. Collection<L2PcInstance> plrs = member.getKnownList().getKnownPlayers().values();
  488. //synchronized (member.getKnownList().getKnownPlayers())
  489. {
  490. for (L2PcInstance player : plrs)
  491. {
  492. player.sendPacket(new RelationChanged(member, member.getRelation(player), member.isAutoAttackable(player)));
  493. if (member.getPet() != null)
  494. player.sendPacket(new RelationChanged(member.getPet(), member.getRelation(player), member.isAutoAttackable(player)));
  495. }
  496. }
  497. }
  498. }
  499. }
  500. /**
  501. * Approve clan as defender for siege<BR><BR>
  502. * @param clanId The int of player's clan id
  503. */
  504. public void approveSiegeDefenderClan(int clanId)
  505. {
  506. if (clanId <= 0)
  507. return;
  508. saveSiegeClan(ClanTable.getInstance().getClan(clanId), 0, true);
  509. loadSiegeClan();
  510. }
  511. /** Return true if object is inside the zone */
  512. public boolean checkIfInZone(L2Object object)
  513. {
  514. return checkIfInZone(object.getX(), object.getY(), object.getZ());
  515. }
  516. /** Return true if object is inside the zone */
  517. public boolean checkIfInZone(int x, int y, int z)
  518. {
  519. return (getIsInProgress() && (getCastle().checkIfInZone(x, y, z))); // Castle zone during siege
  520. }
  521. /**
  522. * Return true if clan is attacker<BR><BR>
  523. * @param clan The L2Clan of the player
  524. */
  525. public boolean checkIsAttacker(L2Clan clan)
  526. {
  527. return (getAttackerClan(clan) != null);
  528. }
  529. /**
  530. * Return true if clan is defender<BR><BR>
  531. * @param clan The L2Clan of the player
  532. */
  533. public boolean checkIsDefender(L2Clan clan)
  534. {
  535. return (getDefenderClan(clan) != null);
  536. }
  537. /**
  538. * Return true if clan is defender waiting approval<BR><BR>
  539. * @param clan The L2Clan of the player
  540. */
  541. public boolean checkIsDefenderWaiting(L2Clan clan)
  542. {
  543. return (getDefenderWaitingClan(clan) != null);
  544. }
  545. /** Clear all registered siege clans from database for castle */
  546. public void clearSiegeClan()
  547. {
  548. Connection con = null;
  549. try
  550. {
  551. con = L2DatabaseFactory.getInstance().getConnection();
  552. PreparedStatement statement = con.prepareStatement("DELETE FROM siege_clans WHERE castle_id=?");
  553. statement.setInt(1, getCastle().getCastleId());
  554. statement.execute();
  555. statement.close();
  556. if (getCastle().getOwnerId() > 0)
  557. {
  558. PreparedStatement statement2 = con.prepareStatement("DELETE FROM siege_clans WHERE clan_id=?");
  559. statement2.setInt(1, getCastle().getOwnerId());
  560. statement2.execute();
  561. statement2.close();
  562. }
  563. getAttackerClans().clear();
  564. getDefenderClans().clear();
  565. getDefenderWaitingClans().clear();
  566. }
  567. catch (Exception e)
  568. {
  569. _log.warning("Exception: clearSiegeClan(): " + e.getMessage());
  570. e.printStackTrace();
  571. }
  572. finally
  573. {
  574. try
  575. {
  576. con.close();
  577. }
  578. catch (Exception e)
  579. {
  580. }
  581. }
  582. }
  583. /** Clear all siege clans waiting for approval from database for castle */
  584. public void clearSiegeWaitingClan()
  585. {
  586. Connection con = null;
  587. try
  588. {
  589. con = L2DatabaseFactory.getInstance().getConnection();
  590. PreparedStatement statement = con.prepareStatement("DELETE FROM siege_clans WHERE castle_id=? and type = 2");
  591. statement.setInt(1, getCastle().getCastleId());
  592. statement.execute();
  593. statement.close();
  594. getDefenderWaitingClans().clear();
  595. }
  596. catch (Exception e)
  597. {
  598. _log.warning("Exception: clearSiegeWaitingClan(): " + e.getMessage());
  599. e.printStackTrace();
  600. }
  601. finally
  602. {
  603. try
  604. {
  605. con.close();
  606. }
  607. catch (Exception e)
  608. {
  609. }
  610. }
  611. }
  612. /** Return list of L2PcInstance registered as attacker in the zone. */
  613. public List<L2PcInstance> getAttackersInZone()
  614. {
  615. List<L2PcInstance> players = new FastList<L2PcInstance>();
  616. L2Clan clan;
  617. for (L2SiegeClan siegeclan : getAttackerClans())
  618. {
  619. clan = ClanTable.getInstance().getClan(siegeclan.getClanId());
  620. for (L2PcInstance player : clan.getOnlineMembers(0))
  621. {
  622. if (checkIfInZone(player.getX(), player.getY(), player.getZ()))
  623. players.add(player);
  624. }
  625. }
  626. return players;
  627. }
  628. /** Return list of L2PcInstance registered as defender but not owner in the zone. */
  629. public List<L2PcInstance> getDefendersButNotOwnersInZone()
  630. {
  631. List<L2PcInstance> players = new FastList<L2PcInstance>();
  632. L2Clan clan;
  633. for (L2SiegeClan siegeclan : getDefenderClans())
  634. {
  635. clan = ClanTable.getInstance().getClan(siegeclan.getClanId());
  636. if (clan.getClanId() == getCastle().getOwnerId())
  637. continue;
  638. for (L2PcInstance player : clan.getOnlineMembers(0))
  639. {
  640. if (checkIfInZone(player.getX(), player.getY(), player.getZ()))
  641. players.add(player);
  642. }
  643. }
  644. return players;
  645. }
  646. /** Return list of L2PcInstance in the zone. */
  647. public List<L2PcInstance> getPlayersInZone()
  648. {
  649. return getCastle().getZone().getAllPlayers();
  650. }
  651. /** Return list of L2PcInstance owning the castle in the zone. */
  652. public List<L2PcInstance> getOwnersInZone()
  653. {
  654. List<L2PcInstance> players = new FastList<L2PcInstance>();
  655. L2Clan clan;
  656. for (L2SiegeClan siegeclan : getDefenderClans())
  657. {
  658. clan = ClanTable.getInstance().getClan(siegeclan.getClanId());
  659. if (clan.getClanId() != getCastle().getOwnerId())
  660. continue;
  661. for (L2PcInstance player : clan.getOnlineMembers(0))
  662. {
  663. if (checkIfInZone(player.getX(), player.getY(), player.getZ()))
  664. players.add(player);
  665. }
  666. }
  667. return players;
  668. }
  669. /** Return list of L2PcInstance not registered as attacker or defender in the zone. */
  670. public List<L2PcInstance> getSpectatorsInZone()
  671. {
  672. List<L2PcInstance> players = new FastList<L2PcInstance>();
  673. Collection<L2PcInstance> pls = L2World.getInstance().getAllPlayers().values();
  674. //synchronized (L2World.getInstance().getAllPlayers())
  675. {
  676. for (L2PcInstance player : pls)
  677. {
  678. // quick check from player states, which don't include siege number however
  679. if (!player.isInsideZone(L2Character.ZONE_SIEGE) || player.getSiegeState() != 0)
  680. continue;
  681. if (checkIfInZone(player.getX(), player.getY(), player.getZ()))
  682. players.add(player);
  683. }
  684. }
  685. return players;
  686. }
  687. /** Control Tower was skilled */
  688. public void killedCT(L2Npc ct)
  689. {
  690. _controlTowerCount--;
  691. if (_controlTowerCount < 0)
  692. _controlTowerCount = 0;
  693. }
  694. /** Remove the flag that was killed */
  695. public void killedFlag(L2Npc flag)
  696. {
  697. if (flag == null)
  698. return;
  699. for (L2SiegeClan clan : getAttackerClans())
  700. {
  701. if (clan.removeFlag(flag))
  702. return;
  703. }
  704. }
  705. /** Display list of registered clans */
  706. public void listRegisterClan(L2PcInstance player)
  707. {
  708. player.sendPacket(new SiegeInfo(getCastle()));
  709. }
  710. /**
  711. * Register clan as attacker<BR><BR>
  712. * @param player The L2PcInstance of the player trying to register
  713. */
  714. public void registerAttacker(L2PcInstance player)
  715. {
  716. registerAttacker(player, false);
  717. }
  718. public void registerAttacker(L2PcInstance player, boolean force)
  719. {
  720. if (player.getClan() == null)
  721. return;
  722. int allyId = 0;
  723. if (getCastle().getOwnerId() != 0)
  724. allyId = ClanTable.getInstance().getClan(getCastle().getOwnerId()).getAllyId();
  725. if (allyId != 0)
  726. {
  727. if (player.getClan().getAllyId() == allyId && !force)
  728. {
  729. player.sendMessage("You cannot register as an attacker because your alliance owns the castle");
  730. return;
  731. }
  732. }
  733. if (force || checkIfCanRegister(player))
  734. saveSiegeClan(player.getClan(), 1, false); // Save to database
  735. }
  736. /**
  737. * Register clan as defender<BR><BR>
  738. * @param player The L2PcInstance of the player trying to register
  739. */
  740. public void registerDefender(L2PcInstance player)
  741. {
  742. registerDefender(player, false);
  743. }
  744. public void registerDefender(L2PcInstance player, boolean force)
  745. {
  746. if (getCastle().getOwnerId() <= 0)
  747. player.sendMessage("You cannot register as a defender because " + getCastle().getName() + " is owned by NPC.");
  748. else if (force || checkIfCanRegister(player))
  749. saveSiegeClan(player.getClan(), 2, false); // Save to database
  750. }
  751. /**
  752. * Remove clan from siege<BR><BR>
  753. * @param clanId The int of player's clan id
  754. */
  755. public void removeSiegeClan(int clanId)
  756. {
  757. if (clanId <= 0)
  758. return;
  759. Connection con = null;
  760. try
  761. {
  762. con = L2DatabaseFactory.getInstance().getConnection();
  763. PreparedStatement statement = con.prepareStatement("DELETE FROM siege_clans WHERE castle_id=? and clan_id=?");
  764. statement.setInt(1, getCastle().getCastleId());
  765. statement.setInt(2, clanId);
  766. statement.execute();
  767. statement.close();
  768. loadSiegeClan();
  769. }
  770. catch (Exception e)
  771. {
  772. }
  773. finally
  774. {
  775. try
  776. {
  777. con.close();
  778. }
  779. catch (Exception e)
  780. {
  781. }
  782. }
  783. }
  784. /**
  785. * Remove clan from siege<BR><BR>
  786. * @param player The L2PcInstance of player/clan being removed
  787. */
  788. public void removeSiegeClan(L2Clan clan)
  789. {
  790. if (clan == null || clan.getHasCastle() == getCastle().getCastleId() || !SiegeManager.getInstance().checkIsRegistered(clan, getCastle().getCastleId()))
  791. return;
  792. removeSiegeClan(clan.getClanId());
  793. }
  794. /**
  795. * Remove clan from siege<BR><BR>
  796. * @param player The L2PcInstance of player/clan being removed
  797. */
  798. public void removeSiegeClan(L2PcInstance player)
  799. {
  800. removeSiegeClan(player.getClan());
  801. }
  802. /**
  803. * Start the auto tasks<BR><BR>
  804. */
  805. public void startAutoTask()
  806. {
  807. correctSiegeDateTime();
  808. _log.info("Siege of " + getCastle().getName() + ": " + getCastle().getSiegeDate().getTime());
  809. loadSiegeClan();
  810. // Schedule siege auto start
  811. if (_scheduledStartSiegeTask != null)
  812. _scheduledStartSiegeTask.cancel(false);
  813. _scheduledStartSiegeTask = ThreadPoolManager.getInstance().scheduleGeneral(new Siege.ScheduleStartSiegeTask(getCastle()), 1000);
  814. }
  815. /**
  816. * Teleport players
  817. */
  818. public void teleportPlayer(TeleportWhoType teleportWho, MapRegionTable.TeleportWhereType teleportWhere)
  819. {
  820. List<L2PcInstance> players;
  821. switch (teleportWho)
  822. {
  823. case Owner:
  824. players = getOwnersInZone();
  825. break;
  826. case Attacker:
  827. players = getAttackersInZone();
  828. break;
  829. case DefenderNotOwner:
  830. players = getDefendersButNotOwnersInZone();
  831. break;
  832. case Spectator:
  833. players = getSpectatorsInZone();
  834. break;
  835. default:
  836. players = getPlayersInZone();
  837. }
  838. for (L2PcInstance player : players)
  839. {
  840. if (player.isGM() || player.isInJail())
  841. continue;
  842. player.teleToLocation(teleportWhere);
  843. }
  844. }
  845. // =========================================================
  846. // Method - Private
  847. /**
  848. * Add clan as attacker<BR><BR>
  849. * @param clanId The int of clan's id
  850. */
  851. private void addAttacker(int clanId)
  852. {
  853. getAttackerClans().add(new L2SiegeClan(clanId, SiegeClanType.ATTACKER)); // Add registered attacker to attacker list
  854. }
  855. /**
  856. * Add clan as defender<BR><BR>
  857. * @param clanId The int of clan's id
  858. */
  859. private void addDefender(int clanId)
  860. {
  861. getDefenderClans().add(new L2SiegeClan(clanId, SiegeClanType.DEFENDER)); // Add registered defender to defender list
  862. }
  863. /**
  864. * <p>Add clan as defender with the specified type</p>
  865. * @param clanId The int of clan's id
  866. * @param type the type of the clan
  867. */
  868. private void addDefender(int clanId, SiegeClanType type)
  869. {
  870. getDefenderClans().add(new L2SiegeClan(clanId, type));
  871. }
  872. /**
  873. * Add clan as defender waiting approval<BR><BR>
  874. * @param clanId The int of clan's id
  875. */
  876. private void addDefenderWaiting(int clanId)
  877. {
  878. getDefenderWaitingClans().add(new L2SiegeClan(clanId, SiegeClanType.DEFENDER_PENDING)); // Add registered defender to defender list
  879. }
  880. /**
  881. * Return true if the player can register.<BR><BR>
  882. * @param player The L2PcInstance of the player trying to register
  883. */
  884. private boolean checkIfCanRegister(L2PcInstance player)
  885. {
  886. if (getIsRegistrationOver())
  887. player.sendMessage("The deadline to register for the siege of " + getCastle().getName() + " has passed.");
  888. else if (getIsInProgress())
  889. player.sendMessage("This is not the time for siege registration and so registration and cancellation cannot be done.");
  890. else if (player.getClan() == null || player.getClan().getLevel() < SiegeManager.getInstance().getSiegeClanMinLevel())
  891. player.sendMessage("Only clans with Level " + SiegeManager.getInstance().getSiegeClanMinLevel() + " and higher may register for a castle siege.");
  892. else if (player.getClan().getHasCastle() > 0)
  893. player.sendMessage("You cannot register because your clan already owns a castle.");
  894. else if (player.getClan().getClanId() == getCastle().getOwnerId())
  895. player.sendPacket(new SystemMessage(SystemMessageId.CLAN_THAT_OWNS_CASTLE_IS_AUTOMATICALLY_REGISTERED_DEFENDING));
  896. else if (SiegeManager.getInstance().checkIsRegistered(player.getClan(), getCastle().getCastleId()))
  897. player.sendPacket(new SystemMessage(SystemMessageId.ALREADY_REQUESTED_SIEGE_BATTLE));
  898. else if (checkIfAlreadyRegisteredForSameDay(player.getClan()))
  899. player.sendPacket(new SystemMessage(SystemMessageId.APPLICATION_DENIED_BECAUSE_ALREADY_SUBMITTED_A_REQUEST_FOR_ANOTHER_SIEGE_BATTLE));
  900. else
  901. return true;
  902. return false;
  903. }
  904. /**
  905. * Return true if the clan has already registered to a siege for the same day.<BR><BR>
  906. * @param clan The L2Clan of the player trying to register
  907. */
  908. public boolean checkIfAlreadyRegisteredForSameDay(L2Clan clan)
  909. {
  910. for (Siege siege : SiegeManager.getInstance().getSieges())
  911. {
  912. if (siege == this)
  913. continue;
  914. if (siege.getSiegeDate().get(Calendar.DAY_OF_WEEK) == this.getSiegeDate().get(Calendar.DAY_OF_WEEK))
  915. {
  916. if (siege.checkIsAttacker(clan))
  917. return true;
  918. if (siege.checkIsDefender(clan))
  919. return true;
  920. if (siege.checkIsDefenderWaiting(clan))
  921. return true;
  922. }
  923. }
  924. return false;
  925. }
  926. /**
  927. * Return the correct siege date as Calendar.<BR><BR>
  928. * @param siegeDate The Calendar siege date and time
  929. */
  930. public void correctSiegeDateTime()
  931. {
  932. boolean corrected = false;
  933. if (getCastle().getSiegeDate().getTimeInMillis() < Calendar.getInstance().getTimeInMillis())
  934. {
  935. // Since siege has past reschedule it to the next one
  936. // This is usually caused by server being down
  937. corrected = true;
  938. setNextSiegeDate();
  939. }
  940. if (!SevenSigns.getInstance().isDateInSealValidPeriod(getCastle().getSiegeDate()))
  941. {
  942. // no sieges in Quest period! reschedule it to the next SealValidationPeriod
  943. // This is usually caused by server being down
  944. corrected = true;
  945. setNextSiegeDate();
  946. }
  947. if (corrected)
  948. saveSiegeDate();
  949. }
  950. /** Load siege clans. */
  951. private void loadSiegeClan()
  952. {
  953. Connection con = null;
  954. try
  955. {
  956. getAttackerClans().clear();
  957. getDefenderClans().clear();
  958. getDefenderWaitingClans().clear();
  959. // Add castle owner as defender (add owner first so that they are on the top of the defender list)
  960. if (getCastle().getOwnerId() > 0)
  961. addDefender(getCastle().getOwnerId(), SiegeClanType.OWNER);
  962. PreparedStatement statement = null;
  963. ResultSet rs = null;
  964. con = L2DatabaseFactory.getInstance().getConnection();
  965. statement = con.prepareStatement("SELECT clan_id,type FROM siege_clans where castle_id=?");
  966. statement.setInt(1, getCastle().getCastleId());
  967. rs = statement.executeQuery();
  968. int typeId;
  969. while (rs.next())
  970. {
  971. typeId = rs.getInt("type");
  972. if (typeId == 0)
  973. addDefender(rs.getInt("clan_id"));
  974. else if (typeId == 1)
  975. addAttacker(rs.getInt("clan_id"));
  976. else if (typeId == 2)
  977. addDefenderWaiting(rs.getInt("clan_id"));
  978. }
  979. statement.close();
  980. }
  981. catch (Exception e)
  982. {
  983. _log.warning("Exception: loadSiegeClan(): " + e.getMessage());
  984. e.printStackTrace();
  985. }
  986. finally
  987. {
  988. try
  989. {
  990. con.close();
  991. }
  992. catch (Exception e)
  993. {
  994. }
  995. }
  996. }
  997. /** Remove all control tower spawned. */
  998. private void removeControlTower()
  999. {
  1000. if (_controlTowers != null)
  1001. {
  1002. // Remove all instance of control tower for this castle
  1003. for (L2ControlTowerInstance ct : _controlTowers)
  1004. {
  1005. if (ct != null)
  1006. ct.decayMe();
  1007. }
  1008. _controlTowers = null;
  1009. }
  1010. }
  1011. /** Remove all flags. */
  1012. private void removeFlags()
  1013. {
  1014. for (L2SiegeClan sc : getAttackerClans())
  1015. {
  1016. if (sc != null)
  1017. sc.removeFlags();
  1018. }
  1019. for (L2SiegeClan sc : getDefenderClans())
  1020. {
  1021. if (sc != null)
  1022. sc.removeFlags();
  1023. }
  1024. }
  1025. /** Remove flags from defenders. */
  1026. private void removeDefenderFlags()
  1027. {
  1028. for (L2SiegeClan sc : getDefenderClans())
  1029. {
  1030. if (sc != null)
  1031. sc.removeFlags();
  1032. }
  1033. }
  1034. /** Save castle siege related to database. */
  1035. private void saveCastleSiege()
  1036. {
  1037. setNextSiegeDate(); // Set the next set date for 2 weeks from now
  1038. // Schedule Time registration end
  1039. getTimeRegistrationOverDate().setTimeInMillis(Calendar.getInstance().getTimeInMillis());
  1040. getTimeRegistrationOverDate().add(Calendar.DAY_OF_MONTH, 1);
  1041. getCastle().setIsTimeRegistrationOver(false);
  1042. saveSiegeDate(); // Save the new date
  1043. startAutoTask(); // Prepare auto start siege and end registration
  1044. }
  1045. /** Save siege date to database. */
  1046. public void saveSiegeDate()
  1047. {
  1048. if (_scheduledStartSiegeTask != null)
  1049. {
  1050. _scheduledStartSiegeTask.cancel(true);
  1051. _scheduledStartSiegeTask = ThreadPoolManager.getInstance().scheduleGeneral(new Siege.ScheduleStartSiegeTask(getCastle()), 1000);
  1052. }
  1053. Connection con = null;
  1054. try
  1055. {
  1056. con = L2DatabaseFactory.getInstance().getConnection();
  1057. PreparedStatement statement = con.prepareStatement("Update castle set siegeDate = ?, regTimeEnd = ?, regTimeOver = ? where id = ?");
  1058. statement.setLong(1, getSiegeDate().getTimeInMillis());
  1059. statement.setLong(2, getTimeRegistrationOverDate().getTimeInMillis());
  1060. statement.setString(3, String.valueOf(getIsTimeRegistrationOver()));
  1061. statement.setInt(4, getCastle().getCastleId());
  1062. statement.execute();
  1063. statement.close();
  1064. }
  1065. catch (Exception e)
  1066. {
  1067. _log.warning("Exception: saveSiegeDate(): " + e.getMessage());
  1068. e.printStackTrace();
  1069. }
  1070. finally
  1071. {
  1072. try
  1073. {
  1074. con.close();
  1075. }
  1076. catch (Exception e)
  1077. {
  1078. }
  1079. }
  1080. }
  1081. /**
  1082. * Save registration to database.<BR><BR>
  1083. * @param clan The L2Clan of player
  1084. * @param typeId -1 = owner 0 = defender, 1 = attacker, 2 = defender waiting
  1085. */
  1086. private void saveSiegeClan(L2Clan clan, int typeId, boolean isUpdateRegistration)
  1087. {
  1088. if (clan.getHasCastle() > 0)
  1089. return;
  1090. Connection con = null;
  1091. try
  1092. {
  1093. if (typeId == 0 || typeId == 2 || typeId == -1)
  1094. {
  1095. if (getDefenderClans().size() + getDefenderWaitingClans().size() >= SiegeManager.getInstance().getDefenderMaxClans())
  1096. return;
  1097. }
  1098. else
  1099. {
  1100. if (getAttackerClans().size() >= SiegeManager.getInstance().getAttackerMaxClans())
  1101. return;
  1102. }
  1103. con = L2DatabaseFactory.getInstance().getConnection();
  1104. PreparedStatement statement;
  1105. if (!isUpdateRegistration)
  1106. {
  1107. statement = con.prepareStatement("INSERT INTO siege_clans (clan_id,castle_id,type,castle_owner) values (?,?,?,0)");
  1108. statement.setInt(1, clan.getClanId());
  1109. statement.setInt(2, getCastle().getCastleId());
  1110. statement.setInt(3, typeId);
  1111. statement.execute();
  1112. statement.close();
  1113. }
  1114. else
  1115. {
  1116. statement = con.prepareStatement("Update siege_clans set type = ? where castle_id = ? and clan_id = ?");
  1117. statement.setInt(1, typeId);
  1118. statement.setInt(2, getCastle().getCastleId());
  1119. statement.setInt(3, clan.getClanId());
  1120. statement.execute();
  1121. statement.close();
  1122. }
  1123. if (typeId == 0 || typeId == -1)
  1124. {
  1125. addDefender(clan.getClanId());
  1126. announceToPlayer(clan.getName() + " has been registered to defend " + getCastle().getName(), false);
  1127. }
  1128. else if (typeId == 1)
  1129. {
  1130. addAttacker(clan.getClanId());
  1131. announceToPlayer(clan.getName() + " has been registered to attack " + getCastle().getName(), false);
  1132. }
  1133. else if (typeId == 2)
  1134. {
  1135. addDefenderWaiting(clan.getClanId());
  1136. announceToPlayer(clan.getName() + " has requested to defend " + getCastle().getName(), false);
  1137. }
  1138. }
  1139. catch (Exception e)
  1140. {
  1141. _log.warning("Exception: saveSiegeClan(L2Clan clan, int typeId, boolean isUpdateRegistration): " + e.getMessage());
  1142. e.printStackTrace();
  1143. }
  1144. finally
  1145. {
  1146. try
  1147. {
  1148. con.close();
  1149. }
  1150. catch (Exception e)
  1151. {
  1152. }
  1153. }
  1154. }
  1155. /** Set the date for the next siege. */
  1156. private void setNextSiegeDate()
  1157. {
  1158. while (getCastle().getSiegeDate().getTimeInMillis() < Calendar.getInstance().getTimeInMillis())
  1159. {
  1160. if (getCastle().getSiegeDate().get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY && getCastle().getSiegeDate().get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY)
  1161. getCastle().getSiegeDate().set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
  1162. // from CT2.3 Castle sieges are on Sunday, but if server admins allow to set day of the siege
  1163. // than sieges can occur on Saturdays as well
  1164. if (getCastle().getSiegeDate().get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY && !Config.CL_SET_SIEGE_TIME_LIST.contains("day"))
  1165. getCastle().getSiegeDate().set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
  1166. // set the next siege day to the next weekend
  1167. getCastle().getSiegeDate().add(Calendar.DAY_OF_MONTH, 7);
  1168. }
  1169. if (!SevenSigns.getInstance().isDateInSealValidPeriod(getCastle().getSiegeDate()))
  1170. getCastle().getSiegeDate().add(Calendar.DAY_OF_MONTH, 7);
  1171. _isRegistrationOver = false; // Allow registration for next siege
  1172. }
  1173. /** Spawn control tower. */
  1174. private void spawnControlTower(int Id)
  1175. {
  1176. //Set control tower array size if one does not exist
  1177. if (_controlTowers == null)
  1178. _controlTowers = new FastList<L2ControlTowerInstance>();
  1179. for (SiegeSpawn _sp : SiegeManager.getInstance().getControlTowerSpawnList(Id))
  1180. {
  1181. L2ControlTowerInstance ct;
  1182. L2NpcTemplate template = NpcTable.getInstance().getTemplate(_sp.getNpcId());
  1183. // TODO: Check/confirm if control towers have any special weapon resistances/vulnerabilities
  1184. // template.addVulnerability(Stats.BOW_WPN_VULN,0);
  1185. // template.addVulnerability(Stats.BLUNT_WPN_VULN,0);
  1186. // template.addVulnerability(Stats.DAGGER_WPN_VULN,0);
  1187. ct = new L2ControlTowerInstance(IdFactory.getInstance().getNextId(), template);
  1188. ct.setCurrentHpMp(_sp.getHp(), ct.getMaxMp());
  1189. ct.spawnMe(_sp.getLocation().getX(), _sp.getLocation().getY(), _sp.getLocation().getZ() + 20);
  1190. _controlTowerCount++;
  1191. _controlTowerMaxCount++;
  1192. _controlTowers.add(ct);
  1193. }
  1194. }
  1195. /**
  1196. * Spawn siege guard.<BR><BR>
  1197. */
  1198. private void spawnSiegeGuard()
  1199. {
  1200. getSiegeGuardManager().spawnSiegeGuard();
  1201. // Register guard to the closest Control Tower
  1202. // When CT dies, so do all the guards that it controls
  1203. if (!getSiegeGuardManager().getSiegeGuardSpawn().isEmpty() && !_controlTowers.isEmpty())
  1204. {
  1205. L2ControlTowerInstance closestCt;
  1206. double distance, x, y, z;
  1207. double distanceClosest = 0;
  1208. for (L2Spawn spawn : getSiegeGuardManager().getSiegeGuardSpawn())
  1209. {
  1210. if (spawn == null)
  1211. continue;
  1212. closestCt = null;
  1213. distanceClosest = 0;
  1214. for (L2ControlTowerInstance ct : _controlTowers)
  1215. {
  1216. if (ct == null)
  1217. continue;
  1218. x = (spawn.getLocx() - ct.getX());
  1219. y = (spawn.getLocy() - ct.getY());
  1220. z = (spawn.getLocz() - ct.getZ());
  1221. distance = (x * x) + (y * y) + (z * z);
  1222. if (closestCt == null || distance < distanceClosest)
  1223. {
  1224. closestCt = ct;
  1225. distanceClosest = distance;
  1226. }
  1227. }
  1228. if (closestCt != null)
  1229. closestCt.registerGuard(spawn);
  1230. }
  1231. }
  1232. }
  1233. public final L2SiegeClan getAttackerClan(L2Clan clan)
  1234. {
  1235. if (clan == null)
  1236. return null;
  1237. return getAttackerClan(clan.getClanId());
  1238. }
  1239. public final L2SiegeClan getAttackerClan(int clanId)
  1240. {
  1241. for (L2SiegeClan sc : getAttackerClans())
  1242. if (sc != null && sc.getClanId() == clanId)
  1243. return sc;
  1244. return null;
  1245. }
  1246. public final List<L2SiegeClan> getAttackerClans()
  1247. {
  1248. if (_isNormalSide)
  1249. return _attackerClans;
  1250. return _defenderClans;
  1251. }
  1252. public final int getAttackerRespawnDelay()
  1253. {
  1254. return (SiegeManager.getInstance().getAttackerRespawnDelay());
  1255. }
  1256. public final Castle getCastle()
  1257. {
  1258. if (_castle == null || _castle.length <= 0)
  1259. return null;
  1260. return _castle[0];
  1261. }
  1262. public final L2SiegeClan getDefenderClan(L2Clan clan)
  1263. {
  1264. if (clan == null)
  1265. return null;
  1266. return getDefenderClan(clan.getClanId());
  1267. }
  1268. public final L2SiegeClan getDefenderClan(int clanId)
  1269. {
  1270. for (L2SiegeClan sc : getDefenderClans())
  1271. if (sc != null && sc.getClanId() == clanId)
  1272. return sc;
  1273. return null;
  1274. }
  1275. public final List<L2SiegeClan> getDefenderClans()
  1276. {
  1277. if (_isNormalSide)
  1278. return _defenderClans;
  1279. return _attackerClans;
  1280. }
  1281. public final L2SiegeClan getDefenderWaitingClan(L2Clan clan)
  1282. {
  1283. if (clan == null)
  1284. return null;
  1285. return getDefenderWaitingClan(clan.getClanId());
  1286. }
  1287. public final L2SiegeClan getDefenderWaitingClan(int clanId)
  1288. {
  1289. for (L2SiegeClan sc : getDefenderWaitingClans())
  1290. if (sc != null && sc.getClanId() == clanId)
  1291. return sc;
  1292. return null;
  1293. }
  1294. public final List<L2SiegeClan> getDefenderWaitingClans()
  1295. {
  1296. return _defenderWaitingClans;
  1297. }
  1298. public final boolean getIsInProgress()
  1299. {
  1300. return _isInProgress;
  1301. }
  1302. public final boolean getIsRegistrationOver()
  1303. {
  1304. return _isRegistrationOver;
  1305. }
  1306. public final boolean getIsTimeRegistrationOver()
  1307. {
  1308. return getCastle().getIsTimeRegistrationOver();
  1309. }
  1310. public final Calendar getSiegeDate()
  1311. {
  1312. return getCastle().getSiegeDate();
  1313. }
  1314. public final Calendar getTimeRegistrationOverDate()
  1315. {
  1316. return getCastle().getTimeRegistrationOverDate();
  1317. }
  1318. public void endTimeRegistration(boolean automatic)
  1319. {
  1320. getCastle().setIsTimeRegistrationOver(true);
  1321. if (!automatic)
  1322. saveSiegeDate();
  1323. }
  1324. public List<L2Npc> getFlag(L2Clan clan)
  1325. {
  1326. if (clan != null)
  1327. {
  1328. L2SiegeClan sc = getAttackerClan(clan);
  1329. if (sc != null)
  1330. return sc.getFlag();
  1331. }
  1332. return null;
  1333. }
  1334. public final SiegeGuardManager getSiegeGuardManager()
  1335. {
  1336. if (_siegeGuardManager == null)
  1337. {
  1338. _siegeGuardManager = new SiegeGuardManager(getCastle());
  1339. }
  1340. return _siegeGuardManager;
  1341. }
  1342. public int getControlTowerCount()
  1343. {
  1344. return _controlTowerCount;
  1345. }
  1346. }