diff --git a/trunk/dist/game/data/scripts/handlers/MasterHandler.java b/trunk/dist/game/data/scripts/handlers/MasterHandler.java
index 2843cc8579..30ad19e883 100644
--- a/trunk/dist/game/data/scripts/handlers/MasterHandler.java
+++ b/trunk/dist/game/data/scripts/handlers/MasterHandler.java
@@ -128,6 +128,7 @@ import handlers.admincommandhandlers.AdminTest;
import handlers.admincommandhandlers.AdminTvTEvent;
import handlers.admincommandhandlers.AdminUnblockIp;
import handlers.admincommandhandlers.AdminVitality;
+import handlers.admincommandhandlers.AdminWall;
import handlers.admincommandhandlers.AdminZone;
import handlers.bypasshandlers.AlternateClassMaster;
import handlers.bypasshandlers.ArcanCityMovie;
@@ -406,6 +407,7 @@ final class MasterHandler
AdminTvTEvent.class,
AdminUnblockIp.class,
AdminVitality.class,
+ AdminWall.class,
AdminZone.class,
},
{
diff --git a/trunk/dist/game/data/scripts/handlers/admincommandhandlers/AdminReload.java b/trunk/dist/game/data/scripts/handlers/admincommandhandlers/AdminReload.java
index 2e423aba56..29cfbdfbbe 100644
--- a/trunk/dist/game/data/scripts/handlers/admincommandhandlers/AdminReload.java
+++ b/trunk/dist/game/data/scripts/handlers/admincommandhandlers/AdminReload.java
@@ -38,6 +38,7 @@ import com.l2jmobius.gameserver.data.xml.impl.NpcData;
import com.l2jmobius.gameserver.data.xml.impl.PrimeShopData;
import com.l2jmobius.gameserver.data.xml.impl.TeleportersData;
import com.l2jmobius.gameserver.data.xml.impl.TransformData;
+import com.l2jmobius.gameserver.data.xml.impl.WallData;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.datatables.SkillData;
import com.l2jmobius.gameserver.handler.IAdminCommandHandler;
@@ -190,6 +191,12 @@ public class AdminReload implements IAdminCommandHandler
AdminData.getInstance().broadcastMessageToGMs(activeChar.getName() + ": Reloaded Doors.");
break;
}
+ case "wall":
+ {
+ WallData.getInstance().load();
+ AdminData.getInstance().broadcastMessageToGMs(activeChar.getName() + ": Reloaded Walls.");
+ break;
+ }
case "zone":
{
ZoneManager.getInstance().reload();
diff --git a/trunk/dist/game/data/scripts/handlers/admincommandhandlers/AdminWall.java b/trunk/dist/game/data/scripts/handlers/admincommandhandlers/AdminWall.java
new file mode 100644
index 0000000000..98a4ec0ef1
--- /dev/null
+++ b/trunk/dist/game/data/scripts/handlers/admincommandhandlers/AdminWall.java
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * 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 handlers.admincommandhandlers;
+
+import java.awt.Color;
+
+import com.l2jmobius.gameserver.data.xml.impl.WallData;
+import com.l2jmobius.gameserver.handler.IAdminCommandHandler;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.holders.WallHolder;
+import com.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author Mobius
+ */
+public class AdminWall implements IAdminCommandHandler
+{
+ private static final String[] ADMIN_COMMANDS =
+ {
+ "admin_showwalls"
+ };
+
+ @Override
+ public boolean useAdminCommand(String command, L2PcInstance activeChar)
+ {
+ if (activeChar == null)
+ {
+ return false;
+ }
+
+ if (command.equals("admin_showwalls"))
+ {
+ final ExServerPrimitive packet = new ExServerPrimitive("wall_info", activeChar.getX(), activeChar.getY(), -16000);
+ for (WallHolder wall : WallData.getInstance().getRegionWalls(activeChar.getX(), activeChar.getY()))
+ {
+ if ((Util.calculateDistance(activeChar.getX(), activeChar.getY(), activeChar.getZ(), wall.getPoint2X(), wall.getPoint2Y(), wall.getZMin(), false, false) < 3000) //
+ || (Util.calculateDistance(activeChar.getX(), activeChar.getY(), activeChar.getZ(), wall.getPoint1X(), wall.getPoint1Y(), wall.getZMin(), false, false) < 3000))
+ {
+ // top-bottom
+ packet.addLine(Color.GREEN, wall.getPoint1X(), wall.getPoint1Y(), wall.getZMax(), wall.getPoint2X(), wall.getPoint2Y(), wall.getZMax());
+ packet.addLine(Color.GREEN, wall.getPoint1X(), wall.getPoint1Y(), wall.getZMin(), wall.getPoint2X(), wall.getPoint2Y(), wall.getZMin());
+ // left-right
+ packet.addLine(Color.GREEN, wall.getPoint1X(), wall.getPoint1Y(), wall.getZMin(), wall.getPoint1X(), wall.getPoint1Y(), wall.getZMax());
+ packet.addLine(Color.GREEN, wall.getPoint2X(), wall.getPoint2Y(), wall.getZMin(), wall.getPoint2X(), wall.getPoint2Y(), wall.getZMax());
+ // diagonals
+ packet.addLine(Color.GREEN, wall.getPoint1X(), wall.getPoint1Y(), wall.getZMin(), wall.getPoint2X(), wall.getPoint2Y(), wall.getZMax());
+ packet.addLine(Color.GREEN, wall.getPoint1X(), wall.getPoint1Y(), wall.getZMax(), wall.getPoint2X(), wall.getPoint2Y(), wall.getZMin());
+ }
+ }
+ activeChar.sendPacket(packet);
+ }
+ return true;
+ }
+
+ @Override
+ public String[] getAdminCommandList()
+ {
+ return ADMIN_COMMANDS;
+ }
+}
diff --git a/trunk/dist/game/data/walls/giran_arena.xml b/trunk/dist/game/data/walls/giran_arena.xml
new file mode 100644
index 0000000000..0cb23bb62e
--- /dev/null
+++ b/trunk/dist/game/data/walls/giran_arena.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/trunk/dist/game/data/xsd/walls.xsd b/trunk/dist/game/data/xsd/walls.xsd
new file mode 100644
index 0000000000..a0f0f607c6
--- /dev/null
+++ b/trunk/dist/game/data/xsd/walls.xsd
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/trunk/java/com/l2jmobius/Config.java b/trunk/java/com/l2jmobius/Config.java
index 6c375aa691..eecbffdef4 100644
--- a/trunk/java/com/l2jmobius/Config.java
+++ b/trunk/java/com/l2jmobius/Config.java
@@ -502,6 +502,7 @@ public final class Config
public static int MIN_MONSTER_ANIMATION;
public static int MAX_MONSTER_ANIMATION;
public static boolean ENABLE_FALLING_DAMAGE;
+ public static boolean ENABLE_WALL_DATA;
public static boolean GRIDS_ALWAYS_ON;
public static int GRID_NEIGHBOR_TURNON_TIME;
public static int GRID_NEIGHBOR_TURNOFF_TIME;
@@ -2000,6 +2001,7 @@ public final class Config
BOTREPORT_REPORT_DELAY = General.getInt("BotReportDelay", 30) * 60000;
BOTREPORT_ALLOW_REPORTS_FROM_SAME_CLAN_MEMBERS = General.getBoolean("AllowReportsFromSameClanMembers", false);
ENABLE_FALLING_DAMAGE = General.getBoolean("EnableFallingDamage", true);
+ ENABLE_WALL_DATA = General.getBoolean("EnableWallData", true);
// Load FloodProtector L2Properties file
final PropertiesParser FloodProtectors = new PropertiesParser(FLOOD_PROTECTOR_FILE);
diff --git a/trunk/java/com/l2jmobius/gameserver/GameServer.java b/trunk/java/com/l2jmobius/gameserver/GameServer.java
index d0a179b5e5..5760883642 100644
--- a/trunk/java/com/l2jmobius/gameserver/GameServer.java
+++ b/trunk/java/com/l2jmobius/gameserver/GameServer.java
@@ -86,6 +86,7 @@ import com.l2jmobius.gameserver.data.xml.impl.StaticObjectData;
import com.l2jmobius.gameserver.data.xml.impl.TeleportersData;
import com.l2jmobius.gameserver.data.xml.impl.TransformData;
import com.l2jmobius.gameserver.data.xml.impl.UIData;
+import com.l2jmobius.gameserver.data.xml.impl.WallData;
import com.l2jmobius.gameserver.datatables.AugmentationData;
import com.l2jmobius.gameserver.datatables.BotReportTable;
import com.l2jmobius.gameserver.datatables.EventDroplist;
@@ -191,6 +192,7 @@ public final class GameServer
InstanceManager.getInstance();
L2World.getInstance();
MapRegionManager.getInstance();
+ WallData.getInstance();
AnnouncementsTable.getInstance();
GlobalVariablesManager.getInstance();
diff --git a/trunk/java/com/l2jmobius/gameserver/GeoData.java b/trunk/java/com/l2jmobius/gameserver/GeoData.java
index 21d097ded6..83becc9624 100644
--- a/trunk/java/com/l2jmobius/gameserver/GeoData.java
+++ b/trunk/java/com/l2jmobius/gameserver/GeoData.java
@@ -25,6 +25,7 @@ import com.l2jmobius.Config;
import com.l2jmobius.commons.geodriver.Cell;
import com.l2jmobius.commons.geodriver.GeoDriver;
import com.l2jmobius.gameserver.data.xml.impl.DoorData;
+import com.l2jmobius.gameserver.data.xml.impl.WallData;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.Location;
@@ -280,6 +281,10 @@ public class GeoData
{
return false;
}
+ if (WallData.getInstance().checkIfWallsBetween(x, y, z, tx, ty, tz))
+ {
+ return false;
+ }
return canSeeTarget(x, y, z, tx, ty, tz);
}
@@ -470,6 +475,10 @@ public class GeoData
{
return new Location(x, y, getHeight(x, y, z));
}
+ if (WallData.getInstance().checkIfWallsBetween(x, y, z, tx, ty, tz))
+ {
+ return new Location(x, y, getHeight(x, y, z));
+ }
final LinePointIterator pointIter = new LinePointIterator(geoX, geoY, tGeoX, tGeoY);
// first point is guaranteed to be available
@@ -532,6 +541,10 @@ public class GeoData
{
return false;
}
+ if (WallData.getInstance().checkIfWallsBetween(fromX, fromY, fromZ, toX, toY, toZ))
+ {
+ return false;
+ }
final LinePointIterator pointIter = new LinePointIterator(geoX, geoY, tGeoX, tGeoY);
// first point is guaranteed to be available
diff --git a/trunk/java/com/l2jmobius/gameserver/data/xml/impl/WallData.java b/trunk/java/com/l2jmobius/gameserver/data/xml/impl/WallData.java
new file mode 100644
index 0000000000..00dbb786de
--- /dev/null
+++ b/trunk/java/com/l2jmobius/gameserver/data/xml/impl/WallData.java
@@ -0,0 +1,167 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * 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.l2jmobius.gameserver.data.xml.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.gameserver.instancemanager.MapRegionManager;
+import com.l2jmobius.gameserver.model.holders.WallHolder;
+import com.l2jmobius.util.data.xml.IXmlReader;
+
+/**
+ * Loads Wall Data.
+ * @author Mobius
+ */
+public class WallData implements IXmlReader
+{
+ private final Map> _walls = new HashMap<>();
+
+ protected WallData()
+ {
+ if (!Config.ENABLE_WALL_DATA)
+ {
+ return;
+ }
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ _walls.clear();
+ parseDatapackDirectory("walls", false);
+ }
+
+ @Override
+ public void parseDocument(Document doc)
+ {
+ int point1X;
+ int point1Y;
+ int point2X;
+ int point2Y;
+ int minZ;
+ int maxZ;
+ int region;
+ int counter = 0;
+ for (Node a = doc.getFirstChild(); a != null; a = a.getNextSibling())
+ {
+ if ("list".equalsIgnoreCase(a.getNodeName()))
+ {
+ for (Node b = a.getFirstChild(); b != null; b = b.getNextSibling())
+ {
+ if ("wall".equalsIgnoreCase(b.getNodeName()))
+ {
+ final NamedNodeMap attrs = b.getAttributes();
+ point1X = parseInteger(attrs, "point1X");
+ point1Y = parseInteger(attrs, "point1Y");
+ point2X = parseInteger(attrs, "point2X");
+ point2Y = parseInteger(attrs, "point2Y");
+ minZ = parseInteger(attrs, "minZ");
+ maxZ = parseInteger(attrs, "maxZ");
+ region = MapRegionManager.getInstance().getMapRegionLocId(point1X, point1Y);
+ if (!_walls.containsKey(region))
+ {
+ _walls.put(region, new ArrayList());
+ }
+ _walls.get(region).add(new WallHolder(point1X, point1Y, point2X, point2Y, minZ, maxZ));
+ counter++;
+ }
+ }
+ }
+ }
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + counter + " wall data.");
+ }
+
+ /**
+ * @param x
+ * @param y
+ * @param z
+ * @param tx
+ * @param ty
+ * @param tz
+ * @return {@code boolean}
+ */
+ public boolean checkIfWallsBetween(int x, int y, int z, int tx, int ty, int tz)
+ {
+ if (!Config.ENABLE_WALL_DATA)
+ {
+ return false;
+ }
+
+ final Collection allWalls = _walls.get(MapRegionManager.getInstance().getMapRegionLocId(x, y));
+ if (allWalls == null)
+ {
+ return false;
+ }
+
+ for (WallHolder wall : allWalls)
+ {
+ boolean intersectFace = false;
+ for (int i = 0; i < 2; i++)
+ {
+ // lower part of the multiplier fraction, if it is 0 we avoid an error and also know that the lines are parallel
+ final int denominator = ((ty - y) * (wall.getPoint1X() - wall.getPoint2X())) - ((tx - x) * (wall.getPoint1Y() - wall.getPoint2Y()));
+ 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
+ final float multiplier1 = (float) (((wall.getPoint2X() - wall.getPoint1X()) * (y - wall.getPoint1Y())) - ((wall.getPoint2Y() - wall.getPoint1Y()) * (x - wall.getPoint1X()))) / denominator;
+ final float multiplier2 = (float) (((tx - x) * (y - wall.getPoint1Y())) - ((ty - y) * (x - wall.getPoint1X()))) / denominator;
+ if ((multiplier1 >= 0) && (multiplier1 <= 1) && (multiplier2 >= 0) && (multiplier2 <= 1))
+ {
+ final int intersectZ = Math.round(z + (multiplier1 * (tz - z)));
+ // now checking if the resulting point is between door's min and max z
+ if ((intersectZ > wall.getZMin()) && (intersectZ < wall.getZMax()))
+ {
+ if (intersectFace)
+ {
+ return true;
+ }
+ intersectFace = true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public List getRegionWalls(int x, int y)
+ {
+ return _walls.get(MapRegionManager.getInstance().getMapRegionLocId(x, y));
+ }
+
+ public static WallData getInstance()
+ {
+ return SingletonHolder._instance;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final WallData _instance = new WallData();
+ }
+}
diff --git a/trunk/java/com/l2jmobius/gameserver/model/holders/WallHolder.java b/trunk/java/com/l2jmobius/gameserver/model/holders/WallHolder.java
new file mode 100644
index 0000000000..7e42d198e3
--- /dev/null
+++ b/trunk/java/com/l2jmobius/gameserver/model/holders/WallHolder.java
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * 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.l2jmobius.gameserver.model.holders;
+
+/**
+ * @author Mobius
+ */
+public class WallHolder
+{
+ private final int _point1X;
+ private final int _point1Y;
+ private final int _point2X;
+ private final int _point2Y;
+ private final int _zMin;
+ private final int _zMax;
+
+ public WallHolder(int point1X, int point1Y, int point2X, int point2Y, int zMin, int zMax)
+ {
+ _point1X = point1X;
+ _point1Y = point1Y;
+ _point2X = point2X;
+ _point2Y = point2Y;
+ _zMin = zMin;
+ _zMax = zMax;
+ }
+
+ public int getPoint1X()
+ {
+ return _point1X;
+ }
+
+ public int getPoint1Y()
+ {
+ return _point1Y;
+ }
+
+ public int getPoint2X()
+ {
+ return _point2X;
+ }
+
+ public int getPoint2Y()
+ {
+ return _point2Y;
+ }
+
+ public int getZMin()
+ {
+ return _zMin;
+ }
+
+ public int getZMax()
+ {
+ return _zMax;
+ }
+}