FortSiege.java 35 KB

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