Prechádzať zdrojové kódy

BETA: Convert door data to XML format.

Thanks to JIV for initial design.
GodKratos 13 rokov pred
rodič
commit
b59b416fe0

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/GeoEngine.java

@@ -100,7 +100,7 @@ public class GeoEngine extends GeoData
 	@Override
 	public boolean canSeeTarget(L2Object cha, Point3D target)
 	{
-		if (DoorTable.getInstance().checkIfDoorsBetween(cha.getX(), cha.getY(), cha.getZ(), target.getX(), target.getY(), target.getZ(), cha.getInstanceId()))
+		if (DoorTable.getInstance().checkIfDoorsBetween(cha.getX(), cha.getY(), cha.getZ(), target.getX(), target.getY(), target.getZ(), cha.getInstanceId(), true))
 			return false;
 		if (cha.getZ() >= target.getZ())
 			return canSeeTarget(cha.getX(), cha.getY(), cha.getZ(), target.getX(), target.getY(), target.getZ());
@@ -126,7 +126,7 @@ public class GeoEngine extends GeoData
 			z += 30; // well they don't move closer to balcony fence at the moment :(
 		int z2 = target.getZ() + 45;
 		if (!(target instanceof L2DoorInstance)
-				&& DoorTable.getInstance().checkIfDoorsBetween(cha.getX(), cha.getY(), z, target.getX(), target.getY(), z2, cha.getInstanceId()))
+				&& DoorTable.getInstance().checkIfDoorsBetween(cha.getX(), cha.getY(), z, target.getX(), target.getY(), z2, cha.getInstanceId(), true))
 			return false;
 		if (target instanceof L2DoorInstance)
 			return true; // door coordinates are hinge coords..

+ 139 - 374
L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/DoorTable.java

@@ -16,445 +16,222 @@ package com.l2jserver.gameserver.datatables;
 
 import gnu.trove.map.hash.TIntObjectHashMap;
 
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.LineNumberReader;
 import java.util.ArrayList;
-import java.util.StringTokenizer;
-import java.util.logging.Level;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.logging.Logger;
 
-import com.l2jserver.Config;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import com.l2jserver.gameserver.engines.DocumentParser;
 import com.l2jserver.gameserver.idfactory.IdFactory;
-import com.l2jserver.gameserver.instancemanager.ClanHallManager;
 import com.l2jserver.gameserver.instancemanager.InstanceManager;
 import com.l2jserver.gameserver.instancemanager.MapRegionManager;
 import com.l2jserver.gameserver.model.StatsSet;
 import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
-import com.l2jserver.gameserver.model.actor.templates.L2CharTemplate;
-import com.l2jserver.gameserver.model.entity.ClanHall;
-import com.l2jserver.gameserver.model.entity.clanhall.SiegableHall;
+import com.l2jserver.gameserver.model.actor.templates.L2DoorTemplate;
 import com.l2jserver.gameserver.pathfinding.AbstractNodeLoc;
 
-public class DoorTable
+public class DoorTable extends DocumentParser
 {
 	private static final Logger _log = Logger.getLogger(DoorTable.class.getName());
 	
-	private final TIntObjectHashMap<L2DoorInstance> _staticItems;
-	private final TIntObjectHashMap<ArrayList<L2DoorInstance>> _regions;
+	private final TIntObjectHashMap<L2DoorInstance> _doors = new TIntObjectHashMap<L2DoorInstance>();
+	private static final TIntObjectHashMap<Set<Integer>> _groups = new TIntObjectHashMap<Set<Integer>>();
+	private final TIntObjectHashMap<ArrayList<L2DoorInstance>> _regions = new TIntObjectHashMap<ArrayList<L2DoorInstance>>();
 	
 	protected DoorTable()
 	{
-		_staticItems = new TIntObjectHashMap<L2DoorInstance>();
-		_regions = new TIntObjectHashMap<ArrayList<L2DoorInstance>>();
-		parseData();
-		onStart();
+		load();
 	}
 	
-	public void reloadAll()
+	@Override
+	public void load()
 	{
-		respawn();
+		parseDatapackFile("data/doorData.xml");
 	}
 	
-	public void respawn()
+	public void reloadAll()
 	{
-		_staticItems.clear();
+		_doors.clear();
+		_groups.clear();
 		_regions.clear();
-		parseData();
+		load();
 	}
 	
-	public void parseData()
+	@Override
+	protected void parseDocument()
 	{
-		final File doorData = new File(Config.DATAPACK_ROOT, "data/door.csv");
-		try (
-			FileReader fr = new FileReader(doorData);
-			BufferedReader br = new BufferedReader(fr);
-			LineNumberReader lnr = new LineNumberReader(br))
+		NamedNodeMap attrs;
+		Node att;
+		StatsSet set;
+		for (Node a = getCurrentDocument().getFirstChild(); a != null; a = a.getNextSibling())
 		{
-			String line = null;
-			_log.info("Searching clan halls doors:");
-			
-			while ((line = lnr.readLine()) != null)
+			if ("list".equalsIgnoreCase(a.getNodeName()))
 			{
-				if ((line.trim().length() == 0) || line.startsWith("#"))
+				for (Node b = a.getFirstChild(); b != null; b = b.getNextSibling())
 				{
-					continue;
+					if ("door".equalsIgnoreCase(b.getNodeName()))
+					{
+						attrs = b.getAttributes();
+						set = new StatsSet();
+						for (int i = 0; i < attrs.getLength(); i++)
+						{
+							att = attrs.item(i);
+							set.set(att.getNodeName(), att.getNodeValue());
+						}
+						makeDoor(set);
+					}
 				}
-				
-				L2DoorInstance door = parseList(line, false);
-				putDoor(door);
-				door.spawnMe(door.getX(), door.getY(), door.getZ());
 			}
-			
-			_log.info("DoorTable: Loaded " + _staticItems.size() + " Door Templates for " + _regions.size() + " regions.");
-		}
-		catch (FileNotFoundException e)
-		{
-			_log.warning("door.csv is missing in data folder");
-		}
-		catch (IOException e)
-		{
-			_log.log(Level.WARNING, "Error while creating door table " + e.getMessage(), e);
 		}
+		
+		_log.info("DoorTable: Loaded " + _doors.size() + " Door Templates for " + _regions.size() + " regions."); 
+	}
+	
+	public void insertCollisionData(StatsSet set)
+	{
+		int posX, posY, nodeX, nodeY, height;
+		height = set.getInteger("height");
+		String[] pos = set.getString("node1").split(",");
+		nodeX = Integer.parseInt(pos[0]);
+		nodeY = Integer.parseInt(pos[1]);
+		pos = set.getString("node2").split(",");
+		posX = Integer.parseInt(pos[0]);
+		posY = Integer.parseInt(pos[1]);
+		int collisionRadius; // (max) radius for movement checks
+		collisionRadius = Math.min(Math.abs(nodeX - posX), Math.abs(nodeY - posY));
+		if (collisionRadius < 20)
+			collisionRadius = 20;
+
+		set.set("collision_radius", collisionRadius);
+		set.set("collision_height", height);
 	}
 	
 	/**
-	 * Parses door list.
-	 * @param line string
-	 * @param commanderDoor whether the door is commander door (fortress)
-	 * @return created door instance
+	 * @param set
 	 */
-	public static L2DoorInstance parseList(final String line, final boolean commanderDoor)
+	private void makeDoor(StatsSet set)
 	{
-		StringTokenizer st = new StringTokenizer(line, ";");
-		L2DoorInstance door = null;
-		try
-		{
-			String name = st.nextToken();
-			int id = Integer.parseInt(st.nextToken());
-			int x = Integer.parseInt(st.nextToken());
-			int y = Integer.parseInt(st.nextToken());
-			int z = Integer.parseInt(st.nextToken());
-			int rangeXMin = Integer.parseInt(st.nextToken());
-			int rangeYMin = Integer.parseInt(st.nextToken());
-			int rangeZMin = Integer.parseInt(st.nextToken());
-			int rangeXMax = Integer.parseInt(st.nextToken());
-			int rangeYMax = Integer.parseInt(st.nextToken());
-			int rangeZMax = Integer.parseInt(st.nextToken());
-			int hp = Integer.parseInt(st.nextToken());
-			int pdef = Integer.parseInt(st.nextToken());
-			int mdef = Integer.parseInt(st.nextToken());
-			int emitter = Integer.parseInt(st.nextToken());
-			boolean unlockable = false;
-			if (st.hasMoreTokens())
-			{
-				unlockable = Boolean.parseBoolean(st.nextToken());
-			}
-			boolean startOpen = false;
-			if (st.hasMoreTokens())
-			{
-				startOpen = Boolean.parseBoolean(st.nextToken());
-			}
-			boolean targetable = true;
-			if (st.hasMoreTokens())
-			{
-				targetable = Boolean.parseBoolean(st.nextToken());
-			}
-			int hallId = 0;
-			if (st.hasMoreTokens())
-			{
-				hallId = Integer.parseInt(st.nextToken());
-			}
-			
-			if (rangeXMin > rangeXMax)
-			{
-				_log.severe("Error in door data, XMin > XMax, ID:" + id);
-			}
-			if (rangeYMin > rangeYMax)
-			{
-				_log.severe("Error in door data, YMin > YMax, ID:" + id);
-			}
-			if (rangeZMin > rangeZMax)
-			{
-				_log.severe("Error in door data, ZMin > ZMax, ID:" + id);
-			}
-			int collisionRadius; // (max) radius for movement checks
-			if ((rangeXMax - rangeXMin) > (rangeYMax - rangeYMin))
-			{
-				collisionRadius = rangeYMax - rangeYMin;
-			}
-			else
-			{
-				collisionRadius = rangeXMax - rangeXMin;
-			}
-			
-			StatsSet npcDat = new StatsSet();
-			npcDat.set("npcId", id);
-			npcDat.set("level", 0);
-			npcDat.set("jClass", "door");
-			
-			npcDat.set("baseSTR", 0);
-			npcDat.set("baseCON", 0);
-			npcDat.set("baseDEX", 0);
-			npcDat.set("baseINT", 0);
-			npcDat.set("baseWIT", 0);
-			npcDat.set("baseMEN", 0);
-			
-			npcDat.set("baseShldDef", 0);
-			npcDat.set("baseShldRate", 0);
-			npcDat.set("baseAccCombat", 38);
-			npcDat.set("baseEvasRate", 38);
-			npcDat.set("baseCritRate", 38);
-			
-			// npcDat.set("name", "");
-			npcDat.set("collision_radius", collisionRadius);
-			npcDat.set("collision_height", rangeZMax - rangeZMin);
-			npcDat.set("sex", "male");
-			npcDat.set("type", "");
-			npcDat.set("baseAtkRange", 0);
-			npcDat.set("baseMpMax", 0);
-			npcDat.set("baseCpMax", 0);
-			npcDat.set("rewardExp", 0);
-			npcDat.set("rewardSp", 0);
-			npcDat.set("basePAtk", 0);
-			npcDat.set("baseMAtk", 0);
-			npcDat.set("basePAtkSpd", 0);
-			npcDat.set("aggroRange", 0);
-			npcDat.set("baseMAtkSpd", 0);
-			npcDat.set("rhand", 0);
-			npcDat.set("lhand", 0);
-			npcDat.set("armor", 0);
-			npcDat.set("baseWalkSpd", 0);
-			npcDat.set("baseRunSpd", 0);
-			npcDat.set("name", name);
-			npcDat.set("baseHpMax", hp);
-			npcDat.set("baseHpReg", 3.e-3f);
-			npcDat.set("baseMpReg", 3.e-3f);
-			npcDat.set("basePDef", pdef);
-			npcDat.set("baseMDef", mdef);
-			
-			L2CharTemplate template = new L2CharTemplate(npcDat);
-			door = new L2DoorInstance(IdFactory.getInstance().getNextId(), template, id, name, unlockable);
-			door.setRange(rangeXMin, rangeYMin, rangeZMin, rangeXMax, rangeYMax, rangeZMax);
-			door.setCurrentHpMp(door.getMaxHp(), door.getMaxMp());
-			door.setXYZInvisible(x, y, z);
-			door.setMapRegion(MapRegionManager.getInstance().getMapRegionLocId(x, y));
-			door.setEmitter(emitter);
-			door.setTargetable(targetable);
-			
-			if (hallId > 0)
-			{
-				ClanHall hall = ClanHallManager.getAllClanHalls().get(hallId);
-				if (hall != null)
-				{
-					door.setClanHall(hall);
-					hall.getDoors().add(door);
-					
-					if (hall.isSiegableHall())
-					{
-						((SiegableHall) hall).getDoorDefault().add(line);
-					}
-				}
-			}
-			
-			if (commanderDoor)
-			{
-				door.setIsCommanderDoor(startOpen);
-			}
-			else
-			{
-				door.setOpen(startOpen);
-			}
-		}
-		catch (Exception e)
-		{
-			_log.log(Level.SEVERE, "Error in door data at line: " + line, e);
-		}
-		return door;
+		insertCollisionData(set);
+		L2DoorTemplate template = new L2DoorTemplate(set);
+		L2DoorInstance door = new L2DoorInstance(IdFactory.getInstance().getNextId(), template, set);
+		door.setCurrentHp(door.getMaxHp());
+		door.spawnMe(template.posX, template.posY, template.posZ);
+		putDoor(door, MapRegionManager.getInstance().getMapRegionLocId(door.getX(), door.getY()));
 	}
-	
-	public L2DoorInstance getDoor(Integer id)
+
+	public L2DoorTemplate getDoorTemplate(int doorId)
 	{
-		return _staticItems.get(id);
+		return _doors.get(doorId).getTemplate();
 	}
 	
-	public void putDoor(L2DoorInstance door)
+	public L2DoorInstance getDoor(int doorId)
+	{
+		return _doors.get(doorId);
+	}
+
+	public void putDoor(L2DoorInstance door, int region)
 	{
-		_staticItems.put(door.getDoorId(), door);
+		_doors.put(door.getDoorId(), door);
 		
-		if (_regions.contains(door.getMapRegion()))
+		if (_regions.contains(region))
+			_regions.get(region).add(door);
+		else
 		{
-			_regions.get(door.getMapRegion()).add(door);
+			final ArrayList<L2DoorInstance> list = new ArrayList<L2DoorInstance>();
+			list.add(door);
+			_regions.put(region, list);
+		}
+	}
+
+	public static void addDoorGroup(String groupName, int doorId)
+	{
+		Set<Integer> set = _groups.get(groupName.hashCode());
+		if (set == null)
+		{
+			set = new HashSet<Integer>();
+			set.add(doorId);
+			_groups.put(groupName.hashCode(), set);
 		}
 		else
 		{
-			final ArrayList<L2DoorInstance> region = new ArrayList<L2DoorInstance>();
-			region.add(door);
-			_regions.put(door.getMapRegion(), region);
+			set.add(doorId);
 		}
 	}
 	
-	public L2DoorInstance[] getDoors()
+	public static Set<Integer> getDoorsByGroup(String groupName)
 	{
-		return _staticItems.values(new L2DoorInstance[0]);
+		return _groups.get(groupName.hashCode());
 	}
 	
-	/**
-	 * Performs a check and sets up a scheduled task for those doors that require auto opening/closing.
-	 */
-	public void checkAutoOpen()
+	public L2DoorInstance[] getDoors()
 	{
-		for (L2DoorInstance doorInst : getDoors())
-		{
-			// Tower of Insolence (open_time 120 seconds)
-			// TODO: (close_time 120 seconds & random_time 120 seconds)
-			if (doorInst.getDoorName().startsWith("toi_"))
-			{
-				doorInst.setAutoActionDelay(120000);
-			}
-			
-			// Devil Isle (open_time 120 seconds)
-			// TODO: (close_time 120 seconds & random_time 30 seconds)
-			else if (doorInst.getDoorName().startsWith("di_"))
-			{
-				doorInst.setAutoActionDelay(120000);
-			}
-			
-			// Garden of Eva (open_time 300 seconds)
-			// TODO: (close_time 20 seconds & random_time 120 seconds)
-			else if (doorInst.getDoorName().startsWith("goe_"))
-			{
-				doorInst.setAutoActionDelay(300000);
-			}
-			
-			// Kratei's Cube (open_time 20 seconds)
-			// TODO: (close_time 15 seconds & random_time 10 seconds)
-			else if (doorInst.getDoorName().startsWith("kc20_"))
-			{
-				doorInst.setAutoActionDelay(20000);
-			}
-			
-			// Kratei's Cube (open_time 30 seconds)
-			// TODO: (close_time 15 seconds & random_time 10 seconds)
-			else if (doorInst.getDoorName().startsWith("kc30_"))
-			{
-				doorInst.setAutoActionDelay(30000);
-			}
-			
-			// Kratei's Cube (open_time 25 seconds)
-			// TODO: (close_time 15 seconds & random_time 10 seconds)
-			else if (doorInst.getDoorName().startsWith("kc25_"))
-			{
-				doorInst.setAutoActionDelay(25000);
-			}
-			
-			// Kratei's Cube (open_time 15 seconds)
-			// TODO: (close_time 15 seconds & random_time 10 seconds)
-			else if (doorInst.getDoorName().startsWith("kc15_"))
-			{
-				doorInst.setAutoActionDelay(15000);
-			}
-			
-			// Kratei's Cube (open_time 10 seconds)
-			// TODO: (close_time 15 seconds & random_time 5 seconds)
-			else if (doorInst.getDoorName().startsWith("kc10_"))
-			{
-				doorInst.setAutoActionDelay(10000);
-			}
-			
-			// Kratei's Cube (open_time 10 seconds)
-			// TODO: (close_time 15 seconds & random_time 10 seconds)
-			else if (doorInst.getDoorName().startsWith("kc10b_"))
-			{
-				doorInst.setAutoActionDelay(10000);
-			}
-			
-			// Kratei's Cube (open_time 14 seconds)
-			// TODO: (close_time 15 seconds & random_time 10 seconds)
-			else if (doorInst.getDoorName().startsWith("kc14_"))
-			{
-				doorInst.setAutoActionDelay(14000);
-			}
-			
-			// Kratei's Cube (open_time 23 seconds)
-			// TODO: (close_time 15 seconds & random_time 10 seconds)
-			else if (doorInst.getDoorName().startsWith("kc23_"))
-			{
-				doorInst.setAutoActionDelay(23000);
-			}
-			
-			// Kratei's Cube (open_time 18 seconds)
-			// TODO: (close_time 15 seconds & random_time 10 seconds)
-			else if (doorInst.getDoorName().startsWith("kc18_"))
-			{
-				doorInst.setAutoActionDelay(18000);
-			}
-			
-			// Kratei's Cube (open_time 26 seconds)
-			// TODO: (close_time 15 seconds & random_time 10 seconds)
-			else if (doorInst.getDoorName().startsWith("kc26_"))
-			{
-				doorInst.setAutoActionDelay(26000);
-			}
-		}
+		return _doors.values(new L2DoorInstance[0]);
 	}
-	
+
 	public boolean checkIfDoorsBetween(AbstractNodeLoc start, AbstractNodeLoc end, int instanceId)
 	{
 		return checkIfDoorsBetween(start.getX(), start.getY(), start.getZ(), end.getX(), end.getY(), end.getZ(), instanceId);
 	}
 	
 	public boolean checkIfDoorsBetween(int x, int y, int z, int tx, int ty, int tz, int instanceId)
+	{
+		return checkIfDoorsBetween(x, y, z, tx, ty, tz, instanceId, false);
+	}
+
+	/**
+	 * @param x 
+	 * @param y 
+	 * @param z 
+	 * @param tx 
+	 * @param ty 
+	 * @param tz 
+	 * @param instanceId 
+	 * @param doubleFaceCheck 
+	 * @return
+	 *  
+	 * TODO: remove geodata checks from door table and convert door nodes to geo zones
+	 */
+	public boolean checkIfDoorsBetween(int x, int y, int z, int tx, int ty, int tz, int instanceId, boolean doubleFaceCheck)
 	{
 		ArrayList<L2DoorInstance> allDoors;
-		if ((instanceId > 0) && (InstanceManager.getInstance().getInstance(instanceId) != null))
-		{
+		if (instanceId > 0 && InstanceManager.getInstance().getInstance(instanceId) != null)
 			allDoors = InstanceManager.getInstance().getInstance(instanceId).getDoors();
-		}
 		else
-		{
 			allDoors = _regions.get(MapRegionManager.getInstance().getMapRegionLocId(x, y));
-		}
 		
 		if (allDoors == null)
-		{
 			return false;
-		}
 		
 		for (L2DoorInstance doorInst : allDoors)
 		{
-			if (doorInst.getXMax() == 0)
-			{
+			//check dead and open
+			if (doorInst.isDead() || doorInst.getOpen() || !doorInst.checkCollision() || doorInst.getX(0) == 0)
 				continue;
-			}
 			
-			// line segment goes through box
-			// first basic checks to stop most calculations short
-			// phase 1, x
-			if (((x <= doorInst.getXMax()) && (tx >= doorInst.getXMin())) || ((tx <= doorInst.getXMax()) && (x >= doorInst.getXMin())))
+			boolean intersectFace = false;
+			for (int i = 0; i < 4; i++)
 			{
-				// phase 2, y
-				if (((y <= doorInst.getYMax()) && (ty >= doorInst.getYMin())) || ((ty <= doorInst.getYMax()) && (y >= doorInst.getYMin())))
+				int j = i + 1 < 4 ? i + 1 : 0;
+				// lower part of the multiplier fraction, if it is 0 we avoid an error and also know that the lines are parallel
+				int denominator = (ty - y) * (doorInst.getX(i) - doorInst.getX(j)) - (tx - x) * (doorInst.getY(i) - doorInst.getY(j));
+				if (denominator == 0)
+					continue;
+				
+				// multipliers to the equations of the lines. If they are lower than 0 or bigger than 1, we know that segments don't intersect
+				float multiplier1 = (float)((doorInst.getX(j) - doorInst.getX(i)) * (y - doorInst.getY(i)) - (doorInst.getY(j) - doorInst.getY(i)) * (x - doorInst.getX(i))) / denominator;
+				float multiplier2 = (float)((tx - x) * (y - doorInst.getY(i)) - (ty - y) * (x - doorInst.getX(i))) / denominator;
+				if (multiplier1 >= 0 && multiplier1 <= 1 && multiplier2 >= 0 && multiplier2 <= 1)
 				{
-					// phase 3, basically only z remains but now we calculate it with another formula (by rage)
-					// in some cases the direct line check (only) in the beginning isn't sufficient,
-					// when char z changes a lot along the path
-					if ((doorInst.getCurrentHp() > 0) && !doorInst.getOpen())
+					int intersectZ = Math.round(z + multiplier1 * (tz - z));
+					// now checking if the resulting point is between door's min and max z
+					if (intersectZ > doorInst.getZMin() && intersectZ < doorInst.getZMax())
 					{
-						int px1 = doorInst.getXMin();
-						int py1 = doorInst.getYMin();
-						int pz1 = doorInst.getZMin();
-						int px2 = doorInst.getXMax();
-						int py2 = doorInst.getYMax();
-						int pz2 = doorInst.getZMax();
-						
-						int l = tx - x;
-						int m = ty - y;
-						int n = tz - z;
-						
-						int dk;
-						
-						if ((dk = ((doorInst.getA() * l) + (doorInst.getB() * m) + (doorInst.getC() * n))) == 0)
-						{
-							continue; // Parallel
-						}
-						
-						float p = (float) ((doorInst.getA() * x) + (doorInst.getB() * y) + (doorInst.getC() * z) + doorInst.getD()) / (float) dk;
-						
-						int fx = (int) (x - (l * p));
-						int fy = (int) (y - (m * p));
-						int fz = (int) (z - (n * p));
-						
-						if (((Math.min(x, tx) <= fx) && (fx <= Math.max(x, tx))) && ((Math.min(y, ty) <= fy) && (fy <= Math.max(y, ty))) && ((Math.min(z, tz) <= fz) && (fz <= Math.max(z, tz))))
-						{
-							if ((((fx >= px1) && (fx <= px2)) || ((fx >= px2) && (fx <= px1))) && (((fy >= py1) && (fy <= py2)) || ((fy >= py2) && (fy <= py1))) && (((fz >= pz1) && (fz <= pz2)) || ((fz >= pz2) && (fz <= pz1))))
-							{
-								return true; // Door between
-							}
-						}
+						if (!doubleFaceCheck || intersectFace)
+							return true;
+						intersectFace = true;
 					}
 				}
 			}
@@ -462,18 +239,6 @@ public class DoorTable
 		return false;
 	}
 	
-	private void onStart()
-	{
-		try
-		{
-			checkAutoOpen();
-		}
-		catch (NullPointerException e)
-		{
-			_log.log(Level.WARNING, "There are errors in your Door.csv file. Update door.csv", e);
-		}
-	}
-	
 	public static DoorTable getInstance()
 	{
 		return SingletonHolder._instance;

+ 275 - 292
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2DoorInstance.java

@@ -15,31 +15,35 @@
 package com.l2jserver.gameserver.model.actor.instance;
 
 import java.util.Collection;
-import java.util.concurrent.ScheduledFuture;
-import java.util.logging.Level;
+import java.util.Set;
+import java.util.concurrent.Future;
 import java.util.logging.Logger;
 
 import javolution.util.FastList;
 
-import com.l2jserver.Config;
 import com.l2jserver.gameserver.ThreadPoolManager;
 import com.l2jserver.gameserver.ai.L2CharacterAI;
 import com.l2jserver.gameserver.ai.L2DoorAI;
+import com.l2jserver.gameserver.datatables.DoorTable;
 import com.l2jserver.gameserver.instancemanager.CastleManager;
+import com.l2jserver.gameserver.instancemanager.ClanHallManager;
 import com.l2jserver.gameserver.instancemanager.FortManager;
+import com.l2jserver.gameserver.instancemanager.InstanceManager;
 import com.l2jserver.gameserver.instancemanager.TerritoryWarManager;
 import com.l2jserver.gameserver.model.L2CharPosition;
 import com.l2jserver.gameserver.model.L2Clan;
 import com.l2jserver.gameserver.model.L2Object;
+import com.l2jserver.gameserver.model.StatsSet;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.L2Playable;
 import com.l2jserver.gameserver.model.actor.knownlist.DoorKnownList;
 import com.l2jserver.gameserver.model.actor.stat.DoorStat;
 import com.l2jserver.gameserver.model.actor.status.DoorStatus;
-import com.l2jserver.gameserver.model.actor.templates.L2CharTemplate;
+import com.l2jserver.gameserver.model.actor.templates.L2DoorTemplate;
 import com.l2jserver.gameserver.model.entity.Castle;
 import com.l2jserver.gameserver.model.entity.ClanHall;
 import com.l2jserver.gameserver.model.entity.Fort;
+import com.l2jserver.gameserver.model.entity.Instance;
 import com.l2jserver.gameserver.model.entity.clanhall.SiegableHall;
 import com.l2jserver.gameserver.model.items.L2Weapon;
 import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
@@ -49,6 +53,7 @@ import com.l2jserver.gameserver.network.serverpackets.DoorStatusUpdate;
 import com.l2jserver.gameserver.network.serverpackets.OnEventTrigger;
 import com.l2jserver.gameserver.network.serverpackets.StaticObject;
 import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
+import com.l2jserver.util.Rnd;
 
 /**
  * This class ...
@@ -59,42 +64,66 @@ public class L2DoorInstance extends L2Character
 {
 	protected static final Logger log = Logger.getLogger(L2DoorInstance.class.getName());
 	
+	private static final byte OPEN_BY_CLICK = 1;
+	private static final byte OPEN_BY_TIME = 2;
+	private static final byte OPEN_BY_ITEM = 4;
+	private static final byte OPEN_BY_SKILL = 8;
+	private static final byte OPEN_BY_CYCLE = 16;
+	
 	/** The castle index in the array of L2Castle this L2NpcInstance belongs to */
 	private int _castleIndex = -2;
-	private int _mapRegion = -1;
 	/** The fort index in the array of L2Fort this L2NpcInstance belongs to */
 	private int _fortIndex = -2;
-	
-	// when door is closed, the dimensions are
-	private int _rangeXMin = 0;
-	private int _rangeYMin = 0;
-	private int _rangeZMin = 0;
-	private int _rangeXMax = 0;
-	private int _rangeYMax = 0;
-	private int _rangeZMax = 0;
-	
-	// these variables assist in see-through calculation only
-	private int _A = 0;
-	private int _B = 0;
-	private int _C = 0;
-	private int _D = 0;
-	
-	protected final int _doorId;
-	protected final String _name;
-	private boolean _open;
-	private boolean _isCommanderDoor;
-	private final boolean _unlockable;
+	private ClanHall _clanHall;
+	private boolean _open = false;
 	private boolean _isAttackableDoor = false;
-	private boolean _isWall = false; // is castle wall ?
-	private boolean _ShowHp = false;
+	private boolean _isTargetable;
+	private boolean _checkCollision;
+	private int _openType = 0;
 	private int _meshindex = 1;
-	private int _emitter = 0;
-	private boolean _targetable = true;
-	
-	private ClanHall _clanHall;
+	private int _level = 0;
+	int _closeTime = -1;
+	int _openTime = -1;
+	int _randomTime = -1;
+	// used for autoclose on open
+	private Future<?> _autoCloseTask;
 	
-	protected int _autoActionDelay = -1;
-	private ScheduledFuture<?> _autoActionTask;
+	/**
+	 * @param objectId
+	 * @param template
+	 * @param data
+	 */
+	public L2DoorInstance(int objectId, L2DoorTemplate template, StatsSet data)
+	{
+		super(objectId, template);
+		setInstanceType(InstanceType.L2DoorInstance);
+		setIsInvul(false);
+		_isTargetable = data.getBool("targetable", true);
+		if (getGroupName() != null)
+			DoorTable.addDoorGroup(getGroupName(), getDoorId());
+		if (data.getString("default_status","close").equals("open"))
+			_open = true;
+		_closeTime = data.getInteger("close_time", -1);
+		_level = data.getInteger("level", 0);
+		_openType = data.getInteger("open_method", 0);
+		_checkCollision = data.getBool("check_collision", true);
+		if (isOpenableByTime())
+		{
+			_closeTime = data.getInteger("open_time");
+			_randomTime = data.getInteger("random_time", -1);
+			startTimerOpen();
+		}
+		int clanhallId = data.getInteger("clanhall_id", 0);
+		if(clanhallId > 0)
+		{
+			ClanHall hall = ClanHallManager.getAllClanHalls().get(clanhallId);
+			if(hall != null)
+			{
+				this.setClanHall(hall);
+				hall.getDoors().add(this);
+			}
+		}
+	}
 	
 	/** This class may be created only by L2Character and only for AI */
 	public class AIAccessor extends L2Character.AIAccessor
@@ -150,71 +179,13 @@ public class L2DoorInstance extends L2Character
 		}
 		return ai;
 	}
-	
-	class CloseTask implements Runnable
-	{
-		@Override
-		public void run()
-		{
-			try
-			{
-				onClose();
-			}
-			catch (Exception e)
-			{
-				_log.log(Level.SEVERE, "", e);
-			}
-		}
-	}
-	
-	/**
-	 * Manages the auto open and closing of a door.
-	 */
-	class AutoOpenClose implements Runnable
-	{
-		@Override
-		public void run()
-		{
-			try
-			{
-				String doorAction;
-				
-				if (!getOpen())
-				{
-					doorAction = "opened";
-					openMe();
-				}
-				else
-				{
-					doorAction = "closed";
-					closeMe();
-				}
-				
-				if (Config.DEBUG)
-					_log.info("Auto " + doorAction + " door ID " + _doorId + " (" + _name + ") for " + (_autoActionDelay / 60000) + " minute(s).");
-			}
-			catch (Exception e)
-			{
-				_log.warning("Could not auto open/close door ID " + _doorId + " (" + _name + ")");
-			}
-		}
-	}
-	
-	/**
-	 * @param objectId 
-	 * @param template 
-	 * @param doorId 
-	 * @param name 
-	 * @param unlockable 
-	 */
-	public L2DoorInstance(int objectId, L2CharTemplate template, int doorId, String name, boolean unlockable)
+
+	private void startTimerOpen()
 	{
-		super(objectId, template);
-		setInstanceType(InstanceType.L2DoorInstance);
-		setIsInvul(false);
-		_doorId = doorId;
-		_name = name;
-		_unlockable = unlockable;
+		int delay = _open ? _openTime : _closeTime;
+		if (_randomTime > 0)
+			delay += Rnd.get(_randomTime);
+		ThreadPoolManager.getInstance().scheduleGeneral(new TimerOpen(), delay*1000);
 	}
 	
 	@Override
@@ -234,6 +205,13 @@ public class L2DoorInstance extends L2Character
 	{
 		return (DoorStat) super.getStat();
 	}
+
+	@Override
+	public L2DoorTemplate getTemplate()
+	{
+		return (L2DoorTemplate) super.getTemplate();
+		
+	}
 	
 	@Override
 	public void initCharStat()
@@ -252,16 +230,36 @@ public class L2DoorInstance extends L2Character
 	{
 		setStatus(new DoorStatus(this));
 	}
+
+	public final boolean isOpenableBySkill()
+	{
+		return (_openType & OPEN_BY_SKILL) != 0;
+	}
 	
-	public final boolean isUnlockable()
+	public final boolean isOpenableByItem()
 	{
-		return _unlockable;
+		return (_openType & OPEN_BY_ITEM) != 0;
+	}
+	
+	public final boolean isOpenableByClick()
+	{
+		return (_openType & OPEN_BY_CLICK) != 0;
+	}
+	
+	public final boolean isOpenableByTime()
+	{
+		return (_openType & OPEN_BY_TIME) != 0;
+	}
+	
+	public final boolean isOpenableByCycle()
+	{
+		return (_openType & OPEN_BY_CYCLE) != 0;
 	}
 	
 	@Override
 	public final int getLevel()
 	{
-		return 1;
+		return _level;
 	}
 	
 	/**
@@ -269,7 +267,7 @@ public class L2DoorInstance extends L2Character
 	 */
 	public int getDoorId()
 	{
-		return _doorId;
+		return getTemplate().doorId;
 	}
 	
 	/**
@@ -279,30 +277,17 @@ public class L2DoorInstance extends L2Character
 	{
 		return _open;
 	}
-	
+
 	/**
 	 * @param open The open to set.
 	 */
 	public void setOpen(boolean open)
 	{
 		_open = open;
-	}
-	
-	/**
-	 * @param val Used for Fortresses to determine if doors can be attacked during siege or not
-	 */
-	public void setIsCommanderDoor(boolean val)
-	{
-		_isCommanderDoor = val;
-	}
-	
-	/**
-	 * @return Doors that cannot be attacked during siege
-	 * these doors will be auto opened if u take control of all commanders buildings
-	 */
-	public boolean getIsCommanderDoor()
-	{
-		return _isCommanderDoor;
+		if (getChildId() > 0)
+		{
+			getSiblingDoor(getChildId()).notifyChildEvent(open);
+		}
 	}
 	
 	public boolean getIsAttackableDoor()
@@ -312,7 +297,7 @@ public class L2DoorInstance extends L2Character
 	
 	public boolean getIsShowHp()
 	{
-		return _ShowHp;
+		return getTemplate().showHp;
 	}
 	
 	public void setIsAttackableDoor(boolean val)
@@ -320,38 +305,6 @@ public class L2DoorInstance extends L2Character
 		_isAttackableDoor = val;
 	}
 	
-	public void setIsShowHp(boolean val)
-	{
-		_ShowHp = val;
-	}
-	
-	/**
-	 * Sets the delay in milliseconds for automatic opening/closing
-	 * of this door instance.
-	 * <BR>
-	 * <B>Note:</B> A value of -1 cancels the auto open/close task.
-	 *
-	 * @param actionDelay
-	 */
-	public void setAutoActionDelay(int actionDelay)
-	{
-		if (_autoActionDelay == actionDelay)
-			return;
-		
-		if (actionDelay > -1)
-		{
-			AutoOpenClose ao = new AutoOpenClose();
-			ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(ao, actionDelay, actionDelay);
-		}
-		else
-		{
-			if (_autoActionTask != null)
-				_autoActionTask.cancel(false);
-		}
-		
-		_autoActionDelay = actionDelay;
-	}
-	
 	public int getDamage()
 	{
 		int dmg = 6 - (int) Math.ceil(getCurrentHp() / getMaxHp() * 6);
@@ -392,11 +345,11 @@ public class L2DoorInstance extends L2Character
 	
 	public boolean isEnemy()
 	{
-		if (getCastle() != null && getCastle().getCastleId() > 0 && getCastle().getZone().isActive())
+		if (getCastle() != null && getCastle().getCastleId() > 0 && getCastle().getZone().isActive() && getIsShowHp())
 			return true;
-		if (getFort() != null && getFort().getFortId() > 0 && getFort().getZone().isActive() && !getIsCommanderDoor())
+		if (getFort() != null && getFort().getFortId() > 0 && getFort().getZone().isActive() && getIsShowHp())
 			return true;
-		if(getClanHall() != null && getClanHall().isSiegableHall() && ((SiegableHall)getClanHall()).getSiegeZone().isActive())
+		if(getClanHall() != null && getClanHall().isSiegableHall() && ((SiegableHall)getClanHall()).getSiegeZone().isActive() && getIsShowHp())
 			return true;
 		return false;
 	}
@@ -404,12 +357,14 @@ public class L2DoorInstance extends L2Character
 	@Override
 	public boolean isAutoAttackable(L2Character attacker)
 	{
-		if (isUnlockable() && getFort() == null)
-			return true;
-		
 		// Doors can`t be attacked by NPCs
 		if (!(attacker instanceof L2Playable))
 			return false;
+
+		if (getIsAttackableDoor())
+			return true;
+		if (!getIsShowHp())
+			return false;
 		
 		L2PcInstance actingPlayer = attacker.getActingPlayer();
 		
@@ -423,7 +378,7 @@ public class L2DoorInstance extends L2Character
 		}
 		// Attackable  only during siege by everyone (not owner)
 		boolean isCastle = (getCastle() != null && getCastle().getCastleId() > 0 && getCastle().getZone().isActive());
-		boolean isFort = (getFort() != null && getFort().getFortId() > 0 && getFort().getZone().isActive() && !getIsCommanderDoor());
+		boolean isFort = (getFort() != null && getFort().getFortId() > 0 && getFort().getZone().isActive());
 		int activeSiegeId = (getFort() != null ? getFort().getFortId() : (getCastle() != null ? getCastle().getCastleId() : 0));
 		
 		if (TerritoryWarManager.getInstance().isTWInProgress())
@@ -444,7 +399,7 @@ public class L2DoorInstance extends L2Character
 			if (clan != null && clan.getClanId() == getCastle().getOwnerId())
 				return false;
 		}
-		return (isCastle || isFort || getIsAttackableDoor());
+		return (isCastle || isFort);
 	}
 	
 	public boolean isAttackable(L2Character attacker)
@@ -457,28 +412,6 @@ public class L2DoorInstance extends L2Character
 	{
 	}
 	
-	public int getDistanceToWatchObject(L2Object object)
-	{
-		if (!(object instanceof L2PcInstance))
-			return 0;
-		return 3000;
-	}
-	
-	/**
-	 * <B><U> Values </U> :</B><BR><BR>
-	 * <li> object is a L2PcInstance : 4000</li>
-	 * <li> object is not a L2PcInstance : 0 </li><BR><BR>
-	 * @param object 
-	 * @return the distance after which the object must be remove from _knownObject according to the type of the object.
-	 */
-	public int getDistanceToForgetObject(L2Object object)
-	{
-		if (!(object instanceof L2PcInstance))
-			return 0;
-		
-		return 4000;
-	}
-	
 	/**
 	 * Return null.<BR><BR>
 	 */
@@ -516,15 +449,18 @@ public class L2DoorInstance extends L2Character
 		StaticObject su = new StaticObject(this, false);
 		DoorStatusUpdate dsu = new DoorStatusUpdate(this);
 		OnEventTrigger oe = null;
-		if (_emitter > 0)
+		if (getEmitter() > 0)
 			oe = new OnEventTrigger(this, getOpen());
 
 		for (L2PcInstance player : knownPlayers)
 		{
 			if (player == null)
 				continue;
+
+			if (player.isGM())
+				su = new StaticObject(this, true);
 			
-			if ((getCastle() != null && getCastle().getCastleId() > 0) || (getFort() != null && getFort().getFortId() > 0 && !getIsCommanderDoor()))
+			if ((getCastle() != null && getCastle().getCastleId() > 0) || (getFort() != null && getFort().getFortId() > 0))
 				su = new StaticObject(this, true);
 			
 			player.sendPacket(su);
@@ -533,94 +469,102 @@ public class L2DoorInstance extends L2Character
 				player.sendPacket(oe);
 		}
 	}
-	
-	public void onOpen()
-	{
-		ThreadPoolManager.getInstance().scheduleGeneral(new CloseTask(), 60000);
-	}
-	
-	public void onClose()
+
+	public final void openMe()
 	{
-		closeMe();
+		if (getGroupName() != null)
+		{
+			manageGroupOpen(true, getGroupName());
+			return;
+		}
+		setOpen(true);
+		broadcastStatusUpdate();
+		startAutoCloseTask();
 	}
-	
+
 	public final void closeMe()
 	{
+		//remove close task
+		Future<?> oldTask = _autoCloseTask;
+		if (oldTask != null)
+		{
+			_autoCloseTask = null;
+			oldTask.cancel(false);
+		}
+		if (getGroupName() != null)
+		{
+			manageGroupOpen(false, getGroupName());
+			return;
+		}
 		setOpen(false);
 		broadcastStatusUpdate();
 	}
-	
-	public final void openMe()
+
+	private void manageGroupOpen(boolean open, String groupName)
 	{
-		setOpen(true);
-		broadcastStatusUpdate();
+		Set<Integer> set = DoorTable.getDoorsByGroup(groupName);
+		L2DoorInstance first = null;
+		for (Integer id : set)
+		{
+			L2DoorInstance door = getSiblingDoor(id);
+			if (first == null)
+				first = door;
+			
+			if (door.getOpen() != open)
+			{
+				door.setOpen(open);
+				door.broadcastStatusUpdate();
+			}
+		}
+		if (first != null && open)
+			first.startAutoCloseTask(); //only one from group
 	}
 	
+	/**
+	 * Door notify child about open state change
+	 * @param open true if opened
+	 */
+	private void notifyChildEvent(boolean open)
+	{
+		byte openThis = open ? getTemplate().masterDoorOpen : getTemplate().masterDoorClose;
+		
+		if (openThis == 0)
+			return;
+		else if (openThis == 1)
+			openMe();
+		else if (openThis == -1)
+			closeMe();
+	}
+
 	@Override
 	public String toString()
 	{
-		return "door " + _doorId;
+		return getClass().getSimpleName() +"["+ getTemplate().doorId + "]("+getObjectId()+")";
 	}
 	
 	public String getDoorName()
 	{
-		return _name;
+		return getTemplate().name;
 	}
 	
-	public int getXMin()
+	public int getX(int i)
 	{
-		return _rangeXMin;
+		return getTemplate().nodeX[i];
 	}
 	
-	public int getYMin()
+	public int getY(int i)
 	{
-		return _rangeYMin;
+		return getTemplate().nodeY[i];
 	}
 	
 	public int getZMin()
 	{
-		return _rangeZMin;
-	}
-	
-	public int getXMax()
-	{
-		return _rangeXMax;
-	}
-	
-	public int getYMax()
-	{
-		return _rangeYMax;
+		return getTemplate().nodeZ;
 	}
 	
 	public int getZMax()
 	{
-		return _rangeZMax;
-	}
-	
-	public void setRange(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax)
-	{
-		_rangeXMin = xMin;
-		_rangeYMin = yMin;
-		_rangeZMin = zMin;
-		
-		_rangeXMax = xMax;
-		_rangeYMax = yMax;
-		_rangeZMax = zMax;
-		
-		_A = _rangeYMax * (_rangeZMax - _rangeZMin) + _rangeYMin * (_rangeZMin - _rangeZMax);
-		_B = _rangeZMin * (_rangeXMax - _rangeXMin) + _rangeZMax * (_rangeXMin - _rangeXMax);
-		_C = _rangeXMin * (_rangeYMax - _rangeYMin) + _rangeXMin * (_rangeYMin - _rangeYMax);
-		_D = -1 * (_rangeXMin * (_rangeYMax * _rangeZMax - _rangeYMin * _rangeZMax) + _rangeXMax * (_rangeYMin * _rangeZMin - _rangeYMin * _rangeZMax) + _rangeXMin * (_rangeYMin * _rangeZMax - _rangeYMax * _rangeZMin));
-	}
-	
-	public int getMapRegion()
-	{
-		return _mapRegion;
-	}
-	
-	public void setMapRegion(int region)
-	{
-		_mapRegion = region;
+		return getTemplate().nodeZ + getTemplate().height;
 	}
 	
 	public Collection<L2DefenderInstance> getKnownDefenders()
@@ -636,44 +580,7 @@ public class L2DoorInstance extends L2Character
 	
 		return result;
 	}
-	
-	public int getA()
-	{
-		return _A;
-	}
-	
-	public int getB()
-	{
-		return _B;
-	}
-	
-	public int getC()
-	{
-		return _C;
-	}
-	
-	public int getD()
-	{
-		return _D;
-	}
-	
-	/**
-	 * Set this door as a castle wall, can be damaged by siege golem only.
-	 * @param b 
-	 */
-	public void setIsWall(boolean b)
-	{
-		_isWall = b;
-	}
-	
-	/**
-	 * @return true if door is a castle wall and can be damaged by siege golem only.
-	 */
-	public boolean isWall()
-	{
-		return _isWall;
-	}
-	
+
 	public void setMeshIndex(int mesh)
 	{
 		_meshindex = mesh;
@@ -684,30 +591,30 @@ public class L2DoorInstance extends L2Character
 		return _meshindex;
 	}
 	
-	public void setEmitter(int emitter)
+	public int getEmitter()
 	{
-		_emitter = emitter;
+		return getTemplate().emmiter;
 	}
-	
-	public int getEmitter()
+
+	public boolean isWall()
 	{
-		return _emitter;
+		return getTemplate().isWall;
 	}
 	
-	public void setTargetable(boolean targetable)
+	public String getGroupName()
 	{
-		_targetable = targetable;
+		return getTemplate().groupName;
 	}
 	
-	public boolean getTargetable()
+	public int getChildId()
 	{
-		return _targetable;
+		return getTemplate().childDoorId;
 	}
 	
 	@Override
 	public void reduceCurrentHp(double damage, L2Character attacker, boolean awake, boolean isDOT, L2Skill skill)
 	{
-		if (_isWall && !(attacker instanceof L2SiegeSummonInstance))
+		if (isWall() && !(attacker instanceof L2SiegeSummonInstance))
 			return;
 		
 		super.reduceCurrentHp(damage, attacker, awake, isDOT, skill);
@@ -725,7 +632,7 @@ public class L2DoorInstance extends L2Character
 		if (!super.doDie(killer))
 			return false;
 		
-		boolean isFort = (getFort() != null && getFort().getFortId() > 0 && getFort().getSiege().getIsInProgress()) && !getIsCommanderDoor();
+		boolean isFort = (getFort() != null && getFort().getFortId() > 0 && getFort().getSiege().getIsInProgress());
 		boolean isCastle = (getCastle() != null	&& getCastle().getCastleId() > 0 && getCastle().getSiege().getIsInProgress());
 		boolean isHall = (getClanHall() != null && getClanHall().isSiegableHall() && ((SiegableHall)getClanHall()).isInSiege());
 		
@@ -737,10 +644,86 @@ public class L2DoorInstance extends L2Character
 	@Override
 	public void sendInfo(L2PcInstance activeChar)
 	{
-		if (_emitter > 0)
+		if (getEmitter() > 0)
 			activeChar.sendPacket(new OnEventTrigger(this, getOpen()));
 		
-		activeChar.sendPacket(new StaticObject(this, false));
+		activeChar.sendPacket(new StaticObject(this, activeChar.isGM()));
+	}
+
+	public void setTargetable(boolean b)
+	{
+		_isTargetable = b;
+		broadcastStatusUpdate();
+	}
+	
+	@Override
+	public boolean isTargetable()
+	{
+		return _isTargetable;
+	}
+	
+	public boolean checkCollision()
+	{
+		return _checkCollision;
+	}
+	
+	/**
+	 * All doors are stored at DoorTable except instance doors
+	 * @param doorId
+	 * @return
+	 */
+	private L2DoorInstance getSiblingDoor(int doorId)
+	{
+		if (getInstanceId() == 0)
+			return DoorTable.getInstance().getDoor(doorId);
+
+		Instance inst = InstanceManager.getInstance().getInstance(getInstanceId());
+		if (inst != null)
+			return inst.getDoor(doorId);
+
+		return null; // 2 late
+	}
+	
+	private void startAutoCloseTask()
+	{
+		if (_closeTime < 0 || isOpenableByTime())
+			return;
+		Future<?> oldTask = _autoCloseTask;
+		if (oldTask != null)
+		{
+			_autoCloseTask = null;
+			oldTask.cancel(false);
+		}
+		_autoCloseTask = ThreadPoolManager.getInstance().scheduleGeneral(new AutoClose(), _closeTime * 1000);
+	}
+	
+	class AutoClose implements Runnable
+	{
+		@Override
+		public void run()
+		{
+			if (getOpen())
+				closeMe();
+		}
+	}
+	
+	class TimerOpen implements Runnable
+	{
+		@Override
+		public void run()
+		{
+			boolean open = getOpen();
+			if (open)
+				closeMe();
+			else
+				openMe();
+			
+			//_log.info("Door "+L2DoorInstance.this+ " switched state "+open);
+			int delay = open ? _closeTime : _openTime;
+			if (_randomTime > 0)
+				delay += Rnd.get(_randomTime);
+			ThreadPoolManager.getInstance().scheduleGeneral(this, delay*1000);
+		}
 	}
 	
 	@Override

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java

@@ -9172,8 +9172,8 @@ public final class L2PcInstance extends L2Playable
 			boolean isFort = (((L2DoorInstance) target).getFort() != null
 					&& ((L2DoorInstance) target).getFort().getFortId() > 0
 					&& ((L2DoorInstance) target).getFort().getSiege().getIsInProgress()
-					&& !((L2DoorInstance) target).getIsCommanderDoor());
-			if ((!isCastle && !isFort)&&(((L2DoorInstance) target).isUnlockable() && skill.getSkillType() != L2SkillType.UNLOCK))
+					&& !((L2DoorInstance) target).getIsShowHp());
+			if ((!isCastle && !isFort)&&(((L2DoorInstance) target).isOpenableBySkill() && skill.getSkillType() != L2SkillType.UNLOCK))
 				return false;
 		}
 		

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/knownlist/DoorKnownList.java

@@ -45,6 +45,6 @@ public class DoorKnownList extends CharKnownList
 		if (object instanceof L2DefenderInstance) return 600;
 		if (!(object instanceof L2PcInstance))
 			return 0;
-		return 3000;
+		return 3500;
 	}
 }

+ 96 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/templates/L2DoorTemplate.java

@@ -0,0 +1,96 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.model.actor.templates;
+
+import com.l2jserver.gameserver.model.StatsSet;
+
+/**
+ * @author JIV
+ *
+ */
+public class L2DoorTemplate extends L2CharTemplate
+{
+	public final int doorId;
+	public final int nodeX[];
+	public final int nodeY[];
+	public final int nodeZ;
+	public final int height;
+	public final int posX;
+	public final int posY;
+	public final int posZ;
+	public final int emmiter;
+	public final int childDoorId;
+	public final String name;
+	public final String groupName;
+	public final boolean showHp;
+	public final boolean isWall;
+	// -1 close,  0 nothing, 1 open
+	public final byte masterDoorClose;
+	public final byte masterDoorOpen;
+	
+	public L2DoorTemplate(StatsSet set)
+	{
+		super(set);
+		
+		//stats
+		doorId = set.getInteger("id");
+		name = set.getString("name");
+
+		//position
+		String[] pos = set.getString("pos").split(";");
+		posX = Integer.parseInt(pos[0]);
+		posY = Integer.parseInt(pos[1]);
+		posZ = Integer.parseInt(pos[2]);
+		height = set.getInteger("height");
+		
+		// TODO: move to geodata system by creating door zones and load there
+		nodeZ = set.getInteger("nodeZ");
+		nodeX = new int[4]; // 4 * x
+		nodeY = new int[4]; // 4 * y
+		for (int i = 0; i < 4; i++)
+		{
+			String split[] = set.getString("node"+(i+1)).split(",");
+			nodeX[i] = Integer.parseInt(split[0]);
+			nodeY[i] = Integer.parseInt(split[1]);
+		}
+		
+		//optional
+		emmiter = set.getInteger("emitter_id", 0);
+		showHp = set.getBool("hp_showable", true);
+		isWall = set.getBool("is_wall", false);
+		groupName = set.getString("group", null);
+		
+		childDoorId = set.getInteger("child_id_event", -1);
+		// true if door is opening
+		String masterevent = set.getString("master_close_event", "act_nothing");
+		if (masterevent.equals("act_open"))
+			masterDoorClose = 1;
+		else if (masterevent.equals("act_close"))
+			masterDoorClose = -1;
+		else
+			masterDoorClose = 0;
+		//#2
+		masterevent = set.getString("master_open_event", "act_nothing");
+		if (masterevent.equals("act_open"))
+			masterDoorOpen = 1;
+		else if (masterevent.equals("act_close"))
+			masterDoorOpen = -1;
+		else
+			masterDoorOpen = 0;
+		
+		
+	}
+	
+}

+ 30 - 46
L2J_Server_BETA/java/com/l2jserver/gameserver/model/entity/Castle.java

@@ -79,7 +79,6 @@ public class Castle
 	
 	private int _castleId = 0;
 	private List<L2DoorInstance> _doors = new ArrayList<>();
-	private List<String> _doorDefault = new ArrayList<>();
 	private String _name = "";
 	private int _ownerId = 0;
 	private Siege _siege = null;
@@ -256,7 +255,6 @@ public class Castle
 		 * if (_castleId == 7 || castleId == 9) // Goddard and Schuttgart _nbArtifact = 2;
 		 */
 		load();
-		loadDoor();
 		_function = new FastMap<Integer, CastleFunction>();
 		final List<L2SkillLearn> residentialSkills = SkillTreesData.getInstance().getAvailableResidentialSkills(castleId);
 		for (L2SkillLearn s : residentialSkills)
@@ -669,20 +667,18 @@ public class Castle
 	 */
 	public void spawnDoor(boolean isDoorWeak)
 	{
-		for (int i = 0; i < getDoors().size(); i++)
+		for (L2DoorInstance door : _doors)
 		{
-			L2DoorInstance door = getDoors().get(i);
-			if (door.getCurrentHp() <= 0)
+			if (door.isDead())
 			{
-				door.decayMe(); // Kill current if not killed already
-				door = DoorTable.parseList(_doorDefault.get(i), false);
-				DoorTable.getInstance().putDoor(door); // Readd the new door to the DoorTable By Erb
+				door.doRevive();
 				if (isDoorWeak)
 					door.setCurrentHp(door.getMaxHp() / 2);
-				door.spawnMe(door.getX(), door.getY(), door.getZ());
-				getDoors().set(i, door);
+				else
+					door.setCurrentHp(door.getMaxHp());
 			}
-			else if (door.getOpen())
+			
+			if (door.getOpen())
 				door.closeMe();
 		}
 		loadDoorUpgrade(); // Check for any upgrade the doors may have
@@ -855,47 +851,23 @@ public class Castle
 		}
 		return true;
 	}
-	
+
 	public void activateInstance()
 	{
-		for (final L2DoorInstance door : _doors)
-		{
-			door.spawnMe(door.getX(), door.getY(), door.getZ());
-		}
+		loadDoor();
 	}
 	
 	// This method loads castle door data from database
 	private void loadDoor()
 	{
-		Connection con = null;
-		try
+		for (L2DoorInstance door : DoorTable.getInstance().getDoors())
 		{
-			con = L2DatabaseFactory.getInstance().getConnection();
-			PreparedStatement statement = con.prepareStatement("Select * from castle_door where castleId = ?");
-			statement.setInt(1, getCastleId());
-			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") + ";0");
-				
-				L2DoorInstance door = DoorTable.parseList(_doorDefault.get(_doorDefault.size() - 1), false);
-				door.setIsWall(rs.getBoolean("isWall"));
+			if (door.getCastle() != null && door.getCastle().getCastleId() == getCastleId())
 				_doors.add(door);
-				DoorTable.getInstance().putDoor(door);
-			}
-			rs.close();
-			statement.close();
-		}
-		catch (Exception e)
-		{
-			_log.log(Level.WARNING, "Exception: loadCastleDoor(): " + e.getMessage(), e);
-		}
-		finally
-		{
-			L2DatabaseFactory.close(con);
 		}
+		
+		if (Config.DEBUG)
+			_log.info("Castle "+this+" loaded "+_doors.size()+" doors.");
 	}
 	
 	// This method loads castle door upgrade data from database
@@ -904,9 +876,12 @@ public class Castle
 		Connection con = null;
 		try
 		{
+			StringBuilder doorIds = new StringBuilder(100);
+			for (L2DoorInstance door : getDoors())
+				doorIds.append(door.getDoorId()).append(",");
+			doorIds.deleteCharAt(doorIds.length()-1);
 			con = L2DatabaseFactory.getInstance().getConnection();
-			PreparedStatement statement = con.prepareStatement("SELECT * FROM castle_doorupgrade WHERE doorId IN (SELECT Id FROM castle_door WHERE castleId = ?)");
-			statement.setInt(1, getCastleId());
+			PreparedStatement statement = con.prepareStatement("Select * from castle_doorupgrade where doorId in ("+doorIds.toString()+")");
 			ResultSet rs = statement.executeQuery();
 			
 			while (rs.next())
@@ -931,9 +906,12 @@ public class Castle
 		Connection con = null;
 		try
 		{
+			StringBuilder doorIds = new StringBuilder(100);
+			for (L2DoorInstance door : getDoors())
+				doorIds.append(door.getDoorId()).append(",");
+			doorIds.deleteCharAt(doorIds.length()-1);
 			con = L2DatabaseFactory.getInstance().getConnection();
-			PreparedStatement statement = con.prepareStatement("delete from castle_doorupgrade where doorId in (select id from castle_door where castleId=?)");
-			statement.setInt(1, getCastleId());
+			PreparedStatement statement = con.prepareStatement("delete from castle_doorupgrade where doorId in ("+doorIds.toString()+")");
 			statement.execute();
 			statement.close();
 		}
@@ -1659,4 +1637,10 @@ public class Castle
 			L2DatabaseFactory.close(con);
 		}
 	}
+	
+	@Override
+	public String toString()
+	{
+		return _name+"("+_castleId+")";
+	}
 }

+ 4 - 5
L2J_Server_BETA/java/com/l2jserver/gameserver/model/entity/ClanHall.java

@@ -17,12 +17,11 @@ package com.l2jserver.gameserver.model.entity;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
-import java.util.List;
+import java.util.ArrayList;
 import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import javolution.util.FastList;
 import javolution.util.FastMap;
 
 import com.l2jserver.Config;
@@ -42,7 +41,7 @@ public abstract class ClanHall
 	protected static final Logger _log = Logger.getLogger(ClanHall.class.getName());
 	
 	private int _clanHallId;
-	private List<L2DoorInstance> _doors;
+	private ArrayList<L2DoorInstance> _doors;
 	private String _name;
 	private int _ownerId;
 	private String _desc;
@@ -269,10 +268,10 @@ public abstract class ClanHall
 	/**
 	 * @return all DoorInstance
 	 */
-	public final List<L2DoorInstance> getDoors()
+	public final ArrayList<L2DoorInstance> getDoors()
 	{
 		if (_doors == null)
-			_doors = new FastList<L2DoorInstance>();
+			_doors = new ArrayList<L2DoorInstance>();
 		return _doors;
 	}
 	

+ 12 - 45
L2J_Server_BETA/java/com/l2jserver/gameserver/model/entity/Fort.java

@@ -20,6 +20,7 @@ import gnu.trove.procedure.TObjectProcedure;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
+import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.List;
 import java.util.concurrent.ScheduledFuture;
@@ -67,9 +68,8 @@ public class Fort
 	protected static final Logger _log = Logger.getLogger(Fort.class.getName());
 	
 	private int _fortId = 0;
-	private List<L2DoorInstance> _doors = new FastList<L2DoorInstance>();
+	private List<L2DoorInstance> _doors = new ArrayList<L2DoorInstance>();
 	private L2StaticObjectInstance _flagPole = null;
-	private List<String> _doorDefault = new FastList<String>();
 	private String _name = "";
 	private FortSiege _siege = null;
 	private Calendar _siegeDate;
@@ -246,7 +246,6 @@ public class Fort
 	{
 		_fortId = fortId;
 		load();
-		loadDoor();
 		loadFlagPoles();
 		_function = new FastMap<Integer, FortFunction>();
 		final List<L2SkillLearn> residentialSkills = SkillTreesData.getInstance().getAvailableResidentialSkills(fortId);
@@ -579,12 +578,11 @@ public class Fort
 	 */
 	public void resetDoors()
 	{
-		for (int i = 0; i < getDoors().size(); i++)
+		for (L2DoorInstance door : _doors)
 		{
-			L2DoorInstance door = getDoors().get(i);
 			if (door.getOpen())
 				door.closeMe();
-			if (door.getCurrentHp() <= 0)
+			if (door.isDead())
 				door.doRevive();
 			if (door.getCurrentHp() < door.getMaxHp())
 				door.setCurrentHp(door.getMaxHp());
@@ -777,48 +775,19 @@ public class Fort
 	
 	public void activateInstance()
 	{
-		for (final L2DoorInstance door : _doors)
-		{
-			door.spawnMe(door.getX(), door.getY(), door.getZ());
-		}
+		loadDoor();
 	}
 	
 	// This method loads fort door data from database
 	private void loadDoor()
 	{
-		Connection con = null;
-		try
+		for (L2DoorInstance door : DoorTable.getInstance().getDoors())
 		{
-			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") + ";0;" + 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);
+			if (door.getFort() != null && door.getFort().getFortId() == getFortId())
+				_doors.add(door);
 		}
+		if (Config.DEBUG)
+			_log.info("Fort "+this+" loaded "+_doors.size()+" doors.");
 	}
 	
 	private void loadFlagPoles()
@@ -844,9 +813,8 @@ public class Fort
 		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 = ?)");
+			PreparedStatement statement = con.prepareStatement("SELECT * FROM fort_doorupgrade WHERE fortId = ?");
 			statement.setInt(1, getFortId());
-			statement.setInt(2, 0);
 			ResultSet rs = statement.executeQuery();
 			
 			while (rs.next())
@@ -872,9 +840,8 @@ public class Fort
 		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 = ?)");
+			PreparedStatement statement = con.prepareStatement("DELETE FROM fort_doorupgrade WHERE WHERE fortId = ?");
 			statement.setInt(1, getFortId());
-			statement.setInt(2, 0);
 			statement.execute();
 			statement.close();
 		}

+ 2 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/model/entity/FortSiege.java

@@ -628,9 +628,10 @@ public class FortSiege implements Siegable
 					// open doors in main building
 					for (L2DoorInstance door : getFort().getDoors())
 					{
-						if (!door.getIsCommanderDoor())
+						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));

+ 22 - 25
L2J_Server_BETA/java/com/l2jserver/gameserver/model/entity/Instance.java

@@ -15,6 +15,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
 import javolution.util.FastList;
 
 import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 
 import com.l2jserver.Config;
@@ -28,10 +29,12 @@ import com.l2jserver.gameserver.instancemanager.MapRegionManager;
 import com.l2jserver.gameserver.model.L2Spawn;
 import com.l2jserver.gameserver.model.L2World;
 import com.l2jserver.gameserver.model.L2WorldRegion;
+import com.l2jserver.gameserver.model.StatsSet;
 import com.l2jserver.gameserver.model.actor.L2Attackable;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.actor.templates.L2DoorTemplate;
 import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.clientpackets.Say2;
@@ -223,10 +226,10 @@ public class Instance
 	
 	/**
 	 * Adds a door into the instance
-	 * @param doorId - from doors.csv
-	 * @param open - initial state of the door
+	 * @param doorId - from doorData.xml
+	 * @param set - statset for initializing door
 	 */
-	private void addDoor(int doorId, boolean open)
+	private void addDoor(int doorId, StatsSet set)
 	{
 		if (_doors == null)
 			_doors = new ArrayList<L2DoorInstance>(2);
@@ -240,25 +243,11 @@ public class Instance
 			}
 		}
 		
-		L2DoorInstance temp = DoorTable.getInstance().getDoor(doorId);
-		L2DoorInstance newdoor = new L2DoorInstance(IdFactory.getInstance().getNextId(), temp.getTemplate(), temp.getDoorId(), temp.getName(), temp.isUnlockable());
+		L2DoorTemplate temp = DoorTable.getInstance().getDoorTemplate(doorId);
+		L2DoorInstance newdoor = new L2DoorInstance(IdFactory.getInstance().getNextId(), temp, set);
 		newdoor.setInstanceId(getId());
-		newdoor.setRange(temp.getXMin(), temp.getYMin(), temp.getZMin(), temp.getXMax(), temp.getYMax(), temp.getZMax());
-		try
-		{
-			newdoor.setMapRegion(MapRegionManager.getInstance().getMapRegionLocId(temp));
-		}
-		catch (Exception e)
-		{
-			_log.severe("Error in door data, ID:" + temp.getDoorId());
-		}
-		newdoor.getStatus().setCurrentHpMp(newdoor.getMaxHp(), newdoor.getMaxMp());
-		newdoor.setOpen(open);
-		newdoor.getPosition().setXYZInvisible(temp.getX(), temp.getY(), temp.getZ());
-		newdoor.spawnMe(newdoor.getX(), newdoor.getY(), newdoor.getZ());
-		newdoor.setEmitter(temp.getEmitter());
-		newdoor.setTargetable(temp.getTargetable());
-		newdoor.setMeshIndex(temp.getMeshIndex());
+		newdoor.setCurrentHp(newdoor.getMaxHp());
+		newdoor.spawnMe(temp.posX, temp.posY, temp.posZ);
 		_doors.add(newdoor);
 	}
 	
@@ -471,13 +460,21 @@ public class Instance
 				for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
 				{
 					int doorId = 0;
-					boolean doorState = false;
 					if ("door".equalsIgnoreCase(d.getNodeName()))
 					{
 						doorId = Integer.parseInt(d.getAttributes().getNamedItem("doorId").getNodeValue());
-						if (d.getAttributes().getNamedItem("open") != null)
-							doorState = Boolean.parseBoolean(d.getAttributes().getNamedItem("open").getNodeValue());
-						addDoor(doorId, doorState);
+						StatsSet set = new StatsSet();
+						for (Node bean = d.getFirstChild(); bean != null; bean = bean.getNextSibling())
+						{
+							if ("set".equalsIgnoreCase(bean.getNodeName()))
+							{
+								NamedNodeMap attrs = bean.getAttributes();
+								String setname = attrs.getNamedItem("name").getNodeValue();
+								String value = attrs.getNamedItem("val").getNodeValue();
+								set.set(setname, value);
+							}
+						}
+						addDoor(doorId, set);
 					}
 				}
 			}

+ 7 - 21
L2J_Server_BETA/java/com/l2jserver/gameserver/model/entity/clanhall/SiegableHall.java

@@ -17,13 +17,9 @@ package com.l2jserver.gameserver.model.entity.clanhall;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.util.Calendar;
-import java.util.List;
 import java.util.logging.Level;
 
-import javolution.util.FastList;
-
 import com.l2jserver.L2DatabaseFactory;
-import com.l2jserver.gameserver.datatables.DoorTable;
 import com.l2jserver.gameserver.model.L2Clan;
 import com.l2jserver.gameserver.model.L2SiegeClan;
 import com.l2jserver.gameserver.model.L2SiegeClan.SiegeClanType;
@@ -42,8 +38,6 @@ public final class SiegableHall extends ClanHall
 {	
 	private static final String SQL_SAVE = "UPDATE siegable_clanhall SET ownerId=?, nextSiege=? WHERE clanHallId=?";
 		
-	protected List<String> _doorDefault;
-	
 	private Calendar _nextSiege;
 	private long _siegeLength;
 	private int[] _scheduleConfig = {7,0,0,12,0};
@@ -56,7 +50,6 @@ public final class SiegableHall extends ClanHall
 	public SiegableHall(StatsSet set)
 	{
 		super(set);
-		_doorDefault = new FastList<String>();
 		_siegeLength = set.getLong("siegeLenght");
 		String[] rawSchConfig = set.getString("scheduleConfig").split(";");
 		if(rawSchConfig.length == 5)
@@ -83,11 +76,6 @@ public final class SiegableHall extends ClanHall
 		else
 			_nextSiege.setTimeInMillis(nextSiege);
 	}
-			
-	public List<String> getDoorDefault()
-	{
-		return _doorDefault;
-	}
 	
 	public void spawnDoor()
 	{
@@ -96,20 +84,18 @@ public final class SiegableHall extends ClanHall
 	
 	public void spawnDoor(boolean isDoorWeak)
 	{
-		for (int i = 0; i < getDoors().size(); i++)
+		for (L2DoorInstance door : this.getDoors())
 		{
-			L2DoorInstance door = getDoors().get(i);
-			if (door.getCurrentHp() <= 0)
+			if (door.isDead())
 			{
-				door.decayMe(); // Kill current if not killed already
-				door = DoorTable.parseList(_doorDefault.get(i), false);
-				DoorTable.getInstance().putDoor(door); //Readd the new door to the DoorTable By Erb
+				door.doRevive();
 				if (isDoorWeak)
 					door.setCurrentHp(door.getMaxHp() / 2);
-				door.spawnMe(door.getX(), door.getY(), door.getZ());
-				getDoors().set(i, door);
+				else
+					door.setCurrentHp(door.getMaxHp());
 			}
-			else if (door.getOpen())
+			
+			if (door.getOpen())
 				door.closeMe();
 		}
 	}

+ 3 - 3
L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/StaticObject.java

@@ -51,18 +51,18 @@ public class StaticObject extends L2GameServerPacket
 		_damageGrade = 0;
 	}
 	
-	public StaticObject(L2DoorInstance door, boolean showHp)
+	public StaticObject(L2DoorInstance door, boolean targetable)
 	{
 		_staticObjectId = door.getDoorId();
 		_objectId = door.getObjectId();
 		_type = 1;
-		_isTargetable = door.getTargetable();
+		_isTargetable = door.isTargetable() || targetable;
 		_meshIndex = door.getMeshIndex();
 		_isClosed = !door.getOpen();
 		_isEnemy = door.isEnemy();
 		_maxHp = door.getMaxVisibleHp();
 		_currentHp = (int) door.getCurrentHp();
-		_showHp = door.getIsShowHp() || showHp;
+		_showHp = door.getIsShowHp();
 		_damageGrade = door.getDamage();
 	}