/*
* This program 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.
*
* This program 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 gnu.trove.TIntIntHashMap;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Calendar;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastList;
import javolution.util.FastMap;
import com.l2jserver.Config;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.FortUpdater;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.datatables.ClanTable;
import com.l2jserver.gameserver.datatables.DoorTable;
import com.l2jserver.gameserver.datatables.NpcTable;
import com.l2jserver.gameserver.datatables.ResidentialSkillTable;
import com.l2jserver.gameserver.datatables.SpawnTable;
import com.l2jserver.gameserver.datatables.StaticObjects;
import com.l2jserver.gameserver.instancemanager.FortManager;
import com.l2jserver.gameserver.instancemanager.ZoneManager;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2Skill;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.instance.L2StaticObjectInstance;
import com.l2jserver.gameserver.model.zone.L2ZoneType;
import com.l2jserver.gameserver.model.zone.type.L2FortZone;
import com.l2jserver.gameserver.model.zone.type.L2SiegeZone;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.PlaySound;
import com.l2jserver.gameserver.network.serverpackets.PledgeShowInfoUpdate;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.gameserver.templates.chars.L2NpcTemplate;
public class Fort
{
protected static final Logger _log = Logger.getLogger(Fort.class.getName());
// =========================================================
// Data Field
private int _fortId = 0;
private List _doors = new FastList();
private L2StaticObjectInstance _flagPole = null;
private List _doorDefault = new FastList();
private List _flagPoleStats = new FastList();
private String _name = "";
private FortSiege _siege = null;
private Calendar _siegeDate;
private Calendar _lastOwnedTime;
private L2FortZone _fortZone;
private L2SiegeZone _zone;
private L2Clan _fortOwner = null;
private int _fortType = 0;
private int _state = 0;
private int _castleId = 0;
private int _blood = 0;
private FastMap _function;
private FastList _residentialSkills = new FastList();
private ScheduledFuture> _FortUpdater;
// Spawn Data
private boolean _isSuspiciousMerchantSpawned = false;
private FastList _siegeNpcs = new FastList();
private FastList _npcCommanders = new FastList();
private FastList _specialEnvoys = new FastList();
private TIntIntHashMap _envoyCastles = new TIntIntHashMap(2);
/** Fortress Functions */
public static final int FUNC_TELEPORT = 1;
public static final int FUNC_RESTORE_HP = 2;
public static final int FUNC_RESTORE_MP = 3;
public static final int FUNC_RESTORE_EXP = 4;
public static final int FUNC_SUPPORT = 5;
public class FortFunction
{
private int _type;
private int _lvl;
protected int _fee;
protected int _tempFee;
private long _rate;
private long _endDate;
protected boolean _inDebt;
public boolean _cwh;
public FortFunction(int type, int lvl, int lease, int tempLease, long rate, long time, boolean cwh)
{
_type = type;
_lvl = lvl;
_fee = lease;
_tempFee = tempLease;
_rate = rate;
_endDate = time;
initializeTask(cwh);
}
public int getType()
{
return _type;
}
public int getLvl()
{
return _lvl;
}
public int getLease()
{
return _fee;
}
public long getRate()
{
return _rate;
}
public long getEndTime()
{
return _endDate;
}
public void setLvl(int lvl)
{
_lvl = lvl;
}
public void setLease(int lease)
{
_fee = lease;
}
public void setEndTime(long time)
{
_endDate = time;
}
private void initializeTask(boolean cwh)
{
if (getOwnerClan() == null)
return;
long currentTime = System.currentTimeMillis();
if (_endDate > currentTime)
ThreadPoolManager.getInstance().scheduleGeneral(new FunctionTask(cwh), _endDate - currentTime);
else
ThreadPoolManager.getInstance().scheduleGeneral(new FunctionTask(cwh), 0);
}
private class FunctionTask implements Runnable
{
public FunctionTask(boolean cwh)
{
_cwh = cwh;
}
public void run()
{
try
{
if (getOwnerClan() == null)
return;
if (getOwnerClan().getWarehouse().getAdena() >= _fee || !_cwh)
{
int fee = _fee;
if (getEndTime() == -1)
fee = _tempFee;
setEndTime(System.currentTimeMillis() + getRate());
dbSave();
if (_cwh)
{
getOwnerClan().getWarehouse().destroyItemByItemId("CS_function_fee", 57, fee, null, null);
if (Config.DEBUG)
_log.warning("Deducted " + fee + " adena from " + getName() + " owner's cwh for function id : " + getType());
}
ThreadPoolManager.getInstance().scheduleGeneral(new FunctionTask(true), getRate());
}
else
removeFunction(getType());
}
catch (Throwable t)
{
}
}
}
public void dbSave()
{
Connection con = null;
try
{
PreparedStatement statement;
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement("REPLACE INTO fort_functions (fort_id, type, lvl, lease, rate, endTime) VALUES (?,?,?,?,?,?)");
statement.setInt(1, getFortId());
statement.setInt(2, getType());
statement.setInt(3, getLvl());
statement.setInt(4, getLease());
statement.setLong(5, getRate());
statement.setLong(6, getEndTime());
statement.execute();
statement.close();
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Exception: Fort.updateFunctions(int type, int lvl, int lease, long rate, long time, boolean addNew): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
}
// =========================================================
// Constructor
public Fort(int fortId)
{
_fortId = fortId;
load();
loadDoor();
loadFlagPoles();
_function = new FastMap();
_residentialSkills = ResidentialSkillTable.getInstance().getSkills(fortId);
if (getOwnerClan() != null)
{
setVisibleFlag(true);
loadFunctions();
}
initNpcs(); // load and spawn npcs (Always spawned)
initSiegeNpcs(); // load suspicious merchants (Despawned 10mins before siege)
//spawnSuspiciousMerchant();// spawn suspicious merchants
initNpcCommanders(); // npc Commanders (not monsters) (Spawned during siege)
spawnNpcCommanders(); // spawn npc Commanders
initSpecialEnvoys(); // envoys from castles (Spawned after fort taken)
if (getOwnerClan() != null && getFortState() == 0)
{
spawnSpecialEnvoys();
ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleSpecialEnvoysDeSpawn(this), 1 * 60 * 60 * 1000); // Prepare 1hr task for special envoys despawn
}
}
/** Return function with id */
public FortFunction getFunction(int type)
{
if (_function.get(type) != null)
return _function.get(type);
return null;
}
public class ScheduleSpecialEnvoysDeSpawn implements Runnable
{
private Fort _fortInst;
public ScheduleSpecialEnvoysDeSpawn(Fort pFort)
{
_fortInst = pFort;
}
public void run()
{
try
{
// if state not decided, change state to indenpendent
if (_fortInst.getFortState() == 0)
_fortInst.setFortState(1, 0);
_fortInst.despawnSpecialEnvoys();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: ScheduleSpecialEnvoysSpawn() for Fort " + _fortInst.getName() + ": " + e.getMessage(), e);
}
}
}
// =========================================================
// Method - Public
public void endOfSiege(L2Clan clan)
{
ThreadPoolManager.getInstance().scheduleGeneral(new endFortressSiege(this, clan), 1000);
}
public void engrave(L2Clan clan)
{
setOwner(clan, true);
}
/**
* Move non clan members off fort area and to nearest town.
*/
public void banishForeigners()
{
getFortZone().banishForeigners(getOwnerClan());
}
/**
* Return true if object is inside the zone
*/
public boolean checkIfInZone(int x, int y, int z)
{
return getZone().isInsideZone(x, y, z);
}
public L2SiegeZone getZone()
{
if (_zone == null)
{
for (L2ZoneType zone : ZoneManager.getInstance().getAllZones())
{
if (zone instanceof L2SiegeZone && ((L2SiegeZone) zone).getSiegeObjectId() == getFortId())
{
_zone = (L2SiegeZone) zone;
break;
}
}
}
return _zone;
}
public L2FortZone getFortZone()
{
if (_fortZone == null)
{
for (L2ZoneType zone : ZoneManager.getInstance().getAllZones())
{
if (zone instanceof L2FortZone && ((L2FortZone) zone).getFortId() == getFortId())
{
_fortZone = (L2FortZone) zone;
break;
}
}
}
return _fortZone;
}
/**
* Get the objects distance to this fort
* @param object
* @return
*/
public double getDistance(L2Object obj)
{
return getZone().getDistanceToZone(obj);
}
public void closeDoor(L2PcInstance activeChar, int doorId)
{
openCloseDoor(activeChar, doorId, false);
}
public void openDoor(L2PcInstance activeChar, int doorId)
{
openCloseDoor(activeChar, doorId, true);
}
public void openCloseDoor(L2PcInstance activeChar, int doorId, boolean open)
{
if (activeChar.getClan() != getOwnerClan())
return;
L2DoorInstance door = getDoor(doorId);
if (door != null)
{
if (open)
door.openMe();
else
door.closeMe();
}
}
// This method is used to begin removing all fort upgrades
public void removeUpgrade()
{
removeDoorUpgrade();
}
/**
* This method will set owner for Fort
* @param clan
* @param updateClanPoints
*/
public boolean setOwner(L2Clan clan, boolean updateClansReputation)
{
L2Clan oldowner = getOwnerClan();
// Remove old owner
if (oldowner != null && clan != null && clan != oldowner)
{
// Remove points from old owner
updateClansReputation(oldowner, true);
try
{
L2PcInstance oldleader = oldowner.getLeader().getPlayerInstance();
if (oldleader != null)
{
if (oldleader.getMountType() == 2)
oldleader.dismount();
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception in setOwner: " + e.getMessage(), e);
}
removeOwner(true);
}
setFortState(0, 0); // initialize fort state
// if clan already have castle, don't store him in fortress
if (clan.getHasCastle() > 0)
{
getSiege().announceToPlayer(new SystemMessage(SystemMessageId.NPCS_RECAPTURED_FORTRESS));
return false;
}
else
{
// Give points to new owner
if (updateClansReputation)
updateClansReputation(clan, false);
spawnSpecialEnvoys();
ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleSpecialEnvoysDeSpawn(this), 1 * 60 * 60 * 1000); // Prepare 1hr task for special envoys despawn
// if clan have already fortress, remove it
if (clan.getHasFort() > 0)
FortManager.getInstance().getFortByOwner(clan).removeOwner(true);
setBloodOathReward(0);
setOwnerClan(clan);
updateOwnerInDB(); // Update in database
if (getSiege().getIsInProgress()) // If siege in progress
getSiege().endSiege();
for (L2PcInstance member : clan.getOnlineMembers(0))
{
giveResidentialSkills(member);
member.sendSkillList();
}
return true;
}
}
public void removeOwner(boolean updateDB)
{
L2Clan clan = getOwnerClan();
if (clan != null)
{
for (L2PcInstance member : clan.getOnlineMembers(0))
{
removeResidentialSkills(member);
member.sendSkillList();
}
clan.setHasFort(0);
clan.broadcastToOnlineMembers(new PledgeShowInfoUpdate(clan));
setOwnerClan(null);
setBloodOathReward(0);
if (updateDB)
updateOwnerInDB();
}
}
public void setBloodOathReward(int val)
{
_blood = val;
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement;
statement = con.prepareStatement("UPDATE fort SET blood=? WHERE id = ?");
statement.setInt(1, _blood);
statement.setInt(2, getFortId());
statement.execute();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: setBloodOathReward(int val): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public int getBloodOathReward()
{
return _blood;
}
/**
* Show or hide flag inside flagpole
*/
public void setVisibleFlag(boolean val)
{
L2StaticObjectInstance flagPole = getFlagPole();
if (flagPole != null)
flagPole.setMeshIndex(val ? 1 : 0);
}
/**
* Respawn all doors on fort grounds
*/
public void resetDoors()
{
for (int i = 0; i < getDoors().size(); i++)
{
L2DoorInstance door = getDoors().get(i);
if (door.getOpen())
door.closeMe();
if (door.getCurrentHp() <= 0)
door.doRevive();
if (door.getCurrentHp() < door.getMaxHp())
door.setCurrentHp(door.getMaxHp());
}
loadDoorUpgrade(); // Check for any upgrade the doors may have
}
// This method upgrade door
public void upgradeDoor(int doorId, int hp, int pDef, int mDef)
{
L2DoorInstance door = getDoor(doorId);
if (door != null && door.getDoorId() == doorId)
{
door.setCurrentHp(door.getMaxHp() + hp);
saveDoorUpgrade(doorId, hp, pDef, mDef);
return;
}
}
// =========================================================
// Method - Private
// This method loads fort
private void load()
{
Connection con = null;
try
{
PreparedStatement statement;
ResultSet rs;
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement("SELECT * FROM fort WHERE id = ?");
statement.setInt(1, getFortId());
rs = statement.executeQuery();
int ownerId = 0;
while (rs.next())
{
_name = rs.getString("name");
_siegeDate = Calendar.getInstance();
_lastOwnedTime = Calendar.getInstance();
_siegeDate.setTimeInMillis(rs.getLong("siegeDate"));
_lastOwnedTime.setTimeInMillis(rs.getLong("lastOwnedTime"));
ownerId = rs.getInt("owner");
_fortType = rs.getInt("fortType");
_state = rs.getInt("state");
_castleId = rs.getInt("castleId");
_blood = rs.getInt("blood");
}
rs.close();
statement.close();
if (ownerId > 0)
{
L2Clan clan = ClanTable.getInstance().getClan(ownerId); // Try to find clan instance
clan.setHasFort(getFortId());
setOwnerClan(clan);
int runCount = getOwnedTime() / (Config.FS_BLOOD_OATH_FRQ * 60);
long initial = System.currentTimeMillis() - _lastOwnedTime.getTimeInMillis();
while (initial > (Config.FS_BLOOD_OATH_FRQ * 60000))
initial -= (Config.FS_BLOOD_OATH_FRQ * 60000);
initial = (Config.FS_BLOOD_OATH_FRQ * 60000) - initial;
_FortUpdater = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new FortUpdater(this, clan, runCount), initial, Config.FS_BLOOD_OATH_FRQ * 60000); // Schedule owner tasks to start running
}
else
setOwnerClan(null);
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: loadFortData(): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
/** Load All Functions */
private void loadFunctions()
{
Connection con = null;
try
{
PreparedStatement statement;
ResultSet rs;
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement("SELECT * FROM fort_functions WHERE fort_id = ?");
statement.setInt(1, getFortId());
rs = statement.executeQuery();
while (rs.next())
{
_function.put(rs.getInt("type"), new FortFunction(rs.getInt("type"), rs.getInt("lvl"), rs.getInt("lease"), 0, rs.getLong("rate"), rs.getLong("endTime"), true));
}
statement.close();
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Exception: Fort.loadFunctions(): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
/** Remove function In List and in DB */
public void removeFunction(int functionType)
{
_function.remove(functionType);
Connection con = null;
try
{
PreparedStatement statement;
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement("DELETE FROM fort_functions WHERE fort_id=? AND type=?");
statement.setInt(1, getFortId());
statement.setInt(2, functionType);
statement.execute();
statement.close();
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Exception: Fort.removeFunctions(int functionType): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public boolean updateFunctions(L2PcInstance player, int type, int lvl, int lease, long rate, boolean addNew)
{
if (player == null)
return false;
if (Config.DEBUG)
_log.warning("Called Fort.updateFunctions(int type, int lvl, int lease, long rate, boolean addNew) Owner : " + getOwnerClan());
if (lease > 0)
if (!player.destroyItemByItemId("Consume", 57, lease, null, true))
return false;
if (addNew)
{
_function.put(type, new FortFunction(type, lvl, lease, 0, rate, 0, false));
}
else
{
if (lvl == 0 && lease == 0)
removeFunction(type);
else
{
int diffLease = lease - _function.get(type).getLease();
if (Config.DEBUG)
_log.warning("Called Fort.updateFunctions diffLease : " + diffLease);
if (diffLease > 0)
{
_function.remove(type);
_function.put(type, new FortFunction(type, lvl, lease, 0, rate, -1, false));
}
else
{
_function.get(type).setLease(lease);
_function.get(type).setLvl(lvl);
_function.get(type).dbSave();
}
}
}
return true;
}
public void activateInstance()
{
for (final L2DoorInstance door : _doors)
{
door.spawnMe(door.getX(), door.getY(), door.getZ());
}
}
// This method loads fort door data from database
private void loadDoor()
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM fort_staticobjects WHERE fortId = ? AND objectType = ?");
statement.setInt(1, getFortId());
statement.setInt(2, 0);
ResultSet rs = statement.executeQuery();
while (rs.next())
{
// Create list of the door default for use when respawning dead doors
_doorDefault.add(rs.getString("name") + ";" + rs.getInt("id") + ";" + rs.getInt("x") + ";" + rs.getInt("y") + ";"
+ rs.getInt("z") + ";" + rs.getInt("range_xmin") + ";" + rs.getInt("range_ymin") + ";" + rs.getInt("range_zmin")
+ ";" + rs.getInt("range_xmax") + ";" + rs.getInt("range_ymax") + ";" + rs.getInt("range_zmax") + ";"
+ rs.getInt("hp") + ";" + rs.getInt("pDef") + ";" + rs.getInt("mDef") + ";" + rs.getBoolean("openType") + ";"
+ rs.getBoolean("commanderDoor"));
L2DoorInstance door;
_doors.add(door = DoorTable.parseList(_doorDefault.get(_doorDefault.size() - 1), true));
DoorTable.getInstance().putDoor(door);
}
rs.close();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: loadFortDoor(): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
// This method loads fort flagpoles data from database
private void loadFlagPoles()
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM fort_staticobjects WHERE fortId = ? AND objectType = ?");
statement.setInt(1, getFortId());
statement.setInt(2, 1);
ResultSet rs = statement.executeQuery();
while (rs.next())
{
//Create list of the door default for use when respawning dead doors
_flagPoleStats.add(rs.getString("name") + ";" + rs.getInt("id") + ";" + rs.getInt("x") + ";" + rs.getInt("y") + ";"
+ rs.getInt("z") + ";3;none;0;0");
_flagPole = StaticObjects.parse(_flagPoleStats.get(_flagPoleStats.size() - 1));
StaticObjects.getInstance().putObject(_flagPole);
}
rs.close();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: loadFlagPoles(): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
// This method loads fort door upgrade data from database
private void loadDoorUpgrade()
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM fort_doorupgrade WHERE doorId IN (SELECT Id FROM fort_staticobjects WHERE fortId = ? AND objectType = ?)");
statement.setInt(1, getFortId());
statement.setInt(2, 0);
ResultSet rs = statement.executeQuery();
while (rs.next())
{
upgradeDoor(rs.getInt("id"), rs.getInt("hp"), rs.getInt("pDef"), rs.getInt("mDef"));
}
rs.close();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: loadFortDoorUpgrade(): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
private void removeDoorUpgrade()
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM fort_doorupgrade WHERE doorId IN (SELECT id FROM fort_staticobjects WHERE fortId=? AND objectType = ?)");
statement.setInt(1, getFortId());
statement.setInt(2, 0);
statement.execute();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: removeDoorUpgrade(): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
private void saveDoorUpgrade(int doorId, int hp, int pDef, int mDef)
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("INSERT INTO fort_doorupgrade (doorId, hp, pDef, mDef) VALUES (?,?,?,?)");
statement.setInt(1, doorId);
statement.setInt(2, hp);
statement.setInt(3, pDef);
statement.setInt(4, mDef);
statement.execute();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: saveDoorUpgrade(int doorId, int hp, int pDef, int mDef): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
private void updateOwnerInDB()
{
L2Clan clan = getOwnerClan();
int clanId = 0;
if (clan != null)
{
clanId = clan.getClanId();
_lastOwnedTime.setTimeInMillis(System.currentTimeMillis());
}
else
_lastOwnedTime.setTimeInMillis(0);
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement;
statement = con.prepareStatement("UPDATE fort SET owner=?,lastOwnedTime=?,state=?,castleId=?,blood=? WHERE id = ?");
statement.setInt(1, clanId);
statement.setLong(2, _lastOwnedTime.getTimeInMillis());
statement.setInt(3, 0);
statement.setInt(4, 0);
statement.setInt(5, getBloodOathReward());
statement.setInt(6, getFortId());
statement.execute();
statement.close();
// ============================================================================
// Announce to clan memebers
if (clan != null)
{
clan.setHasFort(getFortId()); // Set has fort flag for new owner
SystemMessage sm;
sm = new SystemMessage(SystemMessageId.S1_CLAN_IS_VICTORIOUS_IN_THE_FORTRESS_BATTLE_OF_S2);
sm.addString(clan.getName());
sm.addFortId(getFortId());
Collection pls = L2World.getInstance().getAllPlayers().values();
for (L2PcInstance player : pls)
{
player.sendPacket(sm);
}
clan.broadcastToOnlineMembers(new PledgeShowInfoUpdate(clan));
clan.broadcastToOnlineMembers(new PlaySound(1, "Siege_Victory", 0, 0, 0, 0, 0));
if (_FortUpdater != null)
_FortUpdater.cancel(false);
_FortUpdater = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new FortUpdater(this, clan, 0), Config.FS_BLOOD_OATH_FRQ * 60000, Config.FS_BLOOD_OATH_FRQ * 60000); // Schedule owner tasks to start running
}
else
{
_FortUpdater.cancel(false);
_FortUpdater = null;
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: updateOwnerInDB(L2Clan clan): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public final int getFortId()
{
return _fortId;
}
public final L2Clan getOwnerClan()
{
return _fortOwner;
}
public final void setOwnerClan(L2Clan clan)
{
setVisibleFlag(clan != null ? true : false);
_fortOwner = clan;
}
public final L2DoorInstance getDoor(int doorId)
{
if (doorId <= 0)
return null;
for (L2DoorInstance door : getDoors())
{
if (door.getDoorId() == doorId)
return door;
}
return null;
}
public final List getDoors()
{
return _doors;
}
public final L2StaticObjectInstance getFlagPole()
{
return _flagPole;
}
public final FortSiege getSiege()
{
if (_siege == null)
_siege = new FortSiege(new Fort[] { this });
return _siege;
}
public final Calendar getSiegeDate()
{
return _siegeDate;
}
public final void setSiegeDate(Calendar siegeDate)
{
_siegeDate = siegeDate;
}
public final int getOwnedTime()
{
if (_lastOwnedTime.getTimeInMillis() == 0)
return 0;
return (int) ((System.currentTimeMillis() - _lastOwnedTime.getTimeInMillis()) / 1000);
}
public final String getName()
{
return _name;
}
public void updateClansReputation(L2Clan owner, boolean removePoints)
{
if (owner != null)
{
if (removePoints)
owner.takeReputationScore(Config.LOOSE_FORT_POINTS, true);
else
owner.addReputationScore(Config.TAKE_FORT_POINTS, true);
}
}
private class endFortressSiege implements Runnable
{
private Fort _f;
private L2Clan _clan;
public endFortressSiege(Fort f, L2Clan clan)
{
_f = f;
_clan = clan;
}
public void run()
{
try
{
_f.engrave(_clan);
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception in endFortressSiege " + e.getMessage(), e);
}
}
}
/**
* @return Returns state of fortress.
* 0 - not decided yet
* 1 - independent
* 2 - contracted with castle
*/
public final int getFortState()
{
return _state;
}
/**
* @param State.
* 0 - not decided yet
* 1 - independent
* 2 - contracted with castle
* @param CastleId.
* set Castle Id for contracted fort
*/
public final void setFortState(int state, int castleId)
{
_state = state;
_castleId = castleId;
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement;
statement = con.prepareStatement("UPDATE fort SET state=?,castleId=? WHERE id = ?");
statement.setInt(1, getFortState());
statement.setInt(2, getCastleId());
statement.setInt(3, getFortId());
statement.execute();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: setFortState(int state, int castleId): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
/**
* @return Returns Castle Id of fortress contracted with castle.
*/
public final int getCastleId()
{
return _castleId;
}
/**
* @return Returns fortress type.
* 0 - small (3 commanders)
* 1 - big (4 commanders + control room)
*/
public final int getFortType()
{
return _fortType;
}
public final int getCastleIdFromEnvoy(int npcId)
{
return _envoyCastles.get(npcId);
}
/**
* @return Returns amount of barracks.
*/
public final int getFortSize()
{
return getFortType() == 0 ? 3 : 5;
}
public void spawnSuspiciousMerchant()
{
if (_isSuspiciousMerchantSpawned)
return;
_isSuspiciousMerchantSpawned = true;
for (L2Spawn spawnDat : _siegeNpcs)
{
spawnDat.doSpawn();
spawnDat.startRespawn();
}
}
public void despawnSuspiciousMerchant()
{
if (!_isSuspiciousMerchantSpawned)
return;
_isSuspiciousMerchantSpawned = false;
for (L2Spawn spawnDat : _siegeNpcs)
{
spawnDat.stopRespawn();
spawnDat.getLastSpawn().deleteMe();
}
}
public void spawnNpcCommanders()
{
for (L2Spawn spawnDat : _npcCommanders)
{
spawnDat.doSpawn();
spawnDat.startRespawn();
}
}
public void despawnNpcCommanders()
{
for (L2Spawn spawnDat : _npcCommanders)
{
spawnDat.stopRespawn();
spawnDat.getLastSpawn().deleteMe();
}
}
public void spawnSpecialEnvoys()
{
for (L2Spawn spawnDat : _specialEnvoys)
{
spawnDat.doSpawn();
spawnDat.startRespawn();
}
}
public void despawnSpecialEnvoys()
{
for (L2Spawn spawnDat : _specialEnvoys)
{
spawnDat.stopRespawn();
spawnDat.getLastSpawn().deleteMe();
}
}
private void initNpcs()
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM fort_spawnlist WHERE fortId = ? AND spawnType = ? ");
statement.setInt(1, getFortId());
statement.setInt(2, 0);
ResultSet rset = statement.executeQuery();
L2Spawn spawnDat;
L2NpcTemplate template;
while (rset.next())
{
template = NpcTable.getInstance().getTemplate(rset.getInt("npcId"));
if (template != null)
{
spawnDat = new L2Spawn(template);
spawnDat.setAmount(1);
spawnDat.setLocx(rset.getInt("x"));
spawnDat.setLocy(rset.getInt("y"));
spawnDat.setLocz(rset.getInt("z"));
spawnDat.setHeading(rset.getInt("heading"));
spawnDat.setRespawnDelay(60);
SpawnTable.getInstance().addNewSpawn(spawnDat, false);
spawnDat.doSpawn();
spawnDat.startRespawn();
}
else
{
_log.warning("Fort " + getFortId() + " initNpcs: Data missing in NPC table for ID: " + rset.getInt("npcId") + ".");
}
}
rset.close();
statement.close();
}
catch (Exception e)
{
// problem with initializing spawn, go to next one
_log.log(Level.WARNING, "Fort " + getFortId() + " initNpcs: Spawn could not be initialized: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
private void initSiegeNpcs()
{
Connection con = null;
_siegeNpcs.clear();
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT id, npcId, x, y, z, heading FROM fort_spawnlist WHERE fortId = ? AND spawnType = ? ORDER BY id");
statement.setInt(1, getFortId());
statement.setInt(2, 2);
ResultSet rset = statement.executeQuery();
L2Spawn spawnDat;
L2NpcTemplate template;
while (rset.next())
{
template = NpcTable.getInstance().getTemplate(rset.getInt("npcId"));
if (template != null)
{
spawnDat = new L2Spawn(template);
spawnDat.setAmount(1);
spawnDat.setLocx(rset.getInt("x"));
spawnDat.setLocy(rset.getInt("y"));
spawnDat.setLocz(rset.getInt("z"));
spawnDat.setHeading(rset.getInt("heading"));
spawnDat.setRespawnDelay(60);
_siegeNpcs.add(spawnDat);
}
else
{
_log.warning("Fort " + getFortId() + " initSiegeNpcs: Data missing in NPC table for ID: " + rset.getInt("npcId") + ".");
}
}
rset.close();
statement.close();
}
catch (Exception e)
{
// problem with initializing spawn, go to next one
_log.log(Level.WARNING, "Fort " + getFortId() + " initSiegeNpcs: Spawn could not be initialized: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
private void initNpcCommanders()
{
Connection con = null;
_npcCommanders.clear();
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT id, npcId, x, y, z, heading FROM fort_spawnlist WHERE fortId = ? AND spawnType = ? ORDER BY id");
statement.setInt(1, getFortId());
statement.setInt(2, 1);
ResultSet rset = statement.executeQuery();
L2Spawn spawnDat;
L2NpcTemplate template;
while (rset.next())
{
template = NpcTable.getInstance().getTemplate(rset.getInt("npcId"));
if (template != null)
{
spawnDat = new L2Spawn(template);
spawnDat.setAmount(1);
spawnDat.setLocx(rset.getInt("x"));
spawnDat.setLocy(rset.getInt("y"));
spawnDat.setLocz(rset.getInt("z"));
spawnDat.setHeading(rset.getInt("heading"));
spawnDat.setRespawnDelay(60);
_npcCommanders.add(spawnDat);
}
else
{
_log.warning("Fort " + getFortId() + " initNpcCommanders: Data missing in NPC table for ID: " + rset.getInt("npcId")
+ ".");
}
}
rset.close();
statement.close();
}
catch (Exception e)
{
// problem with initializing spawn, go to next one
_log.log(Level.WARNING, "Fort " + getFortId() + " initNpcCommanders: Spawn could not be initialized: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
private void initSpecialEnvoys()
{
Connection con = null;
_specialEnvoys.clear();
_envoyCastles.clear();
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT id, npcId, x, y, z, heading, castleId FROM fort_spawnlist WHERE fortId = ? AND spawnType = ? ORDER BY id");
statement.setInt(1, getFortId());
statement.setInt(2, 3);
ResultSet rset = statement.executeQuery();
L2Spawn spawnDat;
L2NpcTemplate template;
while (rset.next())
{
int castleId = rset.getInt("castleId");
int npcId = rset.getInt("npcId");
template = NpcTable.getInstance().getTemplate(npcId);
if (template != null)
{
spawnDat = new L2Spawn(template);
spawnDat.setAmount(1);
spawnDat.setLocx(rset.getInt("x"));
spawnDat.setLocy(rset.getInt("y"));
spawnDat.setLocz(rset.getInt("z"));
spawnDat.setHeading(rset.getInt("heading"));
spawnDat.setRespawnDelay(60);
_specialEnvoys.add(spawnDat);
_envoyCastles.put(npcId, castleId);
}
else
{
_log.warning("Fort " + getFortId() + " initSpecialEnvoys: Data missing in NPC table for ID: " + rset.getInt("npcId")
+ ".");
}
}
rset.close();
statement.close();
}
catch (Exception e)
{
// problem with initializing spawn, go to next one
_log.log(Level.WARNING, "Fort " + getFortId() + " initSpecialEnvoys: Spawn could not be initialized: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public FastList getResidentialSkills()
{
return _residentialSkills;
}
public void giveResidentialSkills(L2PcInstance player)
{
if (_residentialSkills != null && !_residentialSkills.isEmpty())
{
for (L2Skill sk : _residentialSkills)
player.addSkill(sk, false);
}
}
public void removeResidentialSkills(L2PcInstance player)
{
if (_residentialSkills != null && !_residentialSkills.isEmpty())
{
for (L2Skill sk : _residentialSkills)
player.removeSkill(sk, false, true);
}
}
}