/* * Copyright (C) 2004-2015 L2J Server * * This file is part of L2J Server. * * L2J Server is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * L2J Server is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package com.l2jserver.gameserver.model.entity; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Calendar; import java.util.List; import java.util.concurrent.ScheduledFuture; import java.util.logging.Level; import java.util.logging.Logger; import javolution.util.FastList; import com.l2jserver.Config; import com.l2jserver.L2DatabaseFactory; import com.l2jserver.gameserver.ThreadPoolManager; import com.l2jserver.gameserver.data.sql.impl.ClanTable; import com.l2jserver.gameserver.enums.FortTeleportWhoType; import com.l2jserver.gameserver.instancemanager.FortManager; import com.l2jserver.gameserver.instancemanager.FortSiegeGuardManager; import com.l2jserver.gameserver.instancemanager.FortSiegeManager; import com.l2jserver.gameserver.instancemanager.TerritoryWarManager; import com.l2jserver.gameserver.model.CombatFlag; import com.l2jserver.gameserver.model.FortSiegeSpawn; import com.l2jserver.gameserver.model.L2Clan; import com.l2jserver.gameserver.model.L2Object; import com.l2jserver.gameserver.model.L2SiegeClan; import com.l2jserver.gameserver.model.L2SiegeClan.SiegeClanType; import com.l2jserver.gameserver.model.L2Spawn; import com.l2jserver.gameserver.model.PcCondOverride; import com.l2jserver.gameserver.model.TeleportWhereType; import com.l2jserver.gameserver.model.actor.L2Npc; import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance; import com.l2jserver.gameserver.model.actor.instance.L2FortCommanderInstance; import com.l2jserver.gameserver.model.actor.instance.L2PcInstance; import com.l2jserver.gameserver.model.events.EventDispatcher; import com.l2jserver.gameserver.model.events.impl.sieges.fort.OnFortSiegeFinish; import com.l2jserver.gameserver.model.events.impl.sieges.fort.OnFortSiegeStart; import com.l2jserver.gameserver.network.NpcStringId; import com.l2jserver.gameserver.network.SystemMessageId; import com.l2jserver.gameserver.network.clientpackets.Say2; import com.l2jserver.gameserver.network.serverpackets.NpcSay; import com.l2jserver.gameserver.network.serverpackets.SystemMessage; public class FortSiege implements Siegable { protected static final Logger _log = Logger.getLogger(FortSiege.class.getName()); // SQL private static final String DELETE_FORT_SIEGECLANS_BY_CLAN_ID = "DELETE FROM fortsiege_clans WHERE fort_id = ? AND clan_id = ?"; private static final String DELETE_FORT_SIEGECLANS = "DELETE FROM fortsiege_clans WHERE fort_id = ?"; public class ScheduleEndSiegeTask implements Runnable { @Override public void run() { if (!isInProgress()) { return; } try { _siegeEnd = null; endSiege(); } catch (Exception e) { _log.log(Level.WARNING, "Exception: ScheduleEndSiegeTask() for Fort: " + _fort.getName() + " " + e.getMessage(), e); } } } public class ScheduleStartSiegeTask implements Runnable { private final Fort _fortInst; private final int _time; public ScheduleStartSiegeTask(int time) { _fortInst = _fort; _time = time; } @Override public void run() { if (isInProgress()) { return; } try { final SystemMessage sm; if (_time == 3600) // 1hr remains { ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(600), 3000000); // Prepare task for 10 minutes left. } else if (_time == 600) // 10min remains { getFort().despawnSuspiciousMerchant(); sm = SystemMessage.getSystemMessage(SystemMessageId.S1_MINUTES_UNTIL_THE_FORTRESS_BATTLE_STARTS); sm.addInt(10); announceToPlayer(sm); ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(300), 300000); // Prepare task for 5 minutes left. } else if (_time == 300) // 5min remains { sm = SystemMessage.getSystemMessage(SystemMessageId.S1_MINUTES_UNTIL_THE_FORTRESS_BATTLE_STARTS); sm.addInt(5); announceToPlayer(sm); ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(60), 240000); // Prepare task for 1 minute left. } else if (_time == 60) // 1min remains { sm = SystemMessage.getSystemMessage(SystemMessageId.S1_MINUTES_UNTIL_THE_FORTRESS_BATTLE_STARTS); sm.addInt(1); announceToPlayer(sm); ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(30), 30000); // Prepare task for 30 seconds left. } else if (_time == 30) // 30seconds remains { sm = SystemMessage.getSystemMessage(SystemMessageId.S1_SECONDS_UNTIL_THE_FORTRESS_BATTLE_STARTS); sm.addInt(30); announceToPlayer(sm); ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(10), 20000); // Prepare task for 10 seconds left. } else if (_time == 10) // 10seconds remains { sm = SystemMessage.getSystemMessage(SystemMessageId.S1_SECONDS_UNTIL_THE_FORTRESS_BATTLE_STARTS); sm.addInt(10); announceToPlayer(sm); ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(5), 5000); // Prepare task for 5 seconds left. } else if (_time == 5) // 5seconds remains { sm = SystemMessage.getSystemMessage(SystemMessageId.S1_SECONDS_UNTIL_THE_FORTRESS_BATTLE_STARTS); sm.addInt(5); announceToPlayer(sm); ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(1), 4000); // Prepare task for 1 seconds left. } else if (_time == 1) // 1seconds remains { sm = SystemMessage.getSystemMessage(SystemMessageId.S1_SECONDS_UNTIL_THE_FORTRESS_BATTLE_STARTS); sm.addInt(1); announceToPlayer(sm); ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStartSiegeTask(0), 1000); // Prepare task start siege. } else if (_time == 0)// start siege { _fortInst.getSiege().startSiege(); } else { _log.warning("Exception: ScheduleStartSiegeTask(): unknown siege time: " + String.valueOf(_time)); } } catch (Exception e) { _log.log(Level.WARNING, "Exception: ScheduleStartSiegeTask() for Fort: " + _fortInst.getName() + " " + e.getMessage(), e); } } } public class ScheduleSuspiciousMerchantSpawn implements Runnable { @Override public void run() { if (isInProgress()) { return; } try { _fort.spawnSuspiciousMerchant(); } catch (Exception e) { _log.log(Level.WARNING, "Exception: ScheduleSuspicoiusMerchantSpawn() for Fort: " + _fort.getName() + " " + e.getMessage(), e); } } } public class ScheduleSiegeRestore implements Runnable { @Override public void run() { if (!isInProgress()) { return; } try { _siegeRestore = null; resetSiege(); announceToPlayer(SystemMessage.getSystemMessage(SystemMessageId.BARRACKS_FUNCTION_RESTORED)); } catch (Exception e) { _log.log(Level.WARNING, "Exception: ScheduleSiegeRestore() for Fort: " + _fort.getName() + " " + e.getMessage(), e); } } } private final List _attackerClans = new FastList<>(); // Fort setting protected FastList _commanders = new FastList<>(); protected final Fort _fort; private boolean _isInProgress = false; private FortSiegeGuardManager _siegeGuardManager; ScheduledFuture _siegeEnd = null; ScheduledFuture _siegeRestore = null; ScheduledFuture _siegeStartTask = null; public FortSiege(Fort fort) { _fort = fort; checkAutoTask(); FortSiegeManager.getInstance().addSiege(this); } /** * When siege ends. */ @Override public void endSiege() { if (isInProgress()) { _isInProgress = false; // Flag so that siege instance can be started removeFlags(); // Removes all flags. Note: Remove flag before teleporting players unSpawnFlags(); updatePlayerSiegeStateFlags(true); int ownerId = -1; if (getFort().getOwnerClan() != null) { ownerId = getFort().getOwnerClan().getId(); } getFort().getZone().banishForeigners(ownerId); getFort().getZone().setIsActive(false); getFort().getZone().updateZoneStatusForCharactersInside(); getFort().getZone().setSiegeInstance(null); saveFortSiege(); // Save fort specific data clearSiegeClan(); // Clear siege clan from db removeCommanders(); // Remove commander from this fort getFort().spawnNpcCommanders(); // Spawn NPC commanders getSiegeGuardManager().unspawnSiegeGuard(); // Remove all spawned siege guard from this fort getFort().resetDoors(); // Respawn door to fort ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleSuspiciousMerchantSpawn(), FortSiegeManager.getInstance().getSuspiciousMerchantRespawnDelay() * 60 * 1000L); // Prepare 3hr task for suspicious merchant respawn setSiegeDateTime(true); // store suspicious merchant spawn in DB if (_siegeEnd != null) { _siegeEnd.cancel(true); _siegeEnd = null; } if (_siegeRestore != null) { _siegeRestore.cancel(true); _siegeRestore = null; } if ((getFort().getOwnerClan() != null) && (getFort().getFlagPole().getMeshIndex() == 0)) { getFort().setVisibleFlag(true); } _log.info("Siege of " + getFort().getName() + " fort finished."); // Notify to scripts. EventDispatcher.getInstance().notifyEventAsync(new OnFortSiegeFinish(this), getFort()); } } /** * When siege starts */ @Override public void startSiege() { if (!isInProgress()) { if (_siegeStartTask != null) // used admin command "admin_startfortsiege" { _siegeStartTask.cancel(true); getFort().despawnSuspiciousMerchant(); } _siegeStartTask = null; if (getAttackerClans().isEmpty()) { return; } _isInProgress = true; // Flag so that same siege instance cannot be started again loadSiegeClan(); // Load siege clan from db updatePlayerSiegeStateFlags(false); teleportPlayer(FortTeleportWhoType.Attacker, TeleportWhereType.TOWN); // Teleport to the closest town getFort().despawnNpcCommanders(); // Despawn NPC commanders spawnCommanders(); // Spawn commanders getFort().resetDoors(); // Spawn door spawnSiegeGuard(); // Spawn siege guard getFort().setVisibleFlag(false); getFort().getZone().setSiegeInstance(this); getFort().getZone().setIsActive(true); getFort().getZone().updateZoneStatusForCharactersInside(); // Schedule a task to prepare auto siege end _siegeEnd = ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleEndSiegeTask(), FortSiegeManager.getInstance().getSiegeLength() * 60 * 1000L); // Prepare auto end task final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.THE_FORTRESS_BATTLE_S1_HAS_BEGUN); sm.addCastleId(getFort().getResidenceId()); announceToPlayer(sm); saveFortSiege(); _log.info("Siege of " + getFort().getName() + " fort started."); // Notify to scripts. EventDispatcher.getInstance().notifyEventAsync(new OnFortSiegeStart(this), getFort()); } } /** * Announce to player. * @param sm the system message to send to player */ public void announceToPlayer(SystemMessage sm) { // announce messages only for participants L2Clan clan; for (L2SiegeClan siegeclan : getAttackerClans()) { clan = ClanTable.getInstance().getClan(siegeclan.getClanId()); for (L2PcInstance member : clan.getOnlineMembers(0)) { if (member != null) { member.sendPacket(sm); } } } if (getFort().getOwnerClan() != null) { clan = ClanTable.getInstance().getClan(getFort().getOwnerClan().getId()); for (L2PcInstance member : clan.getOnlineMembers(0)) { if (member != null) { member.sendPacket(sm); } } } } public void announceToPlayer(SystemMessage sm, String s) { sm.addString(s); announceToPlayer(sm); } public void updatePlayerSiegeStateFlags(boolean clear) { L2Clan clan; for (L2SiegeClan siegeclan : getAttackerClans()) { clan = ClanTable.getInstance().getClan(siegeclan.getClanId()); for (L2PcInstance member : clan.getOnlineMembers(0)) { if (member == null) { continue; } if (clear) { member.setSiegeState((byte) 0); member.setSiegeSide(0); member.setIsInSiege(false); member.stopFameTask(); } else { member.setSiegeState((byte) 1); member.setSiegeSide(getFort().getResidenceId()); if (checkIfInZone(member)) { member.setIsInSiege(true); member.startFameTask(Config.FORTRESS_ZONE_FAME_TASK_FREQUENCY * 1000, Config.FORTRESS_ZONE_FAME_AQUIRE_POINTS); } } member.broadcastUserInfo(); } } if (getFort().getOwnerClan() != null) { clan = ClanTable.getInstance().getClan(getFort().getOwnerClan().getId()); for (L2PcInstance member : clan.getOnlineMembers(0)) { if (member == null) { continue; } if (clear) { member.setSiegeState((byte) 0); member.setSiegeSide(0); member.setIsInSiege(false); member.stopFameTask(); } else { member.setSiegeState((byte) 2); member.setSiegeSide(getFort().getResidenceId()); if (checkIfInZone(member)) { member.setIsInSiege(true); member.startFameTask(Config.FORTRESS_ZONE_FAME_TASK_FREQUENCY * 1000, Config.FORTRESS_ZONE_FAME_AQUIRE_POINTS); } } member.broadcastUserInfo(); } } } /** * @param object * @return true if object is inside the zone */ public boolean checkIfInZone(L2Object object) { return checkIfInZone(object.getX(), object.getY(), object.getZ()); } /** * @param x * @param y * @param z * @return true if object is inside the zone */ public boolean checkIfInZone(int x, int y, int z) { return (isInProgress() && (getFort().checkIfInZone(x, y, z))); // Fort zone during siege } /** * @param clan The L2Clan of the player * @return true if clan is attacker */ @Override public boolean checkIsAttacker(L2Clan clan) { return (getAttackerClan(clan) != null); } /** * @param clan The L2Clan of the player * @return true if clan is defender */ @Override public boolean checkIsDefender(L2Clan clan) { if ((clan != null) && (getFort().getOwnerClan() == clan)) { return true; } return false; } /** Clear all registered siege clans from database for fort */ public void clearSiegeClan() { try (Connection con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement ps = con.prepareStatement("DELETE FROM fortsiege_clans WHERE fort_id=?")) { ps.setInt(1, getFort().getResidenceId()); ps.execute(); if (getFort().getOwnerClan() != null) { try (PreparedStatement delete = con.prepareStatement("DELETE FROM fortsiege_clans WHERE clan_id=?")) { delete.setInt(1, getFort().getOwnerClan().getId()); delete.execute(); } } getAttackerClans().clear(); // if siege is in progress, end siege if (isInProgress()) { endSiege(); } // if siege isn't in progress (1hr waiting time till siege starts), cancel waiting time if (_siegeStartTask != null) { _siegeStartTask.cancel(true); _siegeStartTask = null; } } catch (Exception e) { _log.log(Level.WARNING, "Exception: clearSiegeClan(): " + e.getMessage(), e); } } /** Set the date for the next siege. */ private void clearSiegeDate() { getFort().getSiegeDate().setTimeInMillis(0); } /** * @return list of L2PcInstance registered as attacker in the zone. */ @Override public List getAttackersInZone() { List players = new FastList<>(); L2Clan clan; for (L2SiegeClan siegeclan : getAttackerClans()) { clan = ClanTable.getInstance().getClan(siegeclan.getClanId()); for (L2PcInstance player : clan.getOnlineMembers(0)) { if (player == null) { continue; } if (player.isInSiege()) { players.add(player); } } } return players; } /** * @return list of L2PcInstance in the zone. */ public List getPlayersInZone() { return getFort().getZone().getPlayersInside(); } /** * @return list of L2PcInstance owning the fort in the zone. */ public List getOwnersInZone() { List players = new FastList<>(); L2Clan clan; if (getFort().getOwnerClan() != null) { clan = ClanTable.getInstance().getClan(getFort().getOwnerClan().getId()); if (clan != getFort().getOwnerClan()) { return null; } for (L2PcInstance player : clan.getOnlineMembers(0)) { if (player == null) { continue; } if (player.isInSiege()) { players.add(player); } } } return players; } /** * TODO: To DP AI
* Commander was killed * @param instance */ public void killedCommander(L2FortCommanderInstance instance) { if ((_commanders != null) && (getFort() != null) && (_commanders.size() != 0)) { L2Spawn spawn = instance.getSpawn(); if (spawn != null) { FastList commanders = FortSiegeManager.getInstance().getCommanderSpawnList(getFort().getResidenceId()); for (FortSiegeSpawn spawn2 : commanders) { if (spawn2.getId() == spawn.getId()) { NpcStringId npcString = null; switch (spawn2.getMessageId()) { case 1: npcString = NpcStringId.YOU_MAY_HAVE_BROKEN_OUR_ARROWS_BUT_YOU_WILL_NEVER_BREAK_OUR_WILL_ARCHERS_RETREAT; break; case 2: npcString = NpcStringId.AIIEEEE_COMMAND_CENTER_THIS_IS_GUARD_UNIT_WE_NEED_BACKUP_RIGHT_AWAY; break; case 3: npcString = NpcStringId.AT_LAST_THE_MAGIC_FIELD_THAT_PROTECTS_THE_FORTRESS_HAS_WEAKENED_VOLUNTEERS_STAND_BACK; break; case 4: 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; break; } if (npcString != null) { instance.broadcastPacket(new NpcSay(instance.getObjectId(), Say2.NPC_SHOUT, instance.getId(), npcString)); } } } _commanders.remove(spawn); if (_commanders.isEmpty()) { // spawn fort flags spawnFlag(getFort().getResidenceId()); // cancel door/commanders respawn if (_siegeRestore != null) { _siegeRestore.cancel(true); } // open doors in main building for (L2DoorInstance door : getFort().getDoors()) { if (door.getIsShowHp()) { continue; } // TODO this also opens control room door at big fort door.openMe(); } getFort().getSiege().announceToPlayer(SystemMessage.getSystemMessage(SystemMessageId.ALL_BARRACKS_OCCUPIED)); } // schedule restoring doors/commanders respawn else if (_siegeRestore == null) { getFort().getSiege().announceToPlayer(SystemMessage.getSystemMessage(SystemMessageId.SEIZED_BARRACKS)); _siegeRestore = ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleSiegeRestore(), FortSiegeManager.getInstance().getCountDownLength() * 60 * 1000L); } else { getFort().getSiege().announceToPlayer(SystemMessage.getSystemMessage(SystemMessageId.SEIZED_BARRACKS)); } } else { _log.warning("FortSiege.killedCommander(): killed commander, but commander not registered for fortress. NpcId: " + instance.getId() + " FortId: " + getFort().getResidenceId()); } } } /** * Remove the flag that was killed * @param flag */ public void killedFlag(L2Npc flag) { if (flag == null) { return; } for (L2SiegeClan clan : getAttackerClans()) { if (clan.removeFlag(flag)) { return; } } } /** * Register clan as attacker.
* @param player The L2PcInstance of the player trying to register. * @param checkConditions True if should be checked conditions, false otherwise * @return Number that defines what happened.
* 0 - Player don't have clan.
* 1 - Player don't have enough adena to register.
* 2 - Is not right time to register Fortress now.
* 3 - Players clan is already registered to siege.
* 4 - Players clan is successfully registered to siege. */ public int addAttacker(L2PcInstance player, boolean checkConditions) { if (player.getClan() == null) { return 0; // Player dont have clan } if (checkConditions) { if (getFort().getSiege().getAttackerClans().isEmpty() && (player.getInventory().getAdena() < 250000)) { return 1; // Player dont havee enough adena to register } else if ((System.currentTimeMillis() < TerritoryWarManager.getInstance().getTWStartTimeInMillis()) && TerritoryWarManager.getInstance().getIsRegistrationOver()) { return 2; // Is not right time to register Fortress now } if ((System.currentTimeMillis() > TerritoryWarManager.getInstance().getTWStartTimeInMillis()) && TerritoryWarManager.getInstance().isTWChannelOpen()) { return 2; // Is not right time to register Fortress now } for (Fort fort : FortManager.getInstance().getForts()) { if (fort.getSiege().getAttackerClan(player.getClanId()) != null) { return 3; // Players clan is already registred to siege } if ((fort.getOwnerClan() == player.getClan()) && (fort.getSiege().isInProgress() || (fort.getSiege()._siegeStartTask != null))) { return 3; // Players clan is already registred to siege } } } saveSiegeClan(player.getClan()); if (getAttackerClans().size() == 1) { if (checkConditions) { player.reduceAdena("FortressSiege", 250000, null, true); } startAutoTask(true); } return 4; // Players clan is successfully registred to siege } /** * Remove clan from siege * @param clan The clan being removed */ public void removeAttacker(L2Clan clan) { if ((clan == null) || (clan.getFortId() == getFort().getResidenceId()) || !FortSiegeManager.getInstance().checkIsRegistered(clan, getFort().getResidenceId())) { return; } removeSiegeClan(clan.getId()); } /** * This function does not do any checks and should not be called from bypass ! * @param clanId */ private void removeSiegeClan(int clanId) { final String query = (clanId != 0) ? DELETE_FORT_SIEGECLANS_BY_CLAN_ID : DELETE_FORT_SIEGECLANS; try (Connection con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement statement = con.prepareStatement(query)) { statement.setInt(1, getFort().getResidenceId()); if (clanId != 0) { statement.setInt(2, clanId); } statement.execute(); loadSiegeClan(); if (getAttackerClans().isEmpty()) { if (isInProgress()) { endSiege(); } else { saveFortSiege(); // Clear siege time in DB } if (_siegeStartTask != null) { _siegeStartTask.cancel(true); _siegeStartTask = null; } } } catch (Exception e) { _log.log(Level.WARNING, "Exception on removeSiegeClan: " + e.getMessage(), e); } } /** * Start the auto tasks */ public void checkAutoTask() { if (_siegeStartTask != null) { return; } final long delay = getFort().getSiegeDate().getTimeInMillis() - Calendar.getInstance().getTimeInMillis(); if (delay < 0) { // siege time in past saveFortSiege(); clearSiegeClan(); // remove all clans // spawn suspicious merchant immediately ThreadPoolManager.getInstance().executeGeneral(new ScheduleSuspiciousMerchantSpawn()); } else { loadSiegeClan(); if (getAttackerClans().isEmpty()) { // no attackers - waiting for suspicious merchant spawn ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleSuspiciousMerchantSpawn(), delay); } else { // preparing start siege task if (delay > 3600000) // more than hour, how this can happens ? spawn suspicious merchant { ThreadPoolManager.getInstance().executeGeneral(new ScheduleSuspiciousMerchantSpawn()); _siegeStartTask = ThreadPoolManager.getInstance().scheduleGeneral(new FortSiege.ScheduleStartSiegeTask(3600), delay - 3600000); } if (delay > 600000) // more than 10 min, spawn suspicious merchant { ThreadPoolManager.getInstance().executeGeneral(new ScheduleSuspiciousMerchantSpawn()); _siegeStartTask = ThreadPoolManager.getInstance().scheduleGeneral(new FortSiege.ScheduleStartSiegeTask(600), delay - 600000); } else if (delay > 300000) { _siegeStartTask = ThreadPoolManager.getInstance().scheduleGeneral(new FortSiege.ScheduleStartSiegeTask(300), delay - 300000); } else if (delay > 60000) { _siegeStartTask = ThreadPoolManager.getInstance().scheduleGeneral(new FortSiege.ScheduleStartSiegeTask(60), delay - 60000); } else { // lower than 1 min, set to 1 min _siegeStartTask = ThreadPoolManager.getInstance().scheduleGeneral(new FortSiege.ScheduleStartSiegeTask(60), 0); } _log.info("Siege of " + getFort().getName() + " fort: " + getFort().getSiegeDate().getTime()); } } } /** * Start the auto task * @param setTime */ public void startAutoTask(boolean setTime) { if (_siegeStartTask != null) { return; } if (setTime) { setSiegeDateTime(false); } if (getFort().getOwnerClan() != null) { getFort().getOwnerClan().broadcastToOnlineMembers(SystemMessage.getSystemMessage(SystemMessageId.A_FORTRESS_IS_UNDER_ATTACK)); } // Execute siege auto start _siegeStartTask = ThreadPoolManager.getInstance().scheduleGeneral(new FortSiege.ScheduleStartSiegeTask(3600), 0); } /** * Teleport players * @param teleportWho * @param teleportWhere */ public void teleportPlayer(FortTeleportWhoType teleportWho, TeleportWhereType teleportWhere) { List players; switch (teleportWho) { case Owner: players = getOwnersInZone(); break; case Attacker: players = getAttackersInZone(); break; default: players = getPlayersInZone(); } for (L2PcInstance player : players) { if (player.canOverrideCond(PcCondOverride.FORTRESS_CONDITIONS) || player.isJailed()) { continue; } player.teleToLocation(teleportWhere); } } /** * Add clan as attacker< * @param clanId */ private void addAttacker(int clanId) { getAttackerClans().add(new L2SiegeClan(clanId, SiegeClanType.ATTACKER)); // Add registered attacker to attacker list } /** * @param clan * @return {@code true} if the clan has already registered to a siege for the same day, {@code false} otherwise. */ public boolean checkIfAlreadyRegisteredForSameDay(L2Clan clan) { for (FortSiege siege : FortSiegeManager.getInstance().getSieges()) { if (siege == this) { continue; } if (siege.getSiegeDate().get(Calendar.DAY_OF_WEEK) == getSiegeDate().get(Calendar.DAY_OF_WEEK)) { if (siege.checkIsAttacker(clan)) { return true; } if (siege.checkIsDefender(clan)) { return true; } } } return false; } private void setSiegeDateTime(boolean merchant) { Calendar newDate = Calendar.getInstance(); if (merchant) { newDate.add(Calendar.MINUTE, FortSiegeManager.getInstance().getSuspiciousMerchantRespawnDelay()); } else { newDate.add(Calendar.MINUTE, 60); } getFort().setSiegeDate(newDate); saveSiegeDate(); } /** Load siege clans. */ private void loadSiegeClan() { getAttackerClans().clear(); try (Connection con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement ps = con.prepareStatement("SELECT clan_id FROM fortsiege_clans WHERE fort_id=?")) { ps.setInt(1, getFort().getResidenceId()); try (ResultSet rs = ps.executeQuery()) { while (rs.next()) { addAttacker(rs.getInt("clan_id")); } } } catch (Exception e) { _log.log(Level.WARNING, "Exception: loadSiegeClan(): " + e.getMessage(), e); } } /** Remove commanders. */ private void removeCommanders() { if ((_commanders != null) && !_commanders.isEmpty()) { // Remove all instance of commanders for this fort for (L2Spawn spawn : _commanders) { if (spawn != null) { spawn.stopRespawn(); if (spawn.getLastSpawn() != null) { spawn.getLastSpawn().deleteMe(); } } } _commanders.clear(); } } /** Remove all flags. */ private void removeFlags() { for (L2SiegeClan sc : getAttackerClans()) { if (sc != null) { sc.removeFlags(); } } } /** Save fort siege related to database. */ private void saveFortSiege() { clearSiegeDate(); // clear siege date saveSiegeDate(); // Save the new date } /** Save siege date to database. */ private void saveSiegeDate() { try (Connection con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement ps = con.prepareStatement("UPDATE fort SET siegeDate = ? WHERE id = ?")) { ps.setLong(1, getSiegeDate().getTimeInMillis()); ps.setInt(2, getFort().getResidenceId()); ps.execute(); } catch (Exception e) { _log.log(Level.WARNING, "Exception: saveSiegeDate(): " + e.getMessage(), e); } } /** * Save registration to database. * @param clan */ private void saveSiegeClan(L2Clan clan) { if (getAttackerClans().size() >= FortSiegeManager.getInstance().getAttackerMaxClans()) { return; } try (Connection con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement statement = con.prepareStatement("INSERT INTO fortsiege_clans (clan_id,fort_id) values (?,?)")) { statement.setInt(1, clan.getId()); statement.setInt(2, getFort().getResidenceId()); statement.execute(); addAttacker(clan.getId()); } catch (Exception e) { _log.log(Level.WARNING, "Exception: saveSiegeClan(L2Clan clan): " + e.getMessage(), e); } } /** Spawn commanders. */ private void spawnCommanders() { // Set commanders array size if one does not exist try { _commanders.clear(); for (FortSiegeSpawn _sp : FortSiegeManager.getInstance().getCommanderSpawnList(getFort().getResidenceId())) { final L2Spawn spawnDat = new L2Spawn(_sp.getId()); spawnDat.setAmount(1); spawnDat.setX(_sp.getLocation().getX()); spawnDat.setY(_sp.getLocation().getY()); spawnDat.setZ(_sp.getLocation().getZ()); spawnDat.setHeading(_sp.getLocation().getHeading()); spawnDat.setRespawnDelay(60); spawnDat.doSpawn(); spawnDat.stopRespawn(); _commanders.add(spawnDat); } } catch (Exception e) { // problem with initializing spawn, go to next one _log.log(Level.WARNING, "FortSiege.spawnCommander: Spawn could not be initialized: " + e.getMessage(), e); } } private void spawnFlag(int Id) { for (CombatFlag cf : FortSiegeManager.getInstance().getFlagList(Id)) { cf.spawnMe(); } } private void unSpawnFlags() { if (FortSiegeManager.getInstance().getFlagList(getFort().getResidenceId()) == null) { return; } for (CombatFlag cf : FortSiegeManager.getInstance().getFlagList(getFort().getResidenceId())) { cf.unSpawnMe(); } } /** * Spawn siege guard. */ private void spawnSiegeGuard() { getSiegeGuardManager().spawnSiegeGuard(); } @Override public final L2SiegeClan getAttackerClan(L2Clan clan) { if (clan == null) { return null; } return getAttackerClan(clan.getId()); } @Override public final L2SiegeClan getAttackerClan(int clanId) { for (L2SiegeClan sc : getAttackerClans()) { if ((sc != null) && (sc.getClanId() == clanId)) { return sc; } } return null; } @Override public final List getAttackerClans() { return _attackerClans; } public final Fort getFort() { return _fort; } public final boolean isInProgress() { return _isInProgress; } @Override public final Calendar getSiegeDate() { return getFort().getSiegeDate(); } @Override public List getFlag(L2Clan clan) { if (clan != null) { L2SiegeClan sc = getAttackerClan(clan); if (sc != null) { return sc.getFlag(); } } return null; } public final FortSiegeGuardManager getSiegeGuardManager() { if (_siegeGuardManager == null) { _siegeGuardManager = new FortSiegeGuardManager(getFort()); } return _siegeGuardManager; } public void resetSiege() { // reload commanders and repair doors removeCommanders(); spawnCommanders(); getFort().resetDoors(); } public List getCommanders() { return _commanders; } @Override public L2SiegeClan getDefenderClan(int clanId) { return null; } @Override public L2SiegeClan getDefenderClan(L2Clan clan) { return null; } @Override public List getDefenderClans() { return null; } @Override public boolean giveFame() { return true; } @Override public int getFameFrequency() { return Config.FORTRESS_ZONE_FAME_TASK_FREQUENCY; } @Override public int getFameAmount() { return Config.FORTRESS_ZONE_FAME_AQUIRE_POINTS; } @Override public void updateSiege() { } }