ClanHallSiegeEngine.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. /*
  2. * Copyright © 2004-2019 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.clanhall;
  20. import java.util.ArrayList;
  21. import java.util.Calendar;
  22. import java.util.List;
  23. import java.util.Map;
  24. import java.util.concurrent.ConcurrentHashMap;
  25. import java.util.concurrent.ScheduledFuture;
  26. import org.slf4j.Logger;
  27. import org.slf4j.LoggerFactory;
  28. import com.l2jserver.gameserver.config.Config;
  29. import com.l2jserver.commons.database.ConnectionFactory;
  30. import com.l2jserver.gameserver.ThreadPoolManager;
  31. import com.l2jserver.gameserver.data.sql.impl.ClanTable;
  32. import com.l2jserver.gameserver.instancemanager.ClanHallSiegeManager;
  33. import com.l2jserver.gameserver.instancemanager.MapRegionManager;
  34. import com.l2jserver.gameserver.model.L2Clan;
  35. import com.l2jserver.gameserver.model.L2SiegeClan;
  36. import com.l2jserver.gameserver.model.L2SiegeClan.SiegeClanType;
  37. import com.l2jserver.gameserver.model.L2Spawn;
  38. import com.l2jserver.gameserver.model.L2World;
  39. import com.l2jserver.gameserver.model.Location;
  40. import com.l2jserver.gameserver.model.actor.L2Character;
  41. import com.l2jserver.gameserver.model.actor.L2Npc;
  42. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  43. import com.l2jserver.gameserver.model.entity.Siegable;
  44. import com.l2jserver.gameserver.model.quest.Quest;
  45. import com.l2jserver.gameserver.network.NpcStringId;
  46. import com.l2jserver.gameserver.network.SystemMessageId;
  47. import com.l2jserver.gameserver.network.serverpackets.NpcSay;
  48. import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
  49. import com.l2jserver.gameserver.util.Broadcast;
  50. /**
  51. * @author BiggBoss
  52. */
  53. public abstract class ClanHallSiegeEngine extends Quest implements Siegable {
  54. public static final Logger _log = LoggerFactory.getLogger(ClanHallSiegeEngine.class);
  55. private static final String SQL_LOAD_ATTACKERS = "SELECT attacker_id FROM clanhall_siege_attackers WHERE clanhall_id = ?";
  56. private static final String SQL_SAVE_ATTACKERS = "INSERT INTO clanhall_siege_attackers VALUES (?,?)";
  57. private static final String SQL_LOAD_GUARDS = "SELECT * FROM clanhall_siege_guards WHERE clanHallId = ?";
  58. public static final int FORTRESS_RESSISTANCE = 21;
  59. public static final int DEVASTATED_CASTLE = 34;
  60. public static final int BANDIT_STRONGHOLD = 35;
  61. public static final int RAINBOW_SPRINGS = 62;
  62. public static final int BEAST_FARM = 63;
  63. public static final int FORTRESS_OF_DEAD = 64;
  64. private final Map<Integer, L2SiegeClan> _attackers = new ConcurrentHashMap<>();
  65. private List<L2Spawn> _guards;
  66. public SiegableHall _hall;
  67. public ScheduledFuture<?> _siegeTask;
  68. public boolean _missionAccomplished = false;
  69. public ClanHallSiegeEngine(String name, String descr, final int hallId) {
  70. super(-1, name, descr);
  71. _hall = ClanHallSiegeManager.getInstance().getSiegableHall(hallId);
  72. _hall.setSiege(this);
  73. _siegeTask = ThreadPoolManager.getInstance().scheduleGeneral(new PrepareOwner(), _hall.getNextSiegeTime() - System.currentTimeMillis() - 3600000);
  74. _log.info("{} siege scheduled for {}.", _hall.getName(), getSiegeDate().getTime());
  75. loadAttackers();
  76. }
  77. public void loadAttackers() {
  78. try (var con = ConnectionFactory.getInstance().getConnection();
  79. var ps = con.prepareStatement(SQL_LOAD_ATTACKERS)) {
  80. ps.setInt(1, _hall.getId());
  81. try (var rset = ps.executeQuery()) {
  82. while (rset.next()) {
  83. final int id = rset.getInt("attacker_id");
  84. L2SiegeClan clan = new L2SiegeClan(id, SiegeClanType.ATTACKER);
  85. _attackers.put(id, clan);
  86. }
  87. }
  88. } catch (Exception e) {
  89. _log.warn("{}: Could not load siege attackers!", getName(), e);
  90. }
  91. }
  92. public final void saveAttackers() {
  93. try (var con = ConnectionFactory.getInstance().getConnection();
  94. var ps = con.prepareStatement("DELETE FROM clanhall_siege_attackers WHERE clanhall_id = ?")) {
  95. ps.setInt(1, _hall.getId());
  96. ps.execute();
  97. if (_attackers.size() > 0) {
  98. try (var insert = con.prepareStatement(SQL_SAVE_ATTACKERS)) {
  99. for (L2SiegeClan clan : _attackers.values()) {
  100. insert.setInt(1, _hall.getId());
  101. insert.setInt(2, clan.getClanId());
  102. insert.execute();
  103. insert.clearParameters();
  104. }
  105. }
  106. }
  107. _log.info("{}: Successfully saved attackers to database.", getName());
  108. } catch (Exception e) {
  109. _log.warn("{}: Couldnt save attacker list!", getName(), e);
  110. }
  111. }
  112. public final void loadGuards() {
  113. if (_guards == null) {
  114. _guards = new ArrayList<>();
  115. try (var con = ConnectionFactory.getInstance().getConnection();
  116. var ps = con.prepareStatement(SQL_LOAD_GUARDS)) {
  117. ps.setInt(1, _hall.getId());
  118. try (var rset = ps.executeQuery()) {
  119. while (rset.next()) {
  120. final L2Spawn spawn = new L2Spawn(rset.getInt("npcId"));
  121. spawn.setX(rset.getInt("x"));
  122. spawn.setY(rset.getInt("y"));
  123. spawn.setZ(rset.getInt("z"));
  124. spawn.setHeading(rset.getInt("heading"));
  125. spawn.setRespawnDelay(rset.getInt("respawnDelay"));
  126. spawn.setAmount(1);
  127. _guards.add(spawn);
  128. }
  129. }
  130. } catch (Exception e) {
  131. _log.warn("{}: Couldn't load siege guards!", getName(), e);
  132. }
  133. }
  134. }
  135. private final void spawnSiegeGuards() {
  136. for (L2Spawn guard : _guards) {
  137. guard.init();
  138. }
  139. }
  140. private final void unSpawnSiegeGuards() {
  141. if (_guards != null) {
  142. for (L2Spawn guard : _guards) {
  143. guard.stopRespawn();
  144. if (guard.getLastSpawn() != null) {
  145. guard.getLastSpawn().deleteMe();
  146. }
  147. }
  148. }
  149. }
  150. @Override
  151. public List<L2Npc> getFlag(L2Clan clan) {
  152. List<L2Npc> result = null;
  153. L2SiegeClan sClan = getAttackerClan(clan);
  154. if (sClan != null) {
  155. result = sClan.getFlag();
  156. }
  157. return result;
  158. }
  159. public final Map<Integer, L2SiegeClan> getAttackers() {
  160. return _attackers;
  161. }
  162. @Override
  163. public boolean checkIsAttacker(L2Clan clan) {
  164. if (clan == null) {
  165. return false;
  166. }
  167. return _attackers.containsKey(clan.getId());
  168. }
  169. @Override
  170. public boolean checkIsDefender(L2Clan clan) {
  171. return false;
  172. }
  173. @Override
  174. public L2SiegeClan getAttackerClan(int clanId) {
  175. return _attackers.get(clanId);
  176. }
  177. @Override
  178. public L2SiegeClan getAttackerClan(L2Clan clan) {
  179. return getAttackerClan(clan.getId());
  180. }
  181. @Override
  182. public List<L2SiegeClan> getAttackerClans() {
  183. return new ArrayList<>(_attackers.values());
  184. }
  185. @Override
  186. public List<L2PcInstance> getAttackersInZone() {
  187. final List<L2PcInstance> attackers = new ArrayList<>();
  188. for (L2PcInstance pc : _hall.getSiegeZone().getPlayersInside()) {
  189. final L2Clan clan = pc.getClan();
  190. if ((clan != null) && _attackers.containsKey(clan.getId())) {
  191. attackers.add(pc);
  192. }
  193. }
  194. return attackers;
  195. }
  196. @Override
  197. public L2SiegeClan getDefenderClan(int clanId) {
  198. return null;
  199. }
  200. @Override
  201. public L2SiegeClan getDefenderClan(L2Clan clan) {
  202. return null;
  203. }
  204. @Override
  205. public List<L2SiegeClan> getDefenderClans() {
  206. return null;
  207. }
  208. public void prepareOwner() {
  209. if (_hall.getOwnerId() > 0) {
  210. final L2SiegeClan clan = new L2SiegeClan(_hall.getOwnerId(), SiegeClanType.ATTACKER);
  211. _attackers.put(clan.getClanId(), new L2SiegeClan(clan.getClanId(), SiegeClanType.ATTACKER));
  212. }
  213. _hall.free();
  214. _hall.banishForeigners();
  215. SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.REGISTRATION_TERM_FOR_S1_ENDED);
  216. msg.addString(getName());
  217. Broadcast.toAllOnlinePlayers(msg);
  218. _hall.updateSiegeStatus(SiegeStatus.WAITING_BATTLE);
  219. _siegeTask = ThreadPoolManager.getInstance().scheduleGeneral(new SiegeStarts(), 3600000);
  220. }
  221. @Override
  222. public void startSiege() {
  223. if ((_attackers.size() < 1) && (_hall.getId() != 21)) // Fortress of resistance don't have attacker list
  224. {
  225. onSiegeEnds();
  226. _attackers.clear();
  227. _hall.updateNextSiege();
  228. _siegeTask = ThreadPoolManager.getInstance().scheduleGeneral(new PrepareOwner(), _hall.getSiegeDate().getTimeInMillis());
  229. _hall.updateSiegeStatus(SiegeStatus.WAITING_BATTLE);
  230. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.SIEGE_OF_S1_HAS_BEEN_CANCELED_DUE_TO_LACK_OF_INTEREST);
  231. sm.addString(_hall.getName());
  232. Broadcast.toAllOnlinePlayers(sm);
  233. return;
  234. }
  235. _hall.spawnDoor();
  236. loadGuards();
  237. spawnSiegeGuards();
  238. _hall.updateSiegeZone(true);
  239. final byte state = 1;
  240. for (L2SiegeClan sClan : _attackers.values()) {
  241. final L2Clan clan = ClanTable.getInstance().getClan(sClan.getClanId());
  242. if (clan == null) {
  243. continue;
  244. }
  245. for (L2PcInstance pc : clan.getOnlineMembers(0)) {
  246. pc.setSiegeState(state);
  247. pc.broadcastUserInfo();
  248. pc.setIsInHideoutSiege(true);
  249. }
  250. }
  251. _hall.updateSiegeStatus(SiegeStatus.RUNNING);
  252. onSiegeStarts();
  253. _siegeTask = ThreadPoolManager.getInstance().scheduleGeneral(new SiegeEnds(), _hall.getSiegeLenght());
  254. }
  255. @Override
  256. public void endSiege() {
  257. SystemMessage end = SystemMessage.getSystemMessage(SystemMessageId.SIEGE_OF_S1_HAS_ENDED);
  258. end.addString(_hall.getName());
  259. Broadcast.toAllOnlinePlayers(end);
  260. L2Clan winner = getWinner();
  261. SystemMessage finalMsg = null;
  262. if (_missionAccomplished && (winner != null)) {
  263. _hall.setOwner(winner);
  264. winner.setHideoutId(_hall.getId());
  265. finalMsg = SystemMessage.getSystemMessage(SystemMessageId.CLAN_S1_VICTORIOUS_OVER_S2_S_SIEGE);
  266. finalMsg.addString(winner.getName());
  267. finalMsg.addString(_hall.getName());
  268. Broadcast.toAllOnlinePlayers(finalMsg);
  269. } else {
  270. finalMsg = SystemMessage.getSystemMessage(SystemMessageId.SIEGE_S1_DRAW);
  271. finalMsg.addString(_hall.getName());
  272. Broadcast.toAllOnlinePlayers(finalMsg);
  273. }
  274. _missionAccomplished = false;
  275. _hall.updateSiegeZone(false);
  276. _hall.updateNextSiege();
  277. _hall.spawnDoor(false);
  278. _hall.banishForeigners();
  279. final byte state = 0;
  280. for (L2SiegeClan sClan : _attackers.values()) {
  281. final L2Clan clan = ClanTable.getInstance().getClan(sClan.getClanId());
  282. if (clan == null) {
  283. continue;
  284. }
  285. for (L2PcInstance player : clan.getOnlineMembers(0)) {
  286. player.setSiegeState(state);
  287. player.broadcastUserInfo();
  288. player.setIsInHideoutSiege(false);
  289. }
  290. }
  291. // Update pvp flag for winners when siege zone becomes inactive
  292. for (L2Character chr : _hall.getSiegeZone().getCharactersInside()) {
  293. if ((chr != null) && chr.isPlayer()) {
  294. chr.getActingPlayer().startPvPFlag();
  295. }
  296. }
  297. _attackers.clear();
  298. onSiegeEnds();
  299. _siegeTask = ThreadPoolManager.getInstance().scheduleGeneral(new PrepareOwner(), _hall.getNextSiegeTime() - System.currentTimeMillis() - 3600000);
  300. _log.info("Siege of {} scheduled for {}.", _hall.getName(), _hall.getSiegeDate().getTime());
  301. _hall.updateSiegeStatus(SiegeStatus.REGISTERING);
  302. unSpawnSiegeGuards();
  303. }
  304. @Override
  305. public void updateSiege() {
  306. cancelSiegeTask();
  307. _siegeTask = ThreadPoolManager.getInstance().scheduleGeneral(new PrepareOwner(), _hall.getNextSiegeTime() - 3600000);
  308. _log.info("{} siege scheduled for {}.", _hall.getName(), _hall.getSiegeDate().getTime());
  309. }
  310. public void cancelSiegeTask() {
  311. if (_siegeTask != null) {
  312. _siegeTask.cancel(false);
  313. }
  314. }
  315. @Override
  316. public Calendar getSiegeDate() {
  317. return _hall.getSiegeDate();
  318. }
  319. @Override
  320. public boolean giveFame() {
  321. return Config.CHS_ENABLE_FAME;
  322. }
  323. @Override
  324. public int getFameAmount() {
  325. return Config.CHS_FAME_AMOUNT;
  326. }
  327. @Override
  328. public int getFameFrequency() {
  329. return Config.CHS_FAME_FREQUENCY;
  330. }
  331. public final void broadcastNpcSay(final L2Npc npc, final int type, final NpcStringId messageId) {
  332. final NpcSay npcSay = new NpcSay(npc.getObjectId(), type, npc.getId(), messageId);
  333. final int sourceRegion = MapRegionManager.getInstance().getMapRegionLocId(npc);
  334. for (L2PcInstance pc : L2World.getInstance().getPlayers()) {
  335. if ((pc != null) && (MapRegionManager.getInstance().getMapRegionLocId(pc) == sourceRegion)) {
  336. pc.sendPacket(npcSay);
  337. }
  338. }
  339. }
  340. public Location getInnerSpawnLoc(L2PcInstance player) {
  341. return null;
  342. }
  343. public boolean canPlantFlag() {
  344. return true;
  345. }
  346. public boolean doorIsAutoAttackable() {
  347. return true;
  348. }
  349. public void onSiegeStarts() {
  350. }
  351. public void onSiegeEnds() {
  352. }
  353. public abstract L2Clan getWinner();
  354. public class PrepareOwner implements Runnable {
  355. @Override
  356. public void run() {
  357. prepareOwner();
  358. }
  359. }
  360. public class SiegeStarts implements Runnable {
  361. @Override
  362. public void run() {
  363. startSiege();
  364. }
  365. }
  366. public class SiegeEnds implements Runnable {
  367. @Override
  368. public void run() {
  369. endSiege();
  370. }
  371. }
  372. }