Package l2p.gameserver.geodata

Source Code of l2p.gameserver.geodata.GeoMove

package l2p.gameserver.geodata;

import java.util.ArrayList;

import l2p.Config;
import l2p.gameserver.model.L2Object;
import l2p.gameserver.model.L2Player;
import l2p.gameserver.serverpackets.ExShowTrace;
import l2p.util.Location;

/**
* @Author: Diamond
* @Date: 27/04/2009
*/
public class GeoMove
{
  private static final ArrayList<Location> emptyTargetRecorder = new ArrayList<Location>(0);
  private static final ArrayList<ArrayList<Location>> emptyMovePath = new ArrayList<ArrayList<Location>>(0);

  public static ArrayList<Location> findPath(int x, int y, int z, Location target, L2Object obj, boolean showTrace, int refIndex)
  {
    if(Math.abs(z - target.z) > 256)
    {
      return emptyTargetRecorder;
    }
    z = GeoEngine.getHeight(x, y, z, refIndex);
    target.z = GeoEngine.getHeight(target, refIndex);
    PathFind n = new PathFind(x, y, z, target.x, target.y, target.z, obj, refIndex);
    if(n.getPath() == null || n.getPath().isEmpty())
    {
      return emptyTargetRecorder;
    }
    ArrayList<Location> targetRecorder = new ArrayList<Location>(n.getPath().size() + 2);
    // добавляем первую точку в список (начальная позиция чара)
    targetRecorder.add(new Location(x, y, z));
    for(Location p : n.getPath())
    {
      targetRecorder.add(p.geo2world());
    }
    // добавляем последнюю точку в список (цель)
    targetRecorder.add(target);
    if(Config.PATH_CLEAN)
    {
      pathClean(targetRecorder, refIndex);
    }
    if(showTrace && obj.isPlayer() && ((L2Player) obj).getVarB("trace"))
    {
      L2Player player = (L2Player) obj;
      ExShowTrace trace = new ExShowTrace();
      int i = 0;
      for(Location loc : targetRecorder)
      {
        i++;
        if(i == 1 || i == targetRecorder.size())
        {
          continue;
        }
        trace.addTrace(loc.x, loc.y, loc.z + 15, 30000);
      }
      player.sendPacket(trace);
    }
    return targetRecorder;
  }

  public static ArrayList<ArrayList<Location>> findMovePath(int x, int y, int z, Location target, L2Object obj, boolean showTrace, int refIndex)
  {
    return getNodePath(findPath(x, y, z, target, obj, showTrace, refIndex), refIndex);
  }

  public static ArrayList<ArrayList<Location>> getNodePath(ArrayList<Location> path, int refIndex)
  {
    int size = path.size();
    if(size <= 1)
    {
      return emptyMovePath;
    }
    ArrayList<ArrayList<Location>> result = new ArrayList<ArrayList<Location>>();
    for(int i = 1; i < size; i++)
    {
      Location p2 = path.get(i);
      Location p1 = path.get(i - 1);
      ArrayList<Location> moveList = GeoEngine.MoveList(p1.x, p1.y, p1.z, p2.x, p2.y, refIndex, true); // onlyFullPath = true - проверяем весь путь до конца
      if(moveList == null) // если хотя-бы через один из участков нельзя пройти, забраковываем весь путь
      {
        return emptyMovePath;
      }
      if(!moveList.isEmpty()) // это может случиться только если 2 одинаковых точки подряд
      {
        result.add(moveList);
      }
    }
    return result;
  }

  public static ArrayList<Location> constructMoveList(Location begin, Location end)
  {
    begin.world2geo();
    end.world2geo();
    ArrayList<Location> result = new ArrayList<Location>();
    int diff_x = end.x - begin.x, diff_y = end.y - begin.y, diff_z = end.z - begin.z;
    int dx = Math.abs(diff_x), dy = Math.abs(diff_y), dz = Math.abs(diff_z);
    float steps = Math.max(Math.max(dx, dy), dz);
    if(steps == 0) // Никуда не идем
    {
      return result;
    }
    float step_x = diff_x / steps, step_y = diff_y / steps, step_z = diff_z / steps;
    float next_x = begin.x, next_y = begin.y, next_z = begin.z;
    result.add(new Location(begin.x, begin.y, begin.z)); // Первая точка
    for(int i = 0; i < steps; i++)
    {
      next_x += step_x;
      next_y += step_y;
      next_z += step_z;
      result.add(new Location((int) (next_x + 0.5f), (int) (next_y + 0.5f), (int) (next_z + 0.5f)));
    }
    return result;
  }

  /**
   * Очищает путь от ненужных точек.
   *
   * @param path путь который следует очистить
   */
  private static void pathClean(ArrayList<Location> path, int refIndex)
  {
    int size = path.size();
    if(size > 2)
    {
      for(int i = 2; i < size; i++)
      {
        Location p3 = path.get(i); // точка конца движения
        Location p2 = path.get(i - 1); // точка в середине, кандидат на вышибание
        Location p1 = path.get(i - 2); // точка начала движения
        if(p1.equals(p2) || p3.equals(p2) || IsPointInLine(p1, p2, p3)) // если вторая точка совпадает с первой/третьей или на одной линии с ними - она не нужна
        {
          path.remove(i - 1); // удаляем ее
          size--; // отмечаем это в размере массива
          i = Math.max(2, i - 2); // сдвигаемся назад, FIXME: может я тут не совсем прав
        }
      }
    }
    int current = 0;
    int sub;
    while(current < path.size() - 2)
    {
      sub = current + 2;
      while(sub < path.size())
      {
        Location one = path.get(current);
        Location two = path.get(sub);
        if(one.equals(two) || GeoEngine.canMoveWithCollision(one.x, one.y, one.z, two.x, two.y, two.z, refIndex)) //canMoveWithCollision  /  canMoveToCoord
        {
          while(current + 1 < sub)
          {
            path.remove(current + 1);
            sub--;
          }
        }
        sub++;
      }
      current++;
    }
  }

  private static boolean IsPointInLine(Location p1, Location p2, Location p3)
  {
    // Все 3 точки на одной из осей X или Y.
    if(p1.x == p3.x && p3.x == p2.x || p1.y == p3.y && p3.y == p2.y)
    {
      return true;
    }
    // Условие ниже выполнится если все 3 точки выстроены по диагонали.
    // Это работает потому, что сравниваем мы соседние точки (расстояния между ними равны, важен только знак).
    // Для случая с произвольными точками работать не будет.
    if((p1.x - p2.x) * (p1.y - p2.y) == (p2.x - p3.x) * (p2.y - p3.y))
    {
      return true;
    }
    return false;
  }
}
TOP

Related Classes of l2p.gameserver.geodata.GeoMove

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.