|
@@ -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;
|