FortSiege.java 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266
  1. /*
  2. * Copyright (C) 2004-2015 L2J Server
  3. *
  4. * This file is part of L2J Server.
  5. *
  6. * L2J Server is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * L2J Server is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package com.l2jserver.gameserver.model.entity;
  20. import java.sql.Connection;
  21. import java.sql.PreparedStatement;
  22. import java.sql.ResultSet;
  23. import java.util.Calendar;
  24. import java.util.LinkedList;
  25. import java.util.List;
  26. import java.util.concurrent.CopyOnWriteArrayList;
  27. import java.util.concurrent.ScheduledFuture;
  28. import java.util.logging.Level;
  29. import java.util.logging.Logger;
  30. import com.l2jserver.Config;
  31. import com.l2jserver.commons.database.pool.impl.ConnectionFactory;
  32. import com.l2jserver.gameserver.ThreadPoolManager;
  33. import com.l2jserver.gameserver.data.sql.impl.ClanTable;
  34. import com.l2jserver.gameserver.enums.FortTeleportWhoType;
  35. import com.l2jserver.gameserver.instancemanager.FortManager;
  36. import com.l2jserver.gameserver.instancemanager.FortSiegeGuardManager;
  37. import com.l2jserver.gameserver.instancemanager.FortSiegeManager;
  38. import com.l2jserver.gameserver.instancemanager.TerritoryWarManager;
  39. import com.l2jserver.gameserver.model.CombatFlag;
  40. import com.l2jserver.gameserver.model.FortSiegeSpawn;
  41. import com.l2jserver.gameserver.model.L2Clan;
  42. import com.l2jserver.gameserver.model.L2Object;
  43. import com.l2jserver.gameserver.model.L2SiegeClan;
  44. import com.l2jserver.gameserver.model.L2SiegeClan.SiegeClanType;
  45. import com.l2jserver.gameserver.model.L2Spawn;
  46. import com.l2jserver.gameserver.model.PcCondOverride;
  47. import com.l2jserver.gameserver.model.TeleportWhereType;
  48. import com.l2jserver.gameserver.model.actor.L2Npc;
  49. import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
  50. import com.l2jserver.gameserver.model.actor.instance.L2FortCommanderInstance;
  51. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  52. import com.l2jserver.gameserver.model.events.EventDispatcher;
  53. import com.l2jserver.gameserver.model.events.impl.sieges.fort.OnFortSiegeFinish;
  54. import com.l2jserver.gameserver.model.events.impl.sieges.fort.OnFortSiegeStart;
  55. import com.l2jserver.gameserver.network.NpcStringId;
  56. import com.l2jserver.gameserver.network.SystemMessageId;
  57. import com.l2jserver.gameserver.network.clientpackets.Say2;
  58. import com.l2jserver.gameserver.network.serverpackets.NpcSay;
  59. import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
  60. public class FortSiege implements Siegable
  61. {
  62. protected static final Logger _log = Logger.getLogger(FortSiege.class.getName());
  63. // SQL
  64. private static final String DELETE_FORT_SIEGECLANS_BY_CLAN_ID = "DELETE FROM fortsiege_clans WHERE fort_id = ? AND clan_id = ?";
  65. private static final String DELETE_FORT_SIEGECLANS = "DELETE FROM fortsiege_clans WHERE fort_id = ?";
  66. public class ScheduleEndSiegeTask implements Runnable
  67. {
  68. @Override
  69. public void run()
  70. {
  71. if (!isInProgress())
  72. {
  73. return;
  74. }
  75. try
  76. {
  77. _siegeEnd = null;
  78. endSiege();
  79. }
  80. catch (Exception e)
  81. {
  82. _log.log(Level.WARNING, "Exception: ScheduleEndSiegeTask() for Fort: " + _fort.getName() + " " + e.getMessage(), e);
  83. }
  84. }
  85. }
  86. public class ScheduleStartSiegeTask implements Runnable
  87. {
  88. private final Fort _fortInst;
  89. private final int _time;
  90. public ScheduleStartSiegeTask(int time)
  91. {
  92. _fortInst = _fort;
  93. _time = time;
  94. }
  95. @Override
  96. public void run()
  97. {
  98. if (isInProgress())
  99. {
  100. return;
  101. }
  102. try
  103. {
  104. final SystemMessage sm;
  105. if (_time == 3600) // 1hr remains
  106. {
  107. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(600), 3000000); // Prepare task for 10 minutes left.
  108. }
  109. else if (_time == 600) // 10min remains
  110. {
  111. getFort().despawnSuspiciousMerchant();
  112. sm = SystemMessage.getSystemMessage(SystemMessageId.S1_MINUTES_UNTIL_THE_FORTRESS_BATTLE_STARTS);
  113. sm.addInt(10);
  114. announceToPlayer(sm);
  115. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(300), 300000); // Prepare task for 5 minutes left.
  116. }
  117. else if (_time == 300) // 5min remains
  118. {
  119. sm = SystemMessage.getSystemMessage(SystemMessageId.S1_MINUTES_UNTIL_THE_FORTRESS_BATTLE_STARTS);
  120. sm.addInt(5);
  121. announceToPlayer(sm);
  122. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(60), 240000); // Prepare task for 1 minute left.
  123. }
  124. else if (_time == 60) // 1min remains
  125. {
  126. sm = SystemMessage.getSystemMessage(SystemMessageId.S1_MINUTES_UNTIL_THE_FORTRESS_BATTLE_STARTS);
  127. sm.addInt(1);
  128. announceToPlayer(sm);
  129. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(30), 30000); // Prepare task for 30 seconds left.
  130. }
  131. else if (_time == 30) // 30seconds remains
  132. {
  133. sm = SystemMessage.getSystemMessage(SystemMessageId.S1_SECONDS_UNTIL_THE_FORTRESS_BATTLE_STARTS);
  134. sm.addInt(30);
  135. announceToPlayer(sm);
  136. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(10), 20000); // Prepare task for 10 seconds left.
  137. }
  138. else if (_time == 10) // 10seconds remains
  139. {
  140. sm = SystemMessage.getSystemMessage(SystemMessageId.S1_SECONDS_UNTIL_THE_FORTRESS_BATTLE_STARTS);
  141. sm.addInt(10);
  142. announceToPlayer(sm);
  143. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(5), 5000); // Prepare task for 5 seconds left.
  144. }
  145. else if (_time == 5) // 5seconds remains
  146. {
  147. sm = SystemMessage.getSystemMessage(SystemMessageId.S1_SECONDS_UNTIL_THE_FORTRESS_BATTLE_STARTS);
  148. sm.addInt(5);
  149. announceToPlayer(sm);
  150. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(1), 4000); // Prepare task for 1 seconds left.
  151. }
  152. else if (_time == 1) // 1seconds remains
  153. {
  154. sm = SystemMessage.getSystemMessage(SystemMessageId.S1_SECONDS_UNTIL_THE_FORTRESS_BATTLE_STARTS);
  155. sm.addInt(1);
  156. announceToPlayer(sm);
  157. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(0), 1000); // Prepare task start siege.
  158. }
  159. else if (_time == 0)// start siege
  160. {
  161. _fortInst.getSiege().startSiege();
  162. }
  163. else
  164. {
  165. _log.warning("Exception: ScheduleStartSiegeTask(): unknown siege time: " + String.valueOf(_time));
  166. }
  167. }
  168. catch (Exception e)
  169. {
  170. _log.log(Level.WARNING, "Exception: ScheduleStartSiegeTask() for Fort: " + _fortInst.getName() + " " + e.getMessage(), e);
  171. }
  172. }
  173. }
  174. public class ScheduleSuspiciousMerchantSpawn implements Runnable
  175. {
  176. @Override
  177. public void run()
  178. {
  179. if (isInProgress())
  180. {
  181. return;
  182. }
  183. try
  184. {
  185. _fort.spawnSuspiciousMerchant();
  186. }
  187. catch (Exception e)
  188. {
  189. _log.log(Level.WARNING, "Exception: ScheduleSuspicoiusMerchantSpawn() for Fort: " + _fort.getName() + " " + e.getMessage(), e);
  190. }
  191. }
  192. }
  193. public class ScheduleSiegeRestore implements Runnable
  194. {
  195. @Override
  196. public void run()
  197. {
  198. if (!isInProgress())
  199. {
  200. return;
  201. }
  202. try
  203. {
  204. _siegeRestore = null;
  205. resetSiege();
  206. announceToPlayer(SystemMessage.getSystemMessage(SystemMessageId.BARRACKS_FUNCTION_RESTORED));
  207. }
  208. catch (Exception e)
  209. {
  210. _log.log(Level.WARNING, "Exception: ScheduleSiegeRestore() for Fort: " + _fort.getName() + " " + e.getMessage(), e);
  211. }
  212. }
  213. }
  214. private final List<L2SiegeClan> _attackerClans = new CopyOnWriteArrayList<>();
  215. // Fort setting
  216. protected List<L2Spawn> _commanders = new CopyOnWriteArrayList<>();
  217. protected final Fort _fort;
  218. private boolean _isInProgress = false;
  219. private FortSiegeGuardManager _siegeGuardManager;
  220. ScheduledFuture<?> _siegeEnd = null;
  221. ScheduledFuture<?> _siegeRestore = null;
  222. ScheduledFuture<?> _siegeStartTask = null;
  223. public FortSiege(Fort fort)
  224. {
  225. _fort = fort;
  226. checkAutoTask();
  227. FortSiegeManager.getInstance().addSiege(this);
  228. }
  229. /**
  230. * When siege ends.
  231. */
  232. @Override
  233. public void endSiege()
  234. {
  235. if (isInProgress())
  236. {
  237. _isInProgress = false; // Flag so that siege instance can be started
  238. removeFlags(); // Removes all flags. Note: Remove flag before teleporting players
  239. unSpawnFlags();
  240. updatePlayerSiegeStateFlags(true);
  241. int ownerId = -1;
  242. if (getFort().getOwnerClan() != null)
  243. {
  244. ownerId = getFort().getOwnerClan().getId();
  245. }
  246. getFort().getZone().banishForeigners(ownerId);
  247. getFort().getZone().setIsActive(false);
  248. getFort().getZone().updateZoneStatusForCharactersInside();
  249. getFort().getZone().setSiegeInstance(null);
  250. saveFortSiege(); // Save fort specific data
  251. clearSiegeClan(); // Clear siege clan from db
  252. removeCommanders(); // Remove commander from this fort
  253. getFort().spawnNpcCommanders(); // Spawn NPC commanders
  254. getSiegeGuardManager().unspawnSiegeGuard(); // Remove all spawned siege guard from this fort
  255. getFort().resetDoors(); // Respawn door to fort
  256. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleSuspiciousMerchantSpawn(), FortSiegeManager.getInstance().getSuspiciousMerchantRespawnDelay() * 60 * 1000L); // Prepare 3hr task for suspicious merchant respawn
  257. setSiegeDateTime(true); // store suspicious merchant spawn in DB
  258. if (_siegeEnd != null)
  259. {
  260. _siegeEnd.cancel(true);
  261. _siegeEnd = null;
  262. }
  263. if (_siegeRestore != null)
  264. {
  265. _siegeRestore.cancel(true);
  266. _siegeRestore = null;
  267. }
  268. if ((getFort().getOwnerClan() != null) && (getFort().getFlagPole().getMeshIndex() == 0))
  269. {
  270. getFort().setVisibleFlag(true);
  271. }
  272. _log.info("Siege of " + getFort().getName() + " fort finished.");
  273. // Notify to scripts.
  274. EventDispatcher.getInstance().notifyEventAsync(new OnFortSiegeFinish(this), getFort());
  275. }
  276. }
  277. /**
  278. * When siege starts
  279. */
  280. @Override
  281. public void startSiege()
  282. {
  283. if (!isInProgress())
  284. {
  285. if (_siegeStartTask != null) // used admin command "admin_startfortsiege"
  286. {
  287. _siegeStartTask.cancel(true);
  288. getFort().despawnSuspiciousMerchant();
  289. }
  290. _siegeStartTask = null;
  291. if (getAttackerClans().isEmpty())
  292. {
  293. return;
  294. }
  295. _isInProgress = true; // Flag so that same siege instance cannot be started again
  296. loadSiegeClan(); // Load siege clan from db
  297. updatePlayerSiegeStateFlags(false);
  298. teleportPlayer(FortTeleportWhoType.Attacker, TeleportWhereType.TOWN); // Teleport to the closest town
  299. getFort().despawnNpcCommanders(); // Despawn NPC commanders
  300. spawnCommanders(); // Spawn commanders
  301. getFort().resetDoors(); // Spawn door
  302. spawnSiegeGuard(); // Spawn siege guard
  303. getFort().setVisibleFlag(false);
  304. getFort().getZone().setSiegeInstance(this);
  305. getFort().getZone().setIsActive(true);
  306. getFort().getZone().updateZoneStatusForCharactersInside();
  307. // Schedule a task to prepare auto siege end
  308. _siegeEnd = ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleEndSiegeTask(), FortSiegeManager.getInstance().getSiegeLength() * 60 * 1000L); // Prepare auto end task
  309. final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.THE_FORTRESS_BATTLE_S1_HAS_BEGUN);
  310. sm.addCastleId(getFort().getResidenceId());
  311. announceToPlayer(sm);
  312. saveFortSiege();
  313. _log.info("Siege of " + getFort().getName() + " fort started.");
  314. // Notify to scripts.
  315. EventDispatcher.getInstance().notifyEventAsync(new OnFortSiegeStart(this), getFort());
  316. }
  317. }
  318. /**
  319. * Announce to player.
  320. * @param sm the system message to send to player
  321. */
  322. public void announceToPlayer(SystemMessage sm)
  323. {
  324. // announce messages only for participants
  325. L2Clan clan;
  326. for (L2SiegeClan siegeclan : getAttackerClans())
  327. {
  328. clan = ClanTable.getInstance().getClan(siegeclan.getClanId());
  329. for (L2PcInstance member : clan.getOnlineMembers(0))
  330. {
  331. member.sendPacket(sm);
  332. }
  333. }
  334. if (getFort().getOwnerClan() != null)
  335. {
  336. clan = ClanTable.getInstance().getClan(getFort().getOwnerClan().getId());
  337. for (L2PcInstance member : clan.getOnlineMembers(0))
  338. {
  339. if (member != null)
  340. {
  341. member.sendPacket(sm);
  342. }
  343. }
  344. }
  345. }
  346. public void announceToPlayer(SystemMessage sm, String s)
  347. {
  348. sm.addString(s);
  349. announceToPlayer(sm);
  350. }
  351. public void updatePlayerSiegeStateFlags(boolean clear)
  352. {
  353. L2Clan clan;
  354. for (L2SiegeClan siegeclan : getAttackerClans())
  355. {
  356. clan = ClanTable.getInstance().getClan(siegeclan.getClanId());
  357. for (L2PcInstance member : clan.getOnlineMembers(0))
  358. {
  359. if (clear)
  360. {
  361. member.setSiegeState((byte) 0);
  362. member.setSiegeSide(0);
  363. member.setIsInSiege(false);
  364. member.stopFameTask();
  365. }
  366. else
  367. {
  368. member.setSiegeState((byte) 1);
  369. member.setSiegeSide(getFort().getResidenceId());
  370. if (checkIfInZone(member))
  371. {
  372. member.setIsInSiege(true);
  373. member.startFameTask(Config.FORTRESS_ZONE_FAME_TASK_FREQUENCY * 1000, Config.FORTRESS_ZONE_FAME_AQUIRE_POINTS);
  374. }
  375. }
  376. member.broadcastUserInfo();
  377. }
  378. }
  379. if (getFort().getOwnerClan() != null)
  380. {
  381. clan = ClanTable.getInstance().getClan(getFort().getOwnerClan().getId());
  382. for (L2PcInstance member : clan.getOnlineMembers(0))
  383. {
  384. if (member == null)
  385. {
  386. continue;
  387. }
  388. if (clear)
  389. {
  390. member.setSiegeState((byte) 0);
  391. member.setSiegeSide(0);
  392. member.setIsInSiege(false);
  393. member.stopFameTask();
  394. }
  395. else
  396. {
  397. member.setSiegeState((byte) 2);
  398. member.setSiegeSide(getFort().getResidenceId());
  399. if (checkIfInZone(member))
  400. {
  401. member.setIsInSiege(true);
  402. member.startFameTask(Config.FORTRESS_ZONE_FAME_TASK_FREQUENCY * 1000, Config.FORTRESS_ZONE_FAME_AQUIRE_POINTS);
  403. }
  404. }
  405. member.broadcastUserInfo();
  406. }
  407. }
  408. }
  409. /**
  410. * @param object
  411. * @return true if object is inside the zone
  412. */
  413. public boolean checkIfInZone(L2Object object)
  414. {
  415. return checkIfInZone(object.getX(), object.getY(), object.getZ());
  416. }
  417. /**
  418. * @param x
  419. * @param y
  420. * @param z
  421. * @return true if object is inside the zone
  422. */
  423. public boolean checkIfInZone(int x, int y, int z)
  424. {
  425. return (isInProgress() && (getFort().checkIfInZone(x, y, z))); // Fort zone during siege
  426. }
  427. /**
  428. * @param clan The L2Clan of the player
  429. * @return true if clan is attacker
  430. */
  431. @Override
  432. public boolean checkIsAttacker(L2Clan clan)
  433. {
  434. return (getAttackerClan(clan) != null);
  435. }
  436. /**
  437. * @param clan The L2Clan of the player
  438. * @return true if clan is defender
  439. */
  440. @Override
  441. public boolean checkIsDefender(L2Clan clan)
  442. {
  443. if ((clan != null) && (getFort().getOwnerClan() == clan))
  444. {
  445. return true;
  446. }
  447. return false;
  448. }
  449. /** Clear all registered siege clans from database for fort */
  450. public void clearSiegeClan()
  451. {
  452. try (Connection con = ConnectionFactory.getInstance().getConnection();
  453. PreparedStatement ps = con.prepareStatement("DELETE FROM fortsiege_clans WHERE fort_id=?"))
  454. {
  455. ps.setInt(1, getFort().getResidenceId());
  456. ps.execute();
  457. if (getFort().getOwnerClan() != null)
  458. {
  459. try (PreparedStatement delete = con.prepareStatement("DELETE FROM fortsiege_clans WHERE clan_id=?"))
  460. {
  461. delete.setInt(1, getFort().getOwnerClan().getId());
  462. delete.execute();
  463. }
  464. }
  465. getAttackerClans().clear();
  466. // if siege is in progress, end siege
  467. if (isInProgress())
  468. {
  469. endSiege();
  470. }
  471. // if siege isn't in progress (1hr waiting time till siege starts), cancel waiting time
  472. if (_siegeStartTask != null)
  473. {
  474. _siegeStartTask.cancel(true);
  475. _siegeStartTask = null;
  476. }
  477. }
  478. catch (Exception e)
  479. {
  480. _log.log(Level.WARNING, "Exception: clearSiegeClan(): " + e.getMessage(), e);
  481. }
  482. }
  483. /** Set the date for the next siege. */
  484. private void clearSiegeDate()
  485. {
  486. getFort().getSiegeDate().setTimeInMillis(0);
  487. }
  488. /**
  489. * @return list of L2PcInstance registered as attacker in the zone.
  490. */
  491. @Override
  492. public List<L2PcInstance> getAttackersInZone()
  493. {
  494. final List<L2PcInstance> players = new LinkedList<>();
  495. for (L2SiegeClan siegeclan : getAttackerClans())
  496. {
  497. L2Clan clan = ClanTable.getInstance().getClan(siegeclan.getClanId());
  498. for (L2PcInstance player : clan.getOnlineMembers(0))
  499. {
  500. if (player.isInSiege())
  501. {
  502. players.add(player);
  503. }
  504. }
  505. }
  506. return players;
  507. }
  508. /**
  509. * @return list of L2PcInstance in the zone.
  510. */
  511. public List<L2PcInstance> getPlayersInZone()
  512. {
  513. return getFort().getZone().getPlayersInside();
  514. }
  515. /**
  516. * @return list of L2PcInstance owning the fort in the zone.
  517. */
  518. public List<L2PcInstance> getOwnersInZone()
  519. {
  520. final List<L2PcInstance> players = new LinkedList<>();
  521. if (getFort().getOwnerClan() != null)
  522. {
  523. L2Clan clan = ClanTable.getInstance().getClan(getFort().getOwnerClan().getId());
  524. if (clan != getFort().getOwnerClan())
  525. {
  526. return null;
  527. }
  528. for (L2PcInstance player : clan.getOnlineMembers(0))
  529. {
  530. if (player.isInSiege())
  531. {
  532. players.add(player);
  533. }
  534. }
  535. }
  536. return players;
  537. }
  538. /**
  539. * TODO: To DP AI<br>
  540. * Commander was killed
  541. * @param instance
  542. */
  543. public void killedCommander(L2FortCommanderInstance instance)
  544. {
  545. if (!_commanders.isEmpty() && (getFort() != null))
  546. {
  547. L2Spawn spawn = instance.getSpawn();
  548. if (spawn != null)
  549. {
  550. List<FortSiegeSpawn> commanders = FortSiegeManager.getInstance().getCommanderSpawnList(getFort().getResidenceId());
  551. for (FortSiegeSpawn spawn2 : commanders)
  552. {
  553. if (spawn2.getId() == spawn.getId())
  554. {
  555. NpcStringId npcString = null;
  556. switch (spawn2.getMessageId())
  557. {
  558. case 1:
  559. npcString = NpcStringId.YOU_MAY_HAVE_BROKEN_OUR_ARROWS_BUT_YOU_WILL_NEVER_BREAK_OUR_WILL_ARCHERS_RETREAT;
  560. break;
  561. case 2:
  562. npcString = NpcStringId.AIIEEEE_COMMAND_CENTER_THIS_IS_GUARD_UNIT_WE_NEED_BACKUP_RIGHT_AWAY;
  563. break;
  564. case 3:
  565. npcString = NpcStringId.AT_LAST_THE_MAGIC_FIELD_THAT_PROTECTS_THE_FORTRESS_HAS_WEAKENED_VOLUNTEERS_STAND_BACK;
  566. break;
  567. case 4:
  568. npcString = NpcStringId.I_FEEL_SO_MUCH_GRIEF_THAT_I_CANT_EVEN_TAKE_CARE_OF_MYSELF_THERE_ISNT_ANY_REASON_FOR_ME_TO_STAY_HERE_ANY_LONGER;
  569. break;
  570. }
  571. if (npcString != null)
  572. {
  573. instance.broadcastPacket(new NpcSay(instance.getObjectId(), Say2.NPC_SHOUT, instance.getId(), npcString));
  574. }
  575. }
  576. }
  577. _commanders.remove(spawn);
  578. if (_commanders.isEmpty())
  579. {
  580. // spawn fort flags
  581. spawnFlag(getFort().getResidenceId());
  582. // cancel door/commanders respawn
  583. if (_siegeRestore != null)
  584. {
  585. _siegeRestore.cancel(true);
  586. }
  587. // open doors in main building
  588. for (L2DoorInstance door : getFort().getDoors())
  589. {
  590. if (door.getIsShowHp())
  591. {
  592. continue;
  593. }
  594. // TODO this also opens control room door at big fort
  595. door.openMe();
  596. }
  597. getFort().getSiege().announceToPlayer(SystemMessage.getSystemMessage(SystemMessageId.ALL_BARRACKS_OCCUPIED));
  598. }
  599. // schedule restoring doors/commanders respawn
  600. else if (_siegeRestore == null)
  601. {
  602. getFort().getSiege().announceToPlayer(SystemMessage.getSystemMessage(SystemMessageId.SEIZED_BARRACKS));
  603. _siegeRestore = ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleSiegeRestore(), FortSiegeManager.getInstance().getCountDownLength() * 60 * 1000L);
  604. }
  605. else
  606. {
  607. getFort().getSiege().announceToPlayer(SystemMessage.getSystemMessage(SystemMessageId.SEIZED_BARRACKS));
  608. }
  609. }
  610. else
  611. {
  612. _log.warning("FortSiege.killedCommander(): killed commander, but commander not registered for fortress. NpcId: " + instance.getId() + " FortId: " + getFort().getResidenceId());
  613. }
  614. }
  615. }
  616. /**
  617. * Remove the flag that was killed
  618. * @param flag
  619. */
  620. public void killedFlag(L2Npc flag)
  621. {
  622. if (flag == null)
  623. {
  624. return;
  625. }
  626. for (L2SiegeClan clan : getAttackerClans())
  627. {
  628. if (clan.removeFlag(flag))
  629. {
  630. return;
  631. }
  632. }
  633. }
  634. /**
  635. * Register clan as attacker.<BR>
  636. * @param player The L2PcInstance of the player trying to register.
  637. * @param checkConditions True if should be checked conditions, false otherwise
  638. * @return Number that defines what happened. <BR>
  639. * 0 - Player don't have clan.<BR>
  640. * 1 - Player don't have enough adena to register.<BR>
  641. * 2 - Is not right time to register Fortress now.<BR>
  642. * 3 - Players clan is already registered to siege.<BR>
  643. * 4 - Players clan is successfully registered to siege.
  644. */
  645. public int addAttacker(L2PcInstance player, boolean checkConditions)
  646. {
  647. if (player.getClan() == null)
  648. {
  649. return 0; // Player dont have clan
  650. }
  651. if (checkConditions)
  652. {
  653. if (getFort().getSiege().getAttackerClans().isEmpty() && (player.getInventory().getAdena() < 250000))
  654. {
  655. return 1; // Player dont havee enough adena to register
  656. }
  657. else if ((System.currentTimeMillis() < TerritoryWarManager.getInstance().getTWStartTimeInMillis()) && TerritoryWarManager.getInstance().getIsRegistrationOver())
  658. {
  659. return 2; // Is not right time to register Fortress now
  660. }
  661. if ((System.currentTimeMillis() > TerritoryWarManager.getInstance().getTWStartTimeInMillis()) && TerritoryWarManager.getInstance().isTWChannelOpen())
  662. {
  663. return 2; // Is not right time to register Fortress now
  664. }
  665. for (Fort fort : FortManager.getInstance().getForts())
  666. {
  667. if (fort.getSiege().getAttackerClan(player.getClanId()) != null)
  668. {
  669. return 3; // Players clan is already registred to siege
  670. }
  671. if ((fort.getOwnerClan() == player.getClan()) && (fort.getSiege().isInProgress() || (fort.getSiege()._siegeStartTask != null)))
  672. {
  673. return 3; // Players clan is already registred to siege
  674. }
  675. }
  676. }
  677. saveSiegeClan(player.getClan());
  678. if (getAttackerClans().size() == 1)
  679. {
  680. if (checkConditions)
  681. {
  682. player.reduceAdena("FortressSiege", 250000, null, true);
  683. }
  684. startAutoTask(true);
  685. }
  686. return 4; // Players clan is successfully registred to siege
  687. }
  688. /**
  689. * Remove clan from siege
  690. * @param clan The clan being removed
  691. */
  692. public void removeAttacker(L2Clan clan)
  693. {
  694. if ((clan == null) || (clan.getFortId() == getFort().getResidenceId()) || !FortSiegeManager.getInstance().checkIsRegistered(clan, getFort().getResidenceId()))
  695. {
  696. return;
  697. }
  698. removeSiegeClan(clan.getId());
  699. }
  700. /**
  701. * This function does not do any checks and should not be called from bypass !
  702. * @param clanId
  703. */
  704. private void removeSiegeClan(int clanId)
  705. {
  706. final String query = (clanId != 0) ? DELETE_FORT_SIEGECLANS_BY_CLAN_ID : DELETE_FORT_SIEGECLANS;
  707. try (Connection con = ConnectionFactory.getInstance().getConnection();
  708. PreparedStatement ps = con.prepareStatement(query))
  709. {
  710. ps.setInt(1, getFort().getResidenceId());
  711. if (clanId != 0)
  712. {
  713. ps.setInt(2, clanId);
  714. }
  715. ps.execute();
  716. loadSiegeClan();
  717. if (getAttackerClans().isEmpty())
  718. {
  719. if (isInProgress())
  720. {
  721. endSiege();
  722. }
  723. else
  724. {
  725. saveFortSiege(); // Clear siege time in DB
  726. }
  727. if (_siegeStartTask != null)
  728. {
  729. _siegeStartTask.cancel(true);
  730. _siegeStartTask = null;
  731. }
  732. }
  733. }
  734. catch (Exception e)
  735. {
  736. _log.log(Level.WARNING, "Exception on removeSiegeClan: " + e.getMessage(), e);
  737. }
  738. }
  739. /**
  740. * Start the auto tasks
  741. */
  742. public void checkAutoTask()
  743. {
  744. if (_siegeStartTask != null)
  745. {
  746. return;
  747. }
  748. final long delay = getFort().getSiegeDate().getTimeInMillis() - Calendar.getInstance().getTimeInMillis();
  749. if (delay < 0)
  750. {
  751. // siege time in past
  752. saveFortSiege();
  753. clearSiegeClan(); // remove all clans
  754. // spawn suspicious merchant immediately
  755. ThreadPoolManager.getInstance().executeGeneral(new ScheduleSuspiciousMerchantSpawn());
  756. }
  757. else
  758. {
  759. loadSiegeClan();
  760. if (getAttackerClans().isEmpty())
  761. {
  762. // no attackers - waiting for suspicious merchant spawn
  763. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleSuspiciousMerchantSpawn(), delay);
  764. }
  765. else
  766. {
  767. // preparing start siege task
  768. if (delay > 3600000) // more than hour, how this can happens ? spawn suspicious merchant
  769. {
  770. ThreadPoolManager.getInstance().executeGeneral(new ScheduleSuspiciousMerchantSpawn());
  771. _siegeStartTask = ThreadPoolManager.getInstance().scheduleGeneral(new FortSiege.ScheduleStartSiegeTask(3600), delay - 3600000);
  772. }
  773. if (delay > 600000) // more than 10 min, spawn suspicious merchant
  774. {
  775. ThreadPoolManager.getInstance().executeGeneral(new ScheduleSuspiciousMerchantSpawn());
  776. _siegeStartTask = ThreadPoolManager.getInstance().scheduleGeneral(new FortSiege.ScheduleStartSiegeTask(600), delay - 600000);
  777. }
  778. else if (delay > 300000)
  779. {
  780. _siegeStartTask = ThreadPoolManager.getInstance().scheduleGeneral(new FortSiege.ScheduleStartSiegeTask(300), delay - 300000);
  781. }
  782. else if (delay > 60000)
  783. {
  784. _siegeStartTask = ThreadPoolManager.getInstance().scheduleGeneral(new FortSiege.ScheduleStartSiegeTask(60), delay - 60000);
  785. }
  786. else
  787. {
  788. // lower than 1 min, set to 1 min
  789. _siegeStartTask = ThreadPoolManager.getInstance().scheduleGeneral(new FortSiege.ScheduleStartSiegeTask(60), 0);
  790. }
  791. _log.info("Siege of " + getFort().getName() + " fort: " + getFort().getSiegeDate().getTime());
  792. }
  793. }
  794. }
  795. /**
  796. * Start the auto task
  797. * @param setTime
  798. */
  799. public void startAutoTask(boolean setTime)
  800. {
  801. if (_siegeStartTask != null)
  802. {
  803. return;
  804. }
  805. if (setTime)
  806. {
  807. setSiegeDateTime(false);
  808. }
  809. if (getFort().getOwnerClan() != null)
  810. {
  811. getFort().getOwnerClan().broadcastToOnlineMembers(SystemMessage.getSystemMessage(SystemMessageId.A_FORTRESS_IS_UNDER_ATTACK));
  812. }
  813. // Execute siege auto start
  814. _siegeStartTask = ThreadPoolManager.getInstance().scheduleGeneral(new FortSiege.ScheduleStartSiegeTask(3600), 0);
  815. }
  816. /**
  817. * Teleport players
  818. * @param teleportWho
  819. * @param teleportWhere
  820. */
  821. public void teleportPlayer(FortTeleportWhoType teleportWho, TeleportWhereType teleportWhere)
  822. {
  823. List<L2PcInstance> players;
  824. switch (teleportWho)
  825. {
  826. case Owner:
  827. players = getOwnersInZone();
  828. break;
  829. case Attacker:
  830. players = getAttackersInZone();
  831. break;
  832. default:
  833. players = getPlayersInZone();
  834. }
  835. for (L2PcInstance player : players)
  836. {
  837. if (player.canOverrideCond(PcCondOverride.FORTRESS_CONDITIONS) || player.isJailed())
  838. {
  839. continue;
  840. }
  841. player.teleToLocation(teleportWhere);
  842. }
  843. }
  844. /**
  845. * Add clan as attacker<
  846. * @param clanId
  847. */
  848. private void addAttacker(int clanId)
  849. {
  850. getAttackerClans().add(new L2SiegeClan(clanId, SiegeClanType.ATTACKER)); // Add registered attacker to attacker list
  851. }
  852. /**
  853. * @param clan
  854. * @return {@code true} if the clan has already registered to a siege for the same day, {@code false} otherwise.
  855. */
  856. public boolean checkIfAlreadyRegisteredForSameDay(L2Clan clan)
  857. {
  858. for (FortSiege siege : FortSiegeManager.getInstance().getSieges())
  859. {
  860. if (siege == this)
  861. {
  862. continue;
  863. }
  864. if (siege.getSiegeDate().get(Calendar.DAY_OF_WEEK) == getSiegeDate().get(Calendar.DAY_OF_WEEK))
  865. {
  866. if (siege.checkIsAttacker(clan))
  867. {
  868. return true;
  869. }
  870. if (siege.checkIsDefender(clan))
  871. {
  872. return true;
  873. }
  874. }
  875. }
  876. return false;
  877. }
  878. private void setSiegeDateTime(boolean merchant)
  879. {
  880. Calendar newDate = Calendar.getInstance();
  881. if (merchant)
  882. {
  883. newDate.add(Calendar.MINUTE, FortSiegeManager.getInstance().getSuspiciousMerchantRespawnDelay());
  884. }
  885. else
  886. {
  887. newDate.add(Calendar.MINUTE, 60);
  888. }
  889. getFort().setSiegeDate(newDate);
  890. saveSiegeDate();
  891. }
  892. /** Load siege clans. */
  893. private void loadSiegeClan()
  894. {
  895. getAttackerClans().clear();
  896. try (Connection con = ConnectionFactory.getInstance().getConnection();
  897. PreparedStatement ps = con.prepareStatement("SELECT clan_id FROM fortsiege_clans WHERE fort_id=?"))
  898. {
  899. ps.setInt(1, getFort().getResidenceId());
  900. try (ResultSet rs = ps.executeQuery())
  901. {
  902. while (rs.next())
  903. {
  904. addAttacker(rs.getInt("clan_id"));
  905. }
  906. }
  907. }
  908. catch (Exception e)
  909. {
  910. _log.log(Level.WARNING, "Exception: loadSiegeClan(): " + e.getMessage(), e);
  911. }
  912. }
  913. /** Remove commanders. */
  914. private void removeCommanders()
  915. {
  916. if ((_commanders != null) && !_commanders.isEmpty())
  917. {
  918. // Remove all instance of commanders for this fort
  919. for (L2Spawn spawn : _commanders)
  920. {
  921. if (spawn != null)
  922. {
  923. spawn.stopRespawn();
  924. if (spawn.getLastSpawn() != null)
  925. {
  926. spawn.getLastSpawn().deleteMe();
  927. }
  928. }
  929. }
  930. _commanders.clear();
  931. }
  932. }
  933. /** Remove all flags. */
  934. private void removeFlags()
  935. {
  936. for (L2SiegeClan sc : getAttackerClans())
  937. {
  938. if (sc != null)
  939. {
  940. sc.removeFlags();
  941. }
  942. }
  943. }
  944. /** Save fort siege related to database. */
  945. private void saveFortSiege()
  946. {
  947. clearSiegeDate(); // clear siege date
  948. saveSiegeDate(); // Save the new date
  949. }
  950. /** Save siege date to database. */
  951. private void saveSiegeDate()
  952. {
  953. try (Connection con = ConnectionFactory.getInstance().getConnection();
  954. PreparedStatement ps = con.prepareStatement("UPDATE fort SET siegeDate = ? WHERE id = ?"))
  955. {
  956. ps.setLong(1, getSiegeDate().getTimeInMillis());
  957. ps.setInt(2, getFort().getResidenceId());
  958. ps.execute();
  959. }
  960. catch (Exception e)
  961. {
  962. _log.log(Level.WARNING, "Exception: saveSiegeDate(): " + e.getMessage(), e);
  963. }
  964. }
  965. /**
  966. * Save registration to database.
  967. * @param clan
  968. */
  969. private void saveSiegeClan(L2Clan clan)
  970. {
  971. if (getAttackerClans().size() >= FortSiegeManager.getInstance().getAttackerMaxClans())
  972. {
  973. return;
  974. }
  975. try (Connection con = ConnectionFactory.getInstance().getConnection();
  976. PreparedStatement ps = con.prepareStatement("INSERT INTO fortsiege_clans (clan_id,fort_id) values (?,?)"))
  977. {
  978. ps.setInt(1, clan.getId());
  979. ps.setInt(2, getFort().getResidenceId());
  980. ps.execute();
  981. addAttacker(clan.getId());
  982. }
  983. catch (Exception e)
  984. {
  985. _log.log(Level.WARNING, "Exception: saveSiegeClan(L2Clan clan): " + e.getMessage(), e);
  986. }
  987. }
  988. /** Spawn commanders. */
  989. private void spawnCommanders()
  990. {
  991. // Set commanders array size if one does not exist
  992. try
  993. {
  994. _commanders.clear();
  995. for (FortSiegeSpawn _sp : FortSiegeManager.getInstance().getCommanderSpawnList(getFort().getResidenceId()))
  996. {
  997. final L2Spawn spawnDat = new L2Spawn(_sp.getId());
  998. spawnDat.setAmount(1);
  999. spawnDat.setX(_sp.getLocation().getX());
  1000. spawnDat.setY(_sp.getLocation().getY());
  1001. spawnDat.setZ(_sp.getLocation().getZ());
  1002. spawnDat.setHeading(_sp.getLocation().getHeading());
  1003. spawnDat.setRespawnDelay(60);
  1004. spawnDat.doSpawn();
  1005. spawnDat.stopRespawn();
  1006. _commanders.add(spawnDat);
  1007. }
  1008. }
  1009. catch (Exception e)
  1010. {
  1011. // problem with initializing spawn, go to next one
  1012. _log.log(Level.WARNING, "FortSiege.spawnCommander: Spawn could not be initialized: " + e.getMessage(), e);
  1013. }
  1014. }
  1015. private void spawnFlag(int Id)
  1016. {
  1017. for (CombatFlag cf : FortSiegeManager.getInstance().getFlagList(Id))
  1018. {
  1019. cf.spawnMe();
  1020. }
  1021. }
  1022. private void unSpawnFlags()
  1023. {
  1024. if (FortSiegeManager.getInstance().getFlagList(getFort().getResidenceId()) == null)
  1025. {
  1026. return;
  1027. }
  1028. for (CombatFlag cf : FortSiegeManager.getInstance().getFlagList(getFort().getResidenceId()))
  1029. {
  1030. cf.unSpawnMe();
  1031. }
  1032. }
  1033. /**
  1034. * Spawn siege guard.
  1035. */
  1036. private void spawnSiegeGuard()
  1037. {
  1038. getSiegeGuardManager().spawnSiegeGuard();
  1039. }
  1040. @Override
  1041. public final L2SiegeClan getAttackerClan(L2Clan clan)
  1042. {
  1043. if (clan == null)
  1044. {
  1045. return null;
  1046. }
  1047. return getAttackerClan(clan.getId());
  1048. }
  1049. @Override
  1050. public final L2SiegeClan getAttackerClan(int clanId)
  1051. {
  1052. for (L2SiegeClan sc : getAttackerClans())
  1053. {
  1054. if ((sc != null) && (sc.getClanId() == clanId))
  1055. {
  1056. return sc;
  1057. }
  1058. }
  1059. return null;
  1060. }
  1061. @Override
  1062. public final List<L2SiegeClan> getAttackerClans()
  1063. {
  1064. return _attackerClans;
  1065. }
  1066. public final Fort getFort()
  1067. {
  1068. return _fort;
  1069. }
  1070. public final boolean isInProgress()
  1071. {
  1072. return _isInProgress;
  1073. }
  1074. @Override
  1075. public final Calendar getSiegeDate()
  1076. {
  1077. return getFort().getSiegeDate();
  1078. }
  1079. @Override
  1080. public List<L2Npc> getFlag(L2Clan clan)
  1081. {
  1082. if (clan != null)
  1083. {
  1084. L2SiegeClan sc = getAttackerClan(clan);
  1085. if (sc != null)
  1086. {
  1087. return sc.getFlag();
  1088. }
  1089. }
  1090. return null;
  1091. }
  1092. public final FortSiegeGuardManager getSiegeGuardManager()
  1093. {
  1094. if (_siegeGuardManager == null)
  1095. {
  1096. _siegeGuardManager = new FortSiegeGuardManager(getFort());
  1097. }
  1098. return _siegeGuardManager;
  1099. }
  1100. public void resetSiege()
  1101. {
  1102. // reload commanders and repair doors
  1103. removeCommanders();
  1104. spawnCommanders();
  1105. getFort().resetDoors();
  1106. }
  1107. public List<L2Spawn> getCommanders()
  1108. {
  1109. return _commanders;
  1110. }
  1111. @Override
  1112. public L2SiegeClan getDefenderClan(int clanId)
  1113. {
  1114. return null;
  1115. }
  1116. @Override
  1117. public L2SiegeClan getDefenderClan(L2Clan clan)
  1118. {
  1119. return null;
  1120. }
  1121. @Override
  1122. public List<L2SiegeClan> getDefenderClans()
  1123. {
  1124. return null;
  1125. }
  1126. @Override
  1127. public boolean giveFame()
  1128. {
  1129. return true;
  1130. }
  1131. @Override
  1132. public int getFameFrequency()
  1133. {
  1134. return Config.FORTRESS_ZONE_FAME_TASK_FREQUENCY;
  1135. }
  1136. @Override
  1137. public int getFameAmount()
  1138. {
  1139. return Config.FORTRESS_ZONE_FAME_AQUIRE_POINTS;
  1140. }
  1141. @Override
  1142. public void updateSiege()
  1143. {
  1144. }
  1145. }