Преглед на файлове

BETA: Changes to 2D line algorithm. Added 3D line algorithm.
* 2D algorithm was changed to follow the same logic than the new 3D algorithm.
* The 3D algorithm eliminates the z multiplication in GeoData#canSeeTarget

Tested By: Sdw
Reviewed By: UnAfraid

FBIagent преди 11 години
родител
ревизия
642fad0cd7

+ 20 - 18
L2J_Server_BETA/java/com/l2jserver/gameserver/GeoData.java

@@ -35,7 +35,7 @@ import com.l2jserver.gameserver.model.Location;
 import com.l2jserver.gameserver.model.interfaces.ILocational;
 import com.l2jserver.gameserver.util.GeoUtils;
 import com.l2jserver.gameserver.util.LinePointIterator;
-import com.l2jserver.gameserver.util.Util;
+import com.l2jserver.gameserver.util.LinePointIterator3D;
 
 /**
  * @author -Nemesiss-, FBIagent
@@ -52,9 +52,9 @@ public class GeoData implements IGeoDriver
 		}
 	}
 	
-	private static final Logger _LOGGER = Logger.getLogger(GeoData.class.getName());
-	private static final int _ELEVATED_SEE_OVER_DISTANCE = 2;
-	private static final int _MAX_SEE_OVER_HEIGHT = 48;
+	private static final Logger LOGGER = Logger.getLogger(GeoData.class.getName());
+	private static final int ELEVATED_SEE_OVER_DISTANCE = 2;
+	private static final int MAX_SEE_OVER_HEIGHT = 48;
 	
 	public static GeoData getInstance()
 	{
@@ -85,7 +85,7 @@ public class GeoData implements IGeoDriver
 			}
 			catch (Exception ex)
 			{
-				_LOGGER.log(Level.SEVERE, "Failed to load geodata driver!", ex);
+				LOGGER.log(Level.SEVERE, "Failed to load geodata driver!", ex);
 				System.exit(1);
 			}
 			// we do it this way so it's predictable for the compiler
@@ -317,8 +317,6 @@ public class GeoData implements IGeoDriver
 			return true;
 		}
 		
-		double fullDist = Util.calculateDistance(geoX, geoY, 0, tGeoX, tGeoY, 0, false, false);
-		
 		if (tz > z)
 		{
 			int tmp = tx;
@@ -342,38 +340,42 @@ public class GeoData implements IGeoDriver
 			geoY = tmp;
 		}
 		
-		int fullZDiff = tz - z;
-		
-		LinePointIterator pointIter = new LinePointIterator(geoX, geoY, tGeoX, tGeoY);
+		LinePointIterator3D pointIter = new LinePointIterator3D(geoX, geoY, z, tGeoX, tGeoY, tz);
 		// first point is guaranteed to be available, skip it, we can always see our own position
 		pointIter.next();
 		int prevX = pointIter.x();
 		int prevY = pointIter.y();
-		int prevGeoZ = z;
+		int prevZ = pointIter.z();
+		int prevGeoZ = prevZ;
 		int ptIndex = 0;
 		
 		while (pointIter.next())
 		{
 			int curX = pointIter.x();
 			int curY = pointIter.y();
+			
+			if ((curX == prevX) && (curY == prevY))
+			{
+				continue;
+			}
+			
+			int beeCurZ = pointIter.z();
 			int curGeoZ = prevGeoZ;
 			
-			// check only when it's not the last point & the current position has geodata
-			if (/* ((curX != tGeoX) || (curY != tGeoY)) && */hasGeoPos(curX, curY))
+			// the current position has geodata
+			if (hasGeoPos(curX, curY))
 			{
-				double percentageDist = Util.calculateDistance(geoX, geoY, 0, curX, curY, 0, false, false) / fullDist;
-				int beeCurZ = (int) (z + (fullZDiff * percentageDist));
 				int beeCurGeoZ = getNearestZ(curX, curY, beeCurZ);
 				Direction dir = GeoUtils.computeDirection(prevX, prevY, curX, curY);
 				curGeoZ = getLosGeoZ(prevX, prevY, prevGeoZ, curX, curY, dir);
 				int maxHeight;
-				if (ptIndex < _ELEVATED_SEE_OVER_DISTANCE)
+				if (ptIndex < ELEVATED_SEE_OVER_DISTANCE)
 				{
-					maxHeight = z + _MAX_SEE_OVER_HEIGHT;
+					maxHeight = z + MAX_SEE_OVER_HEIGHT;
 				}
 				else
 				{
-					maxHeight = beeCurZ + _MAX_SEE_OVER_HEIGHT;
+					maxHeight = beeCurZ + MAX_SEE_OVER_HEIGHT;
 				}
 				
 				boolean canSeeThrough = false;

+ 60 - 37
L2J_Server_BETA/java/com/l2jserver/gameserver/util/GeoUtils.java

@@ -1,73 +1,96 @@
 /*
  * Copyright (C) 2004-2014 L2J Server
- * 
+ *
  * This file is part of L2J Server.
- * 
+ *
  * L2J Server is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
- * 
+ *
  * L2J Server is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  * General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 package com.l2jserver.gameserver.util;
 
+import java.awt.Color;
+
+import com.l2jserver.gameserver.GeoData;
 import com.l2jserver.gameserver.geoengine.Direction;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.network.serverpackets.ExServerPrimitive;
 
 /**
  * @author FBIagent
  */
 public final class GeoUtils
 {
-	public interface PointListener
+	public static void debug2DLine(L2PcInstance player, int x, int y, int tx, int ty, int z)
 	{
-		/**
-		 * @param x
-		 * @param y
-		 * @return true proceed, false abort
-		 */
-		boolean onPoint(int x, int y);
+		int gx = GeoData.getInstance().getGeoX(x);
+		int gy = GeoData.getInstance().getGeoY(y);
+		
+		int tgx = GeoData.getInstance().getGeoX(tx);
+		int tgy = GeoData.getInstance().getGeoY(ty);
+		
+		ExServerPrimitive prim = new ExServerPrimitive("Debug2DLine", x, y, z);
+		prim.addLine(Color.BLUE, GeoData.getInstance().getWorldX(gx), GeoData.getInstance().getWorldY(gy), z, GeoData.getInstance().getWorldX(tgx), GeoData.getInstance().getWorldY(tgy), z);
+		
+		LinePointIterator iter = new LinePointIterator(gx, gy, tgx, tgy);
+		
+		while (iter.next())
+		{
+			int wx = GeoData.getInstance().getWorldX(iter.x());
+			int wy = GeoData.getInstance().getWorldY(iter.y());
+			
+			prim.addPoint(Color.RED, wx, wy, z);
+		}
+		player.sendPacket(prim);
 	}
 	
-	public static boolean forEachLinePoint(int srcX, int srcY, int dstX, int dstY, PointListener listener)
+	public static void debug3DLine(L2PcInstance player, int x, int y, int z, int tx, int ty, int tz)
 	{
-		int dx = Math.abs(dstX - srcX), sx = srcX < dstX ? 1 : -1;
-		int dy = -Math.abs(dstY - srcY), sy = srcY < dstY ? 1 : -1;
-		int err = dx + dy, e2;
+		int gx = GeoData.getInstance().getGeoX(x);
+		int gy = GeoData.getInstance().getGeoY(y);
+		
+		int tgx = GeoData.getInstance().getGeoX(tx);
+		int tgy = GeoData.getInstance().getGeoY(ty);
+		
+		ExServerPrimitive prim = new ExServerPrimitive("Debug3DLine", x, y, z);
+		prim.addLine(Color.BLUE, GeoData.getInstance().getWorldX(gx), GeoData.getInstance().getWorldY(gy), z, GeoData.getInstance().getWorldX(tgx), GeoData.getInstance().getWorldY(tgy), tz);
 		
-		for (;;)
+		LinePointIterator3D iter = new LinePointIterator3D(gx, gy, z, tgx, tgy, tz);
+		iter.next();
+		int prevX = iter.x();
+		int prevY = iter.y();
+		int wx = GeoData.getInstance().getWorldX(prevX);
+		int wy = GeoData.getInstance().getWorldY(prevY);
+		int wz = iter.z();
+		prim.addPoint(Color.RED, wx, wy, wz);
+		
+		while (iter.next())
 		{
-			if (!listener.onPoint(srcX, srcY))
-			{
-				return false;
-			}
-			
-			if ((srcX == dstX) && (srcY == dstY))
-			{
-				break;
-			}
+			int curX = iter.x();
+			int curY = iter.y();
 			
-			e2 = 2 * err;
-			if (e2 > dy)
+			if ((curX != prevX) || (curY != prevY))
 			{
-				err += dy;
-				srcX += sx;
-			}
-			
-			if (e2 < dx)
-			{
-				err += dx;
-				srcY += sy;
+				wx = GeoData.getInstance().getWorldX(curX);
+				wy = GeoData.getInstance().getWorldY(curY);
+				wz = iter.z();
+				
+				prim.addPoint(Color.RED, wx, wy, wz);
+				
+				prevX = curX;
+				prevY = curY;
 			}
 		}
-		
-		return true;
+		player.sendPacket(prim);
 	}
 	
 	/**

+ 44 - 23
L2J_Server_BETA/java/com/l2jserver/gameserver/util/LinePointIterator.java

@@ -1,18 +1,18 @@
 /*
  * Copyright (C) 2004-2014 L2J Server
- * 
+ *
  * This file is part of L2J Server.
- * 
+ *
  * L2J Server is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
- * 
+ *
  * L2J Server is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  * General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
@@ -29,12 +29,11 @@ public final class LinePointIterator
 	private final int _dstX;
 	private final int _dstY;
 	
-	private final int _dx;
-	private final int _dy;
-	private final int _sx;
-	private final int _sy;
-	private int _err;
-	private int _e2;
+	private final long _dx;
+	private final long _dy;
+	private final long _sx;
+	private final long _sy;
+	private long _error;
 	
 	private boolean _first;
 	
@@ -44,13 +43,19 @@ public final class LinePointIterator
 		_srcY = srcY;
 		_dstX = dstX;
 		_dstY = dstY;
-		
-		_dx = Math.abs(dstX - srcX);
+		_dx = Math.abs((long) dstX - srcX);
+		_dy = Math.abs((long) dstY - srcY);
 		_sx = srcX < dstX ? 1 : -1;
-		_dy = -Math.abs(dstY - srcY);
 		_sy = srcY < dstY ? 1 : -1;
-		_err = _dx + _dy;
-		_e2 = 0;
+		
+		if (_dx >= _dy)
+		{
+			_error = _dx / 2;
+		}
+		else
+		{
+			_error = _dy / 2;
+		}
 		
 		_first = true;
 	}
@@ -62,21 +67,37 @@ public final class LinePointIterator
 			_first = false;
 			return true;
 		}
-		else if ((_srcX != _dstX) || (_srcY != _dstY))
+		else if (_dx >= _dy)
 		{
-			_e2 = 2 * _err;
-			if (_e2 > _dy)
+			if (_srcX != _dstX)
 			{
-				_err += _dy;
 				_srcX += _sx;
+				
+				_error += _dy;
+				if (_error >= _dx)
+				{
+					_srcY += _sy;
+					_error -= _dx;
+				}
+				
+				return true;
 			}
-			
-			if (_e2 < _dx)
+		}
+		else
+		{
+			if (_srcY != _dstY)
 			{
-				_err += _dx;
 				_srcY += _sy;
+				
+				_error += _dx;
+				if (_error >= _dy)
+				{
+					_srcX += _sx;
+					_error -= _dy;
+				}
+				
+				return true;
 			}
-			return true;
 		}
 		
 		return false;

+ 167 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/util/LinePointIterator3D.java

@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2004-2014 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.util;
+
+/**
+ * @author FBIagent
+ */
+public final class LinePointIterator3D
+{
+	private int _srcX;
+	private int _srcY;
+	private int _srcZ;
+	private final int _dstX;
+	private final int _dstY;
+	private final int _dstZ;
+	private final long _dx;
+	private final long _dy;
+	private final long _dz;
+	private final long _sx;
+	private final long _sy;
+	private final long _sz;
+	private long _error;
+	private long _error2;
+	private boolean _first;
+	
+	public LinePointIterator3D(int srcX, int srcY, int srcZ, int dstX, int dstY, int dstZ)
+	{
+		_srcX = srcX;
+		_srcY = srcY;
+		_srcZ = srcZ;
+		_dstX = dstX;
+		_dstY = dstY;
+		_dstZ = dstZ;
+		_dx = Math.abs((long) dstX - srcX);
+		_dy = Math.abs((long) dstY - srcY);
+		_dz = Math.abs((long) dstZ - srcZ);
+		_sx = srcX < dstX ? 1 : -1;
+		_sy = srcY < dstY ? 1 : -1;
+		_sz = srcZ < dstZ ? 1 : -1;
+		
+		if ((_dx >= _dy) && (_dx >= _dz))
+		{
+			_error = _error2 = _dx / 2;
+		}
+		else if ((_dy >= _dx) && (_dy >= _dz))
+		{
+			_error = _error2 = _dy / 2;
+		}
+		else
+		{
+			_error = _error2 = _dz / 2;
+		}
+		
+		_first = true;
+	}
+	
+	public boolean next()
+	{
+		if (_first)
+		{
+			_first = false;
+			return true;
+		}
+		else if ((_dx >= _dy) && (_dx >= _dz))
+		{
+			if (_srcX != _dstX)
+			{
+				_srcX += _sx;
+				
+				_error += _dy;
+				if (_error >= _dx)
+				{
+					_srcY += _sy;
+					_error -= _dx;
+				}
+				
+				_error2 += _dz;
+				if (_error2 >= _dx)
+				{
+					_srcZ += _sz;
+					_error2 -= _dx;
+				}
+				
+				return true;
+			}
+		}
+		else if ((_dy >= _dx) && (_dy >= _dz))
+		{
+			if (_srcY != _dstY)
+			{
+				_srcY += _sy;
+				
+				_error += _dx;
+				if (_error >= _dy)
+				{
+					_srcX += _sx;
+					_error -= _dy;
+				}
+				
+				_error2 += _dz;
+				if (_error2 >= _dy)
+				{
+					_srcZ += _sz;
+					_error2 -= _dy;
+				}
+				
+				return true;
+			}
+		}
+		else
+		{
+			if (_srcZ != _dstZ)
+			{
+				_srcZ += _sz;
+				
+				_error += _dx;
+				if (_error >= _dz)
+				{
+					_srcX += _sx;
+					_error -= _dz;
+				}
+				
+				_error2 += _dy;
+				if (_error2 >= _dz)
+				{
+					_srcY += _sy;
+					_error2 -= _dz;
+				}
+				
+				return true;
+			}
+		}
+		
+		return false;
+	}
+	
+	public int x()
+	{
+		return _srcX;
+	}
+	
+	public int y()
+	{
+		return _srcY;
+	}
+	
+	public int z()
+	{
+		return _srcZ;
+	}
+}