GeoEngine door check improvements.
Contributed by Sahar.
This commit is contained in:
@@ -958,7 +958,6 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
|
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
|
||||||
if (isFollowing())
|
if (isFollowing())
|
||||||
{
|
{
|
||||||
|
|
||||||
// allow larger hit range when the target is moving (check is run only once per second)
|
// allow larger hit range when the target is moving (check is run only once per second)
|
||||||
if (!_actor.isInsideRadius(target, offset + 100, false, false))
|
if (!_actor.isInsideRadius(target, offset + 100, false, false))
|
||||||
{
|
{
|
||||||
@@ -981,14 +980,11 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// while flying there is no move to cast
|
// while flying there is no move to cast
|
||||||
if (_actor.getAI().getIntention() == AI_INTENTION_CAST)
|
if (_actor.getAI().getIntention() == AI_INTENTION_CAST && _actor.isPlayer() && _actor.checkTransformed(transform -> !transform.isCombat()))
|
||||||
{
|
{
|
||||||
if (_actor.checkTransformed(transform -> !transform.isCombat()))
|
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_STOPPED);
|
||||||
{
|
_actor.sendPacket(ActionFailed.STATIC_PACKET);
|
||||||
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_STOPPED);
|
return true;
|
||||||
_actor.sendPacket(ActionFailed.STATIC_PACKET);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
|
// If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
|
||||||
|
@@ -35,13 +35,11 @@ import com.l2jmobius.gameserver.geoengine.geodata.BlockNull;
|
|||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.IGeoObject;
|
|
||||||
import com.l2jmobius.gameserver.instancemanager.WarpedSpaceManager;
|
import com.l2jmobius.gameserver.instancemanager.WarpedSpaceManager;
|
||||||
import com.l2jmobius.gameserver.model.L2Object;
|
import com.l2jmobius.gameserver.model.L2Object;
|
||||||
import com.l2jmobius.gameserver.model.L2World;
|
import com.l2jmobius.gameserver.model.L2World;
|
||||||
import com.l2jmobius.gameserver.model.Location;
|
import com.l2jmobius.gameserver.model.Location;
|
||||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
|
|
||||||
import com.l2jmobius.gameserver.model.instancezone.Instance;
|
import com.l2jmobius.gameserver.model.instancezone.Instance;
|
||||||
import com.l2jmobius.gameserver.util.MathUtil;
|
import com.l2jmobius.gameserver.util.MathUtil;
|
||||||
|
|
||||||
@@ -317,20 +315,6 @@ public class GeoEngine
|
|||||||
return block != null ? block.getHeightNearest(geoX, geoY, worldZ) : (short) worldZ;
|
return block != null ? block.getHeightNearest(geoX, geoY, worldZ) : (short) worldZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the height of cell, which is closest to given coordinates.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.
|
|
||||||
* @param geoX : Cell geodata X coordinate.
|
|
||||||
* @param geoY : Cell geodata Y coordinate.
|
|
||||||
* @param worldZ : Cell world Z coordinate.
|
|
||||||
* @return short : Cell geodata Z coordinate, closest to given coordinates.
|
|
||||||
*/
|
|
||||||
private final short getHeightNearestOriginal(int geoX, int geoY, int worldZ)
|
|
||||||
{
|
|
||||||
final ABlock block = getBlock(geoX, geoY);
|
|
||||||
return block != null ? block.getHeightNearestOriginal(geoX, geoY, worldZ) : (short) worldZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the NSWE flag byte of cell, which is closes to given coordinates.
|
* Returns the NSWE flag byte of cell, which is closes to given coordinates.
|
||||||
* @param geoX : Cell geodata X coordinate.
|
* @param geoX : Cell geodata X coordinate.
|
||||||
@@ -344,20 +328,6 @@ public class GeoEngine
|
|||||||
return block != null ? block.getNsweNearest(geoX, geoY, worldZ) : (byte) 0xFF;
|
return block != null ? block.getNsweNearest(geoX, geoY, worldZ) : (byte) 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the NSWE flag byte of cell, which is closes to given coordinates.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.
|
|
||||||
* @param geoX : Cell geodata X coordinate.
|
|
||||||
* @param geoY : Cell geodata Y coordinate.
|
|
||||||
* @param worldZ : Cell world Z coordinate.
|
|
||||||
* @return short : Cell NSWE flag byte coordinate, closest to given coordinates.
|
|
||||||
*/
|
|
||||||
private final byte getNsweNearestOriginal(int geoX, int geoY, int worldZ)
|
|
||||||
{
|
|
||||||
final ABlock block = getBlock(geoX, geoY);
|
|
||||||
return block != null ? block.getNsweNearestOriginal(geoX, geoY, worldZ) : (byte) 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if world coordinates has geo.
|
* Check if world coordinates has geo.
|
||||||
* @param worldX : World X
|
* @param worldX : World X
|
||||||
@@ -391,6 +361,11 @@ public class GeoEngine
|
|||||||
*/
|
*/
|
||||||
public final boolean canSeeTarget(L2Object origin, L2Object target)
|
public final boolean canSeeTarget(L2Object origin, L2Object target)
|
||||||
{
|
{
|
||||||
|
if (target.isDoor())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// get origin and target world coordinates
|
// get origin and target world coordinates
|
||||||
final int ox = origin.getX();
|
final int ox = origin.getX();
|
||||||
final int oy = origin.getY();
|
final int oy = origin.getY();
|
||||||
@@ -399,7 +374,7 @@ public class GeoEngine
|
|||||||
final int ty = target.getY();
|
final int ty = target.getY();
|
||||||
final int tz = target.getZ();
|
final int tz = target.getZ();
|
||||||
|
|
||||||
if (!target.isDoor() && DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), false))
|
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -430,8 +405,7 @@ public class GeoEngine
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean door = target.isDoor();
|
final short gtz = getHeightNearest(gtx, gty, tz);
|
||||||
final short gtz = door ? getHeightNearestOriginal(gtx, gty, tz) : getHeightNearest(gtx, gty, tz);
|
|
||||||
|
|
||||||
// origin and target coordinates are same
|
// origin and target coordinates are same
|
||||||
if ((gox == gtx) && (goy == gty))
|
if ((gox == gtx) && (goy == gty))
|
||||||
@@ -453,7 +427,7 @@ public class GeoEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
// perform geodata check
|
// perform geodata check
|
||||||
return door ? checkSeeOriginal(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld()) : checkSee(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld());
|
return checkSee(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -472,7 +446,7 @@ public class GeoEngine
|
|||||||
final int ty = position.getY();
|
final int ty = position.getY();
|
||||||
final int tz = position.getZ();
|
final int tz = position.getZ();
|
||||||
|
|
||||||
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), false))
|
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -703,189 +677,6 @@ public class GeoEngine
|
|||||||
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple check for origin to target visibility.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.<br>
|
|
||||||
* NOTE: When two doors close between each other and the LoS check of one doors is performed through another door, result will not be accurate (the other door are skipped).
|
|
||||||
* @param gox : origin X geodata coordinate
|
|
||||||
* @param goy : origin Y geodata coordinate
|
|
||||||
* @param goz : origin Z geodata coordinate
|
|
||||||
* @param oheight : origin height (if instance of {@link Character})
|
|
||||||
* @param gtx : target X geodata coordinate
|
|
||||||
* @param gty : target Y geodata coordinate
|
|
||||||
* @param gtz : target Z geodata coordinate
|
|
||||||
* @param theight : target height (if instance of {@link Character} or {@link L2DoorInstance})
|
|
||||||
* @param instance
|
|
||||||
* @return {@code boolean} : True, when target can be seen.
|
|
||||||
*/
|
|
||||||
private final boolean checkSeeOriginal(int gox, int goy, int goz, double oheight, int gtx, int gty, int gtz, double theight, Instance instance)
|
|
||||||
{
|
|
||||||
// get line of sight Z coordinates
|
|
||||||
double losoz = goz + ((oheight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
|
||||||
double lostz = gtz + ((theight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
|
||||||
|
|
||||||
// get X delta and signum
|
|
||||||
final int dx = Math.abs(gtx - gox);
|
|
||||||
final int sx = gox < gtx ? 1 : -1;
|
|
||||||
final byte dirox = sx > 0 ? GeoStructure.CELL_FLAG_E : GeoStructure.CELL_FLAG_W;
|
|
||||||
final byte dirtx = sx > 0 ? GeoStructure.CELL_FLAG_W : GeoStructure.CELL_FLAG_E;
|
|
||||||
|
|
||||||
// get Y delta and signum
|
|
||||||
final int dy = Math.abs(gty - goy);
|
|
||||||
final int sy = goy < gty ? 1 : -1;
|
|
||||||
final byte diroy = sy > 0 ? GeoStructure.CELL_FLAG_S : GeoStructure.CELL_FLAG_N;
|
|
||||||
final byte dirty = sy > 0 ? GeoStructure.CELL_FLAG_N : GeoStructure.CELL_FLAG_S;
|
|
||||||
|
|
||||||
// get Z delta
|
|
||||||
final int dm = Math.max(dx, dy);
|
|
||||||
final double dz = (lostz - losoz) / dm;
|
|
||||||
|
|
||||||
// get direction flag for diagonal movement
|
|
||||||
final byte diroxy = getDirXY(dirox, diroy);
|
|
||||||
final byte dirtxy = getDirXY(dirtx, dirty);
|
|
||||||
|
|
||||||
// delta, determines axis to move on (+..X axis, -..Y axis)
|
|
||||||
int d = dx - dy;
|
|
||||||
|
|
||||||
// NSWE direction of movement
|
|
||||||
byte diro;
|
|
||||||
byte dirt;
|
|
||||||
|
|
||||||
// clearDebugItems();
|
|
||||||
// dropDebugItem(728, 0, new GeoLocation(gox, goy, goz)); // blue potion
|
|
||||||
// dropDebugItem(728, 0, new GeoLocation(gtx, gty, gtz)); // blue potion
|
|
||||||
|
|
||||||
// initialize node values
|
|
||||||
int nox = gox;
|
|
||||||
int noy = goy;
|
|
||||||
int ntx = gtx;
|
|
||||||
int nty = gty;
|
|
||||||
byte nsweo = getNsweNearestOriginal(gox, goy, goz);
|
|
||||||
byte nswet = getNsweNearestOriginal(gtx, gty, gtz);
|
|
||||||
|
|
||||||
// loop
|
|
||||||
ABlock block;
|
|
||||||
int index;
|
|
||||||
for (int i = 0; i < ((dm + 1) / 2); i++)
|
|
||||||
{
|
|
||||||
// dropDebugItem(57, 0, new GeoLocation(gox, goy, goz)); // antidote
|
|
||||||
// dropDebugItem(1831, 0, new GeoLocation(gtx, gty, gtz)); // adena
|
|
||||||
|
|
||||||
// reset direction flag
|
|
||||||
diro = 0;
|
|
||||||
dirt = 0;
|
|
||||||
|
|
||||||
// calculate next point coordinates
|
|
||||||
int e2 = 2 * d;
|
|
||||||
if ((e2 > -dy) && (e2 < dx))
|
|
||||||
{
|
|
||||||
// calculate next point XY coordinates
|
|
||||||
d -= dy;
|
|
||||||
d += dx;
|
|
||||||
nox += sx;
|
|
||||||
ntx -= sx;
|
|
||||||
noy += sy;
|
|
||||||
nty -= sy;
|
|
||||||
diro |= diroxy;
|
|
||||||
dirt |= dirtxy;
|
|
||||||
}
|
|
||||||
else if (e2 > -dy)
|
|
||||||
{
|
|
||||||
// calculate next point X coordinate
|
|
||||||
d -= dy;
|
|
||||||
nox += sx;
|
|
||||||
ntx -= sx;
|
|
||||||
diro |= dirox;
|
|
||||||
dirt |= dirtx;
|
|
||||||
}
|
|
||||||
else if (e2 < dx)
|
|
||||||
{
|
|
||||||
// calculate next point Y coordinate
|
|
||||||
d += dx;
|
|
||||||
noy += sy;
|
|
||||||
nty -= sy;
|
|
||||||
diro |= diroy;
|
|
||||||
dirt |= dirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// get block of the next cell
|
|
||||||
block = getBlock(nox, noy);
|
|
||||||
|
|
||||||
// get index of particular layer, based on movement conditions
|
|
||||||
if ((nsweo & diro) == 0)
|
|
||||||
{
|
|
||||||
index = block.getIndexAboveOriginal(nox, noy, goz - GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = block.getIndexBelowOriginal(nox, noy, goz + GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layer does not exist, return
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer and next line of sight Z coordinate
|
|
||||||
goz = block.getHeightOriginal(index);
|
|
||||||
losoz += dz;
|
|
||||||
|
|
||||||
// perform line of sight check, return when fails
|
|
||||||
if ((goz - losoz) > Config.MAX_OBSTACLE_HEIGHT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer nswe
|
|
||||||
nsweo = block.getNsweOriginal(index);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// get block of the next cell
|
|
||||||
block = getBlock(ntx, nty);
|
|
||||||
|
|
||||||
// get index of particular layer, based on movement conditions
|
|
||||||
if ((nswet & dirt) == 0)
|
|
||||||
{
|
|
||||||
index = block.getIndexAboveOriginal(ntx, nty, gtz - GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = block.getIndexBelowOriginal(ntx, nty, gtz + GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layer does not exist, return
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer and next line of sight Z coordinate
|
|
||||||
gtz = block.getHeightOriginal(index);
|
|
||||||
lostz -= dz;
|
|
||||||
|
|
||||||
// perform line of sight check, return when fails
|
|
||||||
if ((gtz - lostz) > Config.MAX_OBSTACLE_HEIGHT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer nswe
|
|
||||||
nswet = block.getNsweOriginal(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update coords
|
|
||||||
gox = nox;
|
|
||||||
goy = noy;
|
|
||||||
gtx = ntx;
|
|
||||||
gty = nty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when iteration is completed, compare final Z coordinates
|
|
||||||
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check movement from coordinates to coordinates.
|
* Check movement from coordinates to coordinates.
|
||||||
* @param ox : origin X coordinate
|
* @param ox : origin X coordinate
|
||||||
|
@@ -958,7 +958,6 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
|
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
|
||||||
if (isFollowing())
|
if (isFollowing())
|
||||||
{
|
{
|
||||||
|
|
||||||
// allow larger hit range when the target is moving (check is run only once per second)
|
// allow larger hit range when the target is moving (check is run only once per second)
|
||||||
if (!_actor.isInsideRadius(target, offset + 100, false, false))
|
if (!_actor.isInsideRadius(target, offset + 100, false, false))
|
||||||
{
|
{
|
||||||
@@ -981,14 +980,11 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// while flying there is no move to cast
|
// while flying there is no move to cast
|
||||||
if (_actor.getAI().getIntention() == AI_INTENTION_CAST)
|
if (_actor.getAI().getIntention() == AI_INTENTION_CAST && _actor.isPlayer() && _actor.checkTransformed(transform -> !transform.isCombat()))
|
||||||
{
|
{
|
||||||
if (_actor.checkTransformed(transform -> !transform.isCombat()))
|
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_STOPPED);
|
||||||
{
|
_actor.sendPacket(ActionFailed.STATIC_PACKET);
|
||||||
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_STOPPED);
|
return true;
|
||||||
_actor.sendPacket(ActionFailed.STATIC_PACKET);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
|
// If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
|
||||||
|
@@ -35,13 +35,11 @@ import com.l2jmobius.gameserver.geoengine.geodata.BlockNull;
|
|||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.IGeoObject;
|
|
||||||
import com.l2jmobius.gameserver.instancemanager.WarpedSpaceManager;
|
import com.l2jmobius.gameserver.instancemanager.WarpedSpaceManager;
|
||||||
import com.l2jmobius.gameserver.model.L2Object;
|
import com.l2jmobius.gameserver.model.L2Object;
|
||||||
import com.l2jmobius.gameserver.model.L2World;
|
import com.l2jmobius.gameserver.model.L2World;
|
||||||
import com.l2jmobius.gameserver.model.Location;
|
import com.l2jmobius.gameserver.model.Location;
|
||||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
|
|
||||||
import com.l2jmobius.gameserver.model.instancezone.Instance;
|
import com.l2jmobius.gameserver.model.instancezone.Instance;
|
||||||
import com.l2jmobius.gameserver.util.MathUtil;
|
import com.l2jmobius.gameserver.util.MathUtil;
|
||||||
|
|
||||||
@@ -317,20 +315,6 @@ public class GeoEngine
|
|||||||
return block != null ? block.getHeightNearest(geoX, geoY, worldZ) : (short) worldZ;
|
return block != null ? block.getHeightNearest(geoX, geoY, worldZ) : (short) worldZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the height of cell, which is closest to given coordinates.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.
|
|
||||||
* @param geoX : Cell geodata X coordinate.
|
|
||||||
* @param geoY : Cell geodata Y coordinate.
|
|
||||||
* @param worldZ : Cell world Z coordinate.
|
|
||||||
* @return short : Cell geodata Z coordinate, closest to given coordinates.
|
|
||||||
*/
|
|
||||||
private final short getHeightNearestOriginal(int geoX, int geoY, int worldZ)
|
|
||||||
{
|
|
||||||
final ABlock block = getBlock(geoX, geoY);
|
|
||||||
return block != null ? block.getHeightNearestOriginal(geoX, geoY, worldZ) : (short) worldZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the NSWE flag byte of cell, which is closes to given coordinates.
|
* Returns the NSWE flag byte of cell, which is closes to given coordinates.
|
||||||
* @param geoX : Cell geodata X coordinate.
|
* @param geoX : Cell geodata X coordinate.
|
||||||
@@ -344,20 +328,6 @@ public class GeoEngine
|
|||||||
return block != null ? block.getNsweNearest(geoX, geoY, worldZ) : (byte) 0xFF;
|
return block != null ? block.getNsweNearest(geoX, geoY, worldZ) : (byte) 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the NSWE flag byte of cell, which is closes to given coordinates.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.
|
|
||||||
* @param geoX : Cell geodata X coordinate.
|
|
||||||
* @param geoY : Cell geodata Y coordinate.
|
|
||||||
* @param worldZ : Cell world Z coordinate.
|
|
||||||
* @return short : Cell NSWE flag byte coordinate, closest to given coordinates.
|
|
||||||
*/
|
|
||||||
private final byte getNsweNearestOriginal(int geoX, int geoY, int worldZ)
|
|
||||||
{
|
|
||||||
final ABlock block = getBlock(geoX, geoY);
|
|
||||||
return block != null ? block.getNsweNearestOriginal(geoX, geoY, worldZ) : (byte) 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if world coordinates has geo.
|
* Check if world coordinates has geo.
|
||||||
* @param worldX : World X
|
* @param worldX : World X
|
||||||
@@ -391,6 +361,11 @@ public class GeoEngine
|
|||||||
*/
|
*/
|
||||||
public final boolean canSeeTarget(L2Object origin, L2Object target)
|
public final boolean canSeeTarget(L2Object origin, L2Object target)
|
||||||
{
|
{
|
||||||
|
if (target.isDoor())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// get origin and target world coordinates
|
// get origin and target world coordinates
|
||||||
final int ox = origin.getX();
|
final int ox = origin.getX();
|
||||||
final int oy = origin.getY();
|
final int oy = origin.getY();
|
||||||
@@ -399,7 +374,7 @@ public class GeoEngine
|
|||||||
final int ty = target.getY();
|
final int ty = target.getY();
|
||||||
final int tz = target.getZ();
|
final int tz = target.getZ();
|
||||||
|
|
||||||
if (!target.isDoor() && DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), false))
|
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -430,8 +405,7 @@ public class GeoEngine
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean door = target.isDoor();
|
final short gtz = getHeightNearest(gtx, gty, tz);
|
||||||
final short gtz = door ? getHeightNearestOriginal(gtx, gty, tz) : getHeightNearest(gtx, gty, tz);
|
|
||||||
|
|
||||||
// origin and target coordinates are same
|
// origin and target coordinates are same
|
||||||
if ((gox == gtx) && (goy == gty))
|
if ((gox == gtx) && (goy == gty))
|
||||||
@@ -453,7 +427,7 @@ public class GeoEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
// perform geodata check
|
// perform geodata check
|
||||||
return door ? checkSeeOriginal(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld()) : checkSee(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld());
|
return checkSee(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -472,7 +446,7 @@ public class GeoEngine
|
|||||||
final int ty = position.getY();
|
final int ty = position.getY();
|
||||||
final int tz = position.getZ();
|
final int tz = position.getZ();
|
||||||
|
|
||||||
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), false))
|
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -703,189 +677,6 @@ public class GeoEngine
|
|||||||
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple check for origin to target visibility.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.<br>
|
|
||||||
* NOTE: When two doors close between each other and the LoS check of one doors is performed through another door, result will not be accurate (the other door are skipped).
|
|
||||||
* @param gox : origin X geodata coordinate
|
|
||||||
* @param goy : origin Y geodata coordinate
|
|
||||||
* @param goz : origin Z geodata coordinate
|
|
||||||
* @param oheight : origin height (if instance of {@link Character})
|
|
||||||
* @param gtx : target X geodata coordinate
|
|
||||||
* @param gty : target Y geodata coordinate
|
|
||||||
* @param gtz : target Z geodata coordinate
|
|
||||||
* @param theight : target height (if instance of {@link Character} or {@link L2DoorInstance})
|
|
||||||
* @param instance
|
|
||||||
* @return {@code boolean} : True, when target can be seen.
|
|
||||||
*/
|
|
||||||
private final boolean checkSeeOriginal(int gox, int goy, int goz, double oheight, int gtx, int gty, int gtz, double theight, Instance instance)
|
|
||||||
{
|
|
||||||
// get line of sight Z coordinates
|
|
||||||
double losoz = goz + ((oheight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
|
||||||
double lostz = gtz + ((theight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
|
||||||
|
|
||||||
// get X delta and signum
|
|
||||||
final int dx = Math.abs(gtx - gox);
|
|
||||||
final int sx = gox < gtx ? 1 : -1;
|
|
||||||
final byte dirox = sx > 0 ? GeoStructure.CELL_FLAG_E : GeoStructure.CELL_FLAG_W;
|
|
||||||
final byte dirtx = sx > 0 ? GeoStructure.CELL_FLAG_W : GeoStructure.CELL_FLAG_E;
|
|
||||||
|
|
||||||
// get Y delta and signum
|
|
||||||
final int dy = Math.abs(gty - goy);
|
|
||||||
final int sy = goy < gty ? 1 : -1;
|
|
||||||
final byte diroy = sy > 0 ? GeoStructure.CELL_FLAG_S : GeoStructure.CELL_FLAG_N;
|
|
||||||
final byte dirty = sy > 0 ? GeoStructure.CELL_FLAG_N : GeoStructure.CELL_FLAG_S;
|
|
||||||
|
|
||||||
// get Z delta
|
|
||||||
final int dm = Math.max(dx, dy);
|
|
||||||
final double dz = (lostz - losoz) / dm;
|
|
||||||
|
|
||||||
// get direction flag for diagonal movement
|
|
||||||
final byte diroxy = getDirXY(dirox, diroy);
|
|
||||||
final byte dirtxy = getDirXY(dirtx, dirty);
|
|
||||||
|
|
||||||
// delta, determines axis to move on (+..X axis, -..Y axis)
|
|
||||||
int d = dx - dy;
|
|
||||||
|
|
||||||
// NSWE direction of movement
|
|
||||||
byte diro;
|
|
||||||
byte dirt;
|
|
||||||
|
|
||||||
// clearDebugItems();
|
|
||||||
// dropDebugItem(728, 0, new GeoLocation(gox, goy, goz)); // blue potion
|
|
||||||
// dropDebugItem(728, 0, new GeoLocation(gtx, gty, gtz)); // blue potion
|
|
||||||
|
|
||||||
// initialize node values
|
|
||||||
int nox = gox;
|
|
||||||
int noy = goy;
|
|
||||||
int ntx = gtx;
|
|
||||||
int nty = gty;
|
|
||||||
byte nsweo = getNsweNearestOriginal(gox, goy, goz);
|
|
||||||
byte nswet = getNsweNearestOriginal(gtx, gty, gtz);
|
|
||||||
|
|
||||||
// loop
|
|
||||||
ABlock block;
|
|
||||||
int index;
|
|
||||||
for (int i = 0; i < ((dm + 1) / 2); i++)
|
|
||||||
{
|
|
||||||
// dropDebugItem(57, 0, new GeoLocation(gox, goy, goz)); // antidote
|
|
||||||
// dropDebugItem(1831, 0, new GeoLocation(gtx, gty, gtz)); // adena
|
|
||||||
|
|
||||||
// reset direction flag
|
|
||||||
diro = 0;
|
|
||||||
dirt = 0;
|
|
||||||
|
|
||||||
// calculate next point coordinates
|
|
||||||
int e2 = 2 * d;
|
|
||||||
if ((e2 > -dy) && (e2 < dx))
|
|
||||||
{
|
|
||||||
// calculate next point XY coordinates
|
|
||||||
d -= dy;
|
|
||||||
d += dx;
|
|
||||||
nox += sx;
|
|
||||||
ntx -= sx;
|
|
||||||
noy += sy;
|
|
||||||
nty -= sy;
|
|
||||||
diro |= diroxy;
|
|
||||||
dirt |= dirtxy;
|
|
||||||
}
|
|
||||||
else if (e2 > -dy)
|
|
||||||
{
|
|
||||||
// calculate next point X coordinate
|
|
||||||
d -= dy;
|
|
||||||
nox += sx;
|
|
||||||
ntx -= sx;
|
|
||||||
diro |= dirox;
|
|
||||||
dirt |= dirtx;
|
|
||||||
}
|
|
||||||
else if (e2 < dx)
|
|
||||||
{
|
|
||||||
// calculate next point Y coordinate
|
|
||||||
d += dx;
|
|
||||||
noy += sy;
|
|
||||||
nty -= sy;
|
|
||||||
diro |= diroy;
|
|
||||||
dirt |= dirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// get block of the next cell
|
|
||||||
block = getBlock(nox, noy);
|
|
||||||
|
|
||||||
// get index of particular layer, based on movement conditions
|
|
||||||
if ((nsweo & diro) == 0)
|
|
||||||
{
|
|
||||||
index = block.getIndexAboveOriginal(nox, noy, goz - GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = block.getIndexBelowOriginal(nox, noy, goz + GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layer does not exist, return
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer and next line of sight Z coordinate
|
|
||||||
goz = block.getHeightOriginal(index);
|
|
||||||
losoz += dz;
|
|
||||||
|
|
||||||
// perform line of sight check, return when fails
|
|
||||||
if ((goz - losoz) > Config.MAX_OBSTACLE_HEIGHT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer nswe
|
|
||||||
nsweo = block.getNsweOriginal(index);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// get block of the next cell
|
|
||||||
block = getBlock(ntx, nty);
|
|
||||||
|
|
||||||
// get index of particular layer, based on movement conditions
|
|
||||||
if ((nswet & dirt) == 0)
|
|
||||||
{
|
|
||||||
index = block.getIndexAboveOriginal(ntx, nty, gtz - GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = block.getIndexBelowOriginal(ntx, nty, gtz + GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layer does not exist, return
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer and next line of sight Z coordinate
|
|
||||||
gtz = block.getHeightOriginal(index);
|
|
||||||
lostz -= dz;
|
|
||||||
|
|
||||||
// perform line of sight check, return when fails
|
|
||||||
if ((gtz - lostz) > Config.MAX_OBSTACLE_HEIGHT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer nswe
|
|
||||||
nswet = block.getNsweOriginal(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update coords
|
|
||||||
gox = nox;
|
|
||||||
goy = noy;
|
|
||||||
gtx = ntx;
|
|
||||||
gty = nty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when iteration is completed, compare final Z coordinates
|
|
||||||
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check movement from coordinates to coordinates.
|
* Check movement from coordinates to coordinates.
|
||||||
* @param ox : origin X coordinate
|
* @param ox : origin X coordinate
|
||||||
|
@@ -958,7 +958,6 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
|
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
|
||||||
if (isFollowing())
|
if (isFollowing())
|
||||||
{
|
{
|
||||||
|
|
||||||
// allow larger hit range when the target is moving (check is run only once per second)
|
// allow larger hit range when the target is moving (check is run only once per second)
|
||||||
if (!_actor.isInsideRadius(target, offset + 100, false, false))
|
if (!_actor.isInsideRadius(target, offset + 100, false, false))
|
||||||
{
|
{
|
||||||
@@ -981,14 +980,11 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// while flying there is no move to cast
|
// while flying there is no move to cast
|
||||||
if (_actor.getAI().getIntention() == AI_INTENTION_CAST)
|
if (_actor.getAI().getIntention() == AI_INTENTION_CAST && _actor.isPlayer() && _actor.checkTransformed(transform -> !transform.isCombat()))
|
||||||
{
|
{
|
||||||
if (_actor.checkTransformed(transform -> !transform.isCombat()))
|
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_STOPPED);
|
||||||
{
|
_actor.sendPacket(ActionFailed.STATIC_PACKET);
|
||||||
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_STOPPED);
|
return true;
|
||||||
_actor.sendPacket(ActionFailed.STATIC_PACKET);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
|
// If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
|
||||||
|
@@ -35,13 +35,11 @@ import com.l2jmobius.gameserver.geoengine.geodata.BlockNull;
|
|||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.IGeoObject;
|
|
||||||
import com.l2jmobius.gameserver.instancemanager.WarpedSpaceManager;
|
import com.l2jmobius.gameserver.instancemanager.WarpedSpaceManager;
|
||||||
import com.l2jmobius.gameserver.model.L2Object;
|
import com.l2jmobius.gameserver.model.L2Object;
|
||||||
import com.l2jmobius.gameserver.model.L2World;
|
import com.l2jmobius.gameserver.model.L2World;
|
||||||
import com.l2jmobius.gameserver.model.Location;
|
import com.l2jmobius.gameserver.model.Location;
|
||||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
|
|
||||||
import com.l2jmobius.gameserver.model.instancezone.Instance;
|
import com.l2jmobius.gameserver.model.instancezone.Instance;
|
||||||
import com.l2jmobius.gameserver.util.MathUtil;
|
import com.l2jmobius.gameserver.util.MathUtil;
|
||||||
|
|
||||||
@@ -317,20 +315,6 @@ public class GeoEngine
|
|||||||
return block != null ? block.getHeightNearest(geoX, geoY, worldZ) : (short) worldZ;
|
return block != null ? block.getHeightNearest(geoX, geoY, worldZ) : (short) worldZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the height of cell, which is closest to given coordinates.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.
|
|
||||||
* @param geoX : Cell geodata X coordinate.
|
|
||||||
* @param geoY : Cell geodata Y coordinate.
|
|
||||||
* @param worldZ : Cell world Z coordinate.
|
|
||||||
* @return short : Cell geodata Z coordinate, closest to given coordinates.
|
|
||||||
*/
|
|
||||||
private final short getHeightNearestOriginal(int geoX, int geoY, int worldZ)
|
|
||||||
{
|
|
||||||
final ABlock block = getBlock(geoX, geoY);
|
|
||||||
return block != null ? block.getHeightNearestOriginal(geoX, geoY, worldZ) : (short) worldZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the NSWE flag byte of cell, which is closes to given coordinates.
|
* Returns the NSWE flag byte of cell, which is closes to given coordinates.
|
||||||
* @param geoX : Cell geodata X coordinate.
|
* @param geoX : Cell geodata X coordinate.
|
||||||
@@ -344,20 +328,6 @@ public class GeoEngine
|
|||||||
return block != null ? block.getNsweNearest(geoX, geoY, worldZ) : (byte) 0xFF;
|
return block != null ? block.getNsweNearest(geoX, geoY, worldZ) : (byte) 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the NSWE flag byte of cell, which is closes to given coordinates.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.
|
|
||||||
* @param geoX : Cell geodata X coordinate.
|
|
||||||
* @param geoY : Cell geodata Y coordinate.
|
|
||||||
* @param worldZ : Cell world Z coordinate.
|
|
||||||
* @return short : Cell NSWE flag byte coordinate, closest to given coordinates.
|
|
||||||
*/
|
|
||||||
private final byte getNsweNearestOriginal(int geoX, int geoY, int worldZ)
|
|
||||||
{
|
|
||||||
final ABlock block = getBlock(geoX, geoY);
|
|
||||||
return block != null ? block.getNsweNearestOriginal(geoX, geoY, worldZ) : (byte) 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if world coordinates has geo.
|
* Check if world coordinates has geo.
|
||||||
* @param worldX : World X
|
* @param worldX : World X
|
||||||
@@ -391,6 +361,11 @@ public class GeoEngine
|
|||||||
*/
|
*/
|
||||||
public final boolean canSeeTarget(L2Object origin, L2Object target)
|
public final boolean canSeeTarget(L2Object origin, L2Object target)
|
||||||
{
|
{
|
||||||
|
if (target.isDoor())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// get origin and target world coordinates
|
// get origin and target world coordinates
|
||||||
final int ox = origin.getX();
|
final int ox = origin.getX();
|
||||||
final int oy = origin.getY();
|
final int oy = origin.getY();
|
||||||
@@ -399,7 +374,7 @@ public class GeoEngine
|
|||||||
final int ty = target.getY();
|
final int ty = target.getY();
|
||||||
final int tz = target.getZ();
|
final int tz = target.getZ();
|
||||||
|
|
||||||
if (!target.isDoor() && DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), false))
|
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -430,8 +405,7 @@ public class GeoEngine
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean door = target.isDoor();
|
final short gtz = getHeightNearest(gtx, gty, tz);
|
||||||
final short gtz = door ? getHeightNearestOriginal(gtx, gty, tz) : getHeightNearest(gtx, gty, tz);
|
|
||||||
|
|
||||||
// origin and target coordinates are same
|
// origin and target coordinates are same
|
||||||
if ((gox == gtx) && (goy == gty))
|
if ((gox == gtx) && (goy == gty))
|
||||||
@@ -453,7 +427,7 @@ public class GeoEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
// perform geodata check
|
// perform geodata check
|
||||||
return door ? checkSeeOriginal(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld()) : checkSee(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld());
|
return checkSee(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -472,7 +446,7 @@ public class GeoEngine
|
|||||||
final int ty = position.getY();
|
final int ty = position.getY();
|
||||||
final int tz = position.getZ();
|
final int tz = position.getZ();
|
||||||
|
|
||||||
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), false))
|
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -703,189 +677,6 @@ public class GeoEngine
|
|||||||
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple check for origin to target visibility.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.<br>
|
|
||||||
* NOTE: When two doors close between each other and the LoS check of one doors is performed through another door, result will not be accurate (the other door are skipped).
|
|
||||||
* @param gox : origin X geodata coordinate
|
|
||||||
* @param goy : origin Y geodata coordinate
|
|
||||||
* @param goz : origin Z geodata coordinate
|
|
||||||
* @param oheight : origin height (if instance of {@link Character})
|
|
||||||
* @param gtx : target X geodata coordinate
|
|
||||||
* @param gty : target Y geodata coordinate
|
|
||||||
* @param gtz : target Z geodata coordinate
|
|
||||||
* @param theight : target height (if instance of {@link Character} or {@link L2DoorInstance})
|
|
||||||
* @param instance
|
|
||||||
* @return {@code boolean} : True, when target can be seen.
|
|
||||||
*/
|
|
||||||
private final boolean checkSeeOriginal(int gox, int goy, int goz, double oheight, int gtx, int gty, int gtz, double theight, Instance instance)
|
|
||||||
{
|
|
||||||
// get line of sight Z coordinates
|
|
||||||
double losoz = goz + ((oheight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
|
||||||
double lostz = gtz + ((theight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
|
||||||
|
|
||||||
// get X delta and signum
|
|
||||||
final int dx = Math.abs(gtx - gox);
|
|
||||||
final int sx = gox < gtx ? 1 : -1;
|
|
||||||
final byte dirox = sx > 0 ? GeoStructure.CELL_FLAG_E : GeoStructure.CELL_FLAG_W;
|
|
||||||
final byte dirtx = sx > 0 ? GeoStructure.CELL_FLAG_W : GeoStructure.CELL_FLAG_E;
|
|
||||||
|
|
||||||
// get Y delta and signum
|
|
||||||
final int dy = Math.abs(gty - goy);
|
|
||||||
final int sy = goy < gty ? 1 : -1;
|
|
||||||
final byte diroy = sy > 0 ? GeoStructure.CELL_FLAG_S : GeoStructure.CELL_FLAG_N;
|
|
||||||
final byte dirty = sy > 0 ? GeoStructure.CELL_FLAG_N : GeoStructure.CELL_FLAG_S;
|
|
||||||
|
|
||||||
// get Z delta
|
|
||||||
final int dm = Math.max(dx, dy);
|
|
||||||
final double dz = (lostz - losoz) / dm;
|
|
||||||
|
|
||||||
// get direction flag for diagonal movement
|
|
||||||
final byte diroxy = getDirXY(dirox, diroy);
|
|
||||||
final byte dirtxy = getDirXY(dirtx, dirty);
|
|
||||||
|
|
||||||
// delta, determines axis to move on (+..X axis, -..Y axis)
|
|
||||||
int d = dx - dy;
|
|
||||||
|
|
||||||
// NSWE direction of movement
|
|
||||||
byte diro;
|
|
||||||
byte dirt;
|
|
||||||
|
|
||||||
// clearDebugItems();
|
|
||||||
// dropDebugItem(728, 0, new GeoLocation(gox, goy, goz)); // blue potion
|
|
||||||
// dropDebugItem(728, 0, new GeoLocation(gtx, gty, gtz)); // blue potion
|
|
||||||
|
|
||||||
// initialize node values
|
|
||||||
int nox = gox;
|
|
||||||
int noy = goy;
|
|
||||||
int ntx = gtx;
|
|
||||||
int nty = gty;
|
|
||||||
byte nsweo = getNsweNearestOriginal(gox, goy, goz);
|
|
||||||
byte nswet = getNsweNearestOriginal(gtx, gty, gtz);
|
|
||||||
|
|
||||||
// loop
|
|
||||||
ABlock block;
|
|
||||||
int index;
|
|
||||||
for (int i = 0; i < ((dm + 1) / 2); i++)
|
|
||||||
{
|
|
||||||
// dropDebugItem(57, 0, new GeoLocation(gox, goy, goz)); // antidote
|
|
||||||
// dropDebugItem(1831, 0, new GeoLocation(gtx, gty, gtz)); // adena
|
|
||||||
|
|
||||||
// reset direction flag
|
|
||||||
diro = 0;
|
|
||||||
dirt = 0;
|
|
||||||
|
|
||||||
// calculate next point coordinates
|
|
||||||
int e2 = 2 * d;
|
|
||||||
if ((e2 > -dy) && (e2 < dx))
|
|
||||||
{
|
|
||||||
// calculate next point XY coordinates
|
|
||||||
d -= dy;
|
|
||||||
d += dx;
|
|
||||||
nox += sx;
|
|
||||||
ntx -= sx;
|
|
||||||
noy += sy;
|
|
||||||
nty -= sy;
|
|
||||||
diro |= diroxy;
|
|
||||||
dirt |= dirtxy;
|
|
||||||
}
|
|
||||||
else if (e2 > -dy)
|
|
||||||
{
|
|
||||||
// calculate next point X coordinate
|
|
||||||
d -= dy;
|
|
||||||
nox += sx;
|
|
||||||
ntx -= sx;
|
|
||||||
diro |= dirox;
|
|
||||||
dirt |= dirtx;
|
|
||||||
}
|
|
||||||
else if (e2 < dx)
|
|
||||||
{
|
|
||||||
// calculate next point Y coordinate
|
|
||||||
d += dx;
|
|
||||||
noy += sy;
|
|
||||||
nty -= sy;
|
|
||||||
diro |= diroy;
|
|
||||||
dirt |= dirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// get block of the next cell
|
|
||||||
block = getBlock(nox, noy);
|
|
||||||
|
|
||||||
// get index of particular layer, based on movement conditions
|
|
||||||
if ((nsweo & diro) == 0)
|
|
||||||
{
|
|
||||||
index = block.getIndexAboveOriginal(nox, noy, goz - GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = block.getIndexBelowOriginal(nox, noy, goz + GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layer does not exist, return
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer and next line of sight Z coordinate
|
|
||||||
goz = block.getHeightOriginal(index);
|
|
||||||
losoz += dz;
|
|
||||||
|
|
||||||
// perform line of sight check, return when fails
|
|
||||||
if ((goz - losoz) > Config.MAX_OBSTACLE_HEIGHT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer nswe
|
|
||||||
nsweo = block.getNsweOriginal(index);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// get block of the next cell
|
|
||||||
block = getBlock(ntx, nty);
|
|
||||||
|
|
||||||
// get index of particular layer, based on movement conditions
|
|
||||||
if ((nswet & dirt) == 0)
|
|
||||||
{
|
|
||||||
index = block.getIndexAboveOriginal(ntx, nty, gtz - GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = block.getIndexBelowOriginal(ntx, nty, gtz + GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layer does not exist, return
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer and next line of sight Z coordinate
|
|
||||||
gtz = block.getHeightOriginal(index);
|
|
||||||
lostz -= dz;
|
|
||||||
|
|
||||||
// perform line of sight check, return when fails
|
|
||||||
if ((gtz - lostz) > Config.MAX_OBSTACLE_HEIGHT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer nswe
|
|
||||||
nswet = block.getNsweOriginal(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update coords
|
|
||||||
gox = nox;
|
|
||||||
goy = noy;
|
|
||||||
gtx = ntx;
|
|
||||||
gty = nty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when iteration is completed, compare final Z coordinates
|
|
||||||
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check movement from coordinates to coordinates.
|
* Check movement from coordinates to coordinates.
|
||||||
* @param ox : origin X coordinate
|
* @param ox : origin X coordinate
|
||||||
|
@@ -958,7 +958,6 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
|
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
|
||||||
if (isFollowing())
|
if (isFollowing())
|
||||||
{
|
{
|
||||||
|
|
||||||
// allow larger hit range when the target is moving (check is run only once per second)
|
// allow larger hit range when the target is moving (check is run only once per second)
|
||||||
if (!_actor.isInsideRadius(target, offset + 100, false, false))
|
if (!_actor.isInsideRadius(target, offset + 100, false, false))
|
||||||
{
|
{
|
||||||
@@ -981,14 +980,11 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// while flying there is no move to cast
|
// while flying there is no move to cast
|
||||||
if (_actor.getAI().getIntention() == AI_INTENTION_CAST)
|
if (_actor.getAI().getIntention() == AI_INTENTION_CAST && _actor.isPlayer() && _actor.checkTransformed(transform -> !transform.isCombat()))
|
||||||
{
|
{
|
||||||
if (_actor.checkTransformed(transform -> !transform.isCombat()))
|
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_STOPPED);
|
||||||
{
|
_actor.sendPacket(ActionFailed.STATIC_PACKET);
|
||||||
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_STOPPED);
|
return true;
|
||||||
_actor.sendPacket(ActionFailed.STATIC_PACKET);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
|
// If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
|
||||||
|
@@ -35,13 +35,11 @@ import com.l2jmobius.gameserver.geoengine.geodata.BlockNull;
|
|||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.IGeoObject;
|
|
||||||
import com.l2jmobius.gameserver.instancemanager.WarpedSpaceManager;
|
import com.l2jmobius.gameserver.instancemanager.WarpedSpaceManager;
|
||||||
import com.l2jmobius.gameserver.model.L2Object;
|
import com.l2jmobius.gameserver.model.L2Object;
|
||||||
import com.l2jmobius.gameserver.model.L2World;
|
import com.l2jmobius.gameserver.model.L2World;
|
||||||
import com.l2jmobius.gameserver.model.Location;
|
import com.l2jmobius.gameserver.model.Location;
|
||||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
|
|
||||||
import com.l2jmobius.gameserver.model.instancezone.Instance;
|
import com.l2jmobius.gameserver.model.instancezone.Instance;
|
||||||
import com.l2jmobius.gameserver.util.MathUtil;
|
import com.l2jmobius.gameserver.util.MathUtil;
|
||||||
|
|
||||||
@@ -317,20 +315,6 @@ public class GeoEngine
|
|||||||
return block != null ? block.getHeightNearest(geoX, geoY, worldZ) : (short) worldZ;
|
return block != null ? block.getHeightNearest(geoX, geoY, worldZ) : (short) worldZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the height of cell, which is closest to given coordinates.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.
|
|
||||||
* @param geoX : Cell geodata X coordinate.
|
|
||||||
* @param geoY : Cell geodata Y coordinate.
|
|
||||||
* @param worldZ : Cell world Z coordinate.
|
|
||||||
* @return short : Cell geodata Z coordinate, closest to given coordinates.
|
|
||||||
*/
|
|
||||||
private final short getHeightNearestOriginal(int geoX, int geoY, int worldZ)
|
|
||||||
{
|
|
||||||
final ABlock block = getBlock(geoX, geoY);
|
|
||||||
return block != null ? block.getHeightNearestOriginal(geoX, geoY, worldZ) : (short) worldZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the NSWE flag byte of cell, which is closes to given coordinates.
|
* Returns the NSWE flag byte of cell, which is closes to given coordinates.
|
||||||
* @param geoX : Cell geodata X coordinate.
|
* @param geoX : Cell geodata X coordinate.
|
||||||
@@ -344,20 +328,6 @@ public class GeoEngine
|
|||||||
return block != null ? block.getNsweNearest(geoX, geoY, worldZ) : (byte) 0xFF;
|
return block != null ? block.getNsweNearest(geoX, geoY, worldZ) : (byte) 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the NSWE flag byte of cell, which is closes to given coordinates.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.
|
|
||||||
* @param geoX : Cell geodata X coordinate.
|
|
||||||
* @param geoY : Cell geodata Y coordinate.
|
|
||||||
* @param worldZ : Cell world Z coordinate.
|
|
||||||
* @return short : Cell NSWE flag byte coordinate, closest to given coordinates.
|
|
||||||
*/
|
|
||||||
private final byte getNsweNearestOriginal(int geoX, int geoY, int worldZ)
|
|
||||||
{
|
|
||||||
final ABlock block = getBlock(geoX, geoY);
|
|
||||||
return block != null ? block.getNsweNearestOriginal(geoX, geoY, worldZ) : (byte) 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if world coordinates has geo.
|
* Check if world coordinates has geo.
|
||||||
* @param worldX : World X
|
* @param worldX : World X
|
||||||
@@ -391,6 +361,11 @@ public class GeoEngine
|
|||||||
*/
|
*/
|
||||||
public final boolean canSeeTarget(L2Object origin, L2Object target)
|
public final boolean canSeeTarget(L2Object origin, L2Object target)
|
||||||
{
|
{
|
||||||
|
if (target.isDoor())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// get origin and target world coordinates
|
// get origin and target world coordinates
|
||||||
final int ox = origin.getX();
|
final int ox = origin.getX();
|
||||||
final int oy = origin.getY();
|
final int oy = origin.getY();
|
||||||
@@ -399,7 +374,7 @@ public class GeoEngine
|
|||||||
final int ty = target.getY();
|
final int ty = target.getY();
|
||||||
final int tz = target.getZ();
|
final int tz = target.getZ();
|
||||||
|
|
||||||
if (!target.isDoor() && DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), false))
|
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -430,8 +405,7 @@ public class GeoEngine
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean door = target.isDoor();
|
final short gtz = getHeightNearest(gtx, gty, tz);
|
||||||
final short gtz = door ? getHeightNearestOriginal(gtx, gty, tz) : getHeightNearest(gtx, gty, tz);
|
|
||||||
|
|
||||||
// origin and target coordinates are same
|
// origin and target coordinates are same
|
||||||
if ((gox == gtx) && (goy == gty))
|
if ((gox == gtx) && (goy == gty))
|
||||||
@@ -453,7 +427,7 @@ public class GeoEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
// perform geodata check
|
// perform geodata check
|
||||||
return door ? checkSeeOriginal(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld()) : checkSee(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld());
|
return checkSee(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -472,7 +446,7 @@ public class GeoEngine
|
|||||||
final int ty = position.getY();
|
final int ty = position.getY();
|
||||||
final int tz = position.getZ();
|
final int tz = position.getZ();
|
||||||
|
|
||||||
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), false))
|
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -703,189 +677,6 @@ public class GeoEngine
|
|||||||
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple check for origin to target visibility.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.<br>
|
|
||||||
* NOTE: When two doors close between each other and the LoS check of one doors is performed through another door, result will not be accurate (the other door are skipped).
|
|
||||||
* @param gox : origin X geodata coordinate
|
|
||||||
* @param goy : origin Y geodata coordinate
|
|
||||||
* @param goz : origin Z geodata coordinate
|
|
||||||
* @param oheight : origin height (if instance of {@link Character})
|
|
||||||
* @param gtx : target X geodata coordinate
|
|
||||||
* @param gty : target Y geodata coordinate
|
|
||||||
* @param gtz : target Z geodata coordinate
|
|
||||||
* @param theight : target height (if instance of {@link Character} or {@link L2DoorInstance})
|
|
||||||
* @param instance
|
|
||||||
* @return {@code boolean} : True, when target can be seen.
|
|
||||||
*/
|
|
||||||
private final boolean checkSeeOriginal(int gox, int goy, int goz, double oheight, int gtx, int gty, int gtz, double theight, Instance instance)
|
|
||||||
{
|
|
||||||
// get line of sight Z coordinates
|
|
||||||
double losoz = goz + ((oheight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
|
||||||
double lostz = gtz + ((theight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
|
||||||
|
|
||||||
// get X delta and signum
|
|
||||||
final int dx = Math.abs(gtx - gox);
|
|
||||||
final int sx = gox < gtx ? 1 : -1;
|
|
||||||
final byte dirox = sx > 0 ? GeoStructure.CELL_FLAG_E : GeoStructure.CELL_FLAG_W;
|
|
||||||
final byte dirtx = sx > 0 ? GeoStructure.CELL_FLAG_W : GeoStructure.CELL_FLAG_E;
|
|
||||||
|
|
||||||
// get Y delta and signum
|
|
||||||
final int dy = Math.abs(gty - goy);
|
|
||||||
final int sy = goy < gty ? 1 : -1;
|
|
||||||
final byte diroy = sy > 0 ? GeoStructure.CELL_FLAG_S : GeoStructure.CELL_FLAG_N;
|
|
||||||
final byte dirty = sy > 0 ? GeoStructure.CELL_FLAG_N : GeoStructure.CELL_FLAG_S;
|
|
||||||
|
|
||||||
// get Z delta
|
|
||||||
final int dm = Math.max(dx, dy);
|
|
||||||
final double dz = (lostz - losoz) / dm;
|
|
||||||
|
|
||||||
// get direction flag for diagonal movement
|
|
||||||
final byte diroxy = getDirXY(dirox, diroy);
|
|
||||||
final byte dirtxy = getDirXY(dirtx, dirty);
|
|
||||||
|
|
||||||
// delta, determines axis to move on (+..X axis, -..Y axis)
|
|
||||||
int d = dx - dy;
|
|
||||||
|
|
||||||
// NSWE direction of movement
|
|
||||||
byte diro;
|
|
||||||
byte dirt;
|
|
||||||
|
|
||||||
// clearDebugItems();
|
|
||||||
// dropDebugItem(728, 0, new GeoLocation(gox, goy, goz)); // blue potion
|
|
||||||
// dropDebugItem(728, 0, new GeoLocation(gtx, gty, gtz)); // blue potion
|
|
||||||
|
|
||||||
// initialize node values
|
|
||||||
int nox = gox;
|
|
||||||
int noy = goy;
|
|
||||||
int ntx = gtx;
|
|
||||||
int nty = gty;
|
|
||||||
byte nsweo = getNsweNearestOriginal(gox, goy, goz);
|
|
||||||
byte nswet = getNsweNearestOriginal(gtx, gty, gtz);
|
|
||||||
|
|
||||||
// loop
|
|
||||||
ABlock block;
|
|
||||||
int index;
|
|
||||||
for (int i = 0; i < ((dm + 1) / 2); i++)
|
|
||||||
{
|
|
||||||
// dropDebugItem(57, 0, new GeoLocation(gox, goy, goz)); // antidote
|
|
||||||
// dropDebugItem(1831, 0, new GeoLocation(gtx, gty, gtz)); // adena
|
|
||||||
|
|
||||||
// reset direction flag
|
|
||||||
diro = 0;
|
|
||||||
dirt = 0;
|
|
||||||
|
|
||||||
// calculate next point coordinates
|
|
||||||
int e2 = 2 * d;
|
|
||||||
if ((e2 > -dy) && (e2 < dx))
|
|
||||||
{
|
|
||||||
// calculate next point XY coordinates
|
|
||||||
d -= dy;
|
|
||||||
d += dx;
|
|
||||||
nox += sx;
|
|
||||||
ntx -= sx;
|
|
||||||
noy += sy;
|
|
||||||
nty -= sy;
|
|
||||||
diro |= diroxy;
|
|
||||||
dirt |= dirtxy;
|
|
||||||
}
|
|
||||||
else if (e2 > -dy)
|
|
||||||
{
|
|
||||||
// calculate next point X coordinate
|
|
||||||
d -= dy;
|
|
||||||
nox += sx;
|
|
||||||
ntx -= sx;
|
|
||||||
diro |= dirox;
|
|
||||||
dirt |= dirtx;
|
|
||||||
}
|
|
||||||
else if (e2 < dx)
|
|
||||||
{
|
|
||||||
// calculate next point Y coordinate
|
|
||||||
d += dx;
|
|
||||||
noy += sy;
|
|
||||||
nty -= sy;
|
|
||||||
diro |= diroy;
|
|
||||||
dirt |= dirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// get block of the next cell
|
|
||||||
block = getBlock(nox, noy);
|
|
||||||
|
|
||||||
// get index of particular layer, based on movement conditions
|
|
||||||
if ((nsweo & diro) == 0)
|
|
||||||
{
|
|
||||||
index = block.getIndexAboveOriginal(nox, noy, goz - GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = block.getIndexBelowOriginal(nox, noy, goz + GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layer does not exist, return
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer and next line of sight Z coordinate
|
|
||||||
goz = block.getHeightOriginal(index);
|
|
||||||
losoz += dz;
|
|
||||||
|
|
||||||
// perform line of sight check, return when fails
|
|
||||||
if ((goz - losoz) > Config.MAX_OBSTACLE_HEIGHT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer nswe
|
|
||||||
nsweo = block.getNsweOriginal(index);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// get block of the next cell
|
|
||||||
block = getBlock(ntx, nty);
|
|
||||||
|
|
||||||
// get index of particular layer, based on movement conditions
|
|
||||||
if ((nswet & dirt) == 0)
|
|
||||||
{
|
|
||||||
index = block.getIndexAboveOriginal(ntx, nty, gtz - GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = block.getIndexBelowOriginal(ntx, nty, gtz + GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layer does not exist, return
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer and next line of sight Z coordinate
|
|
||||||
gtz = block.getHeightOriginal(index);
|
|
||||||
lostz -= dz;
|
|
||||||
|
|
||||||
// perform line of sight check, return when fails
|
|
||||||
if ((gtz - lostz) > Config.MAX_OBSTACLE_HEIGHT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer nswe
|
|
||||||
nswet = block.getNsweOriginal(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update coords
|
|
||||||
gox = nox;
|
|
||||||
goy = noy;
|
|
||||||
gtx = ntx;
|
|
||||||
gty = nty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when iteration is completed, compare final Z coordinates
|
|
||||||
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check movement from coordinates to coordinates.
|
* Check movement from coordinates to coordinates.
|
||||||
* @param ox : origin X coordinate
|
* @param ox : origin X coordinate
|
||||||
|
@@ -42,7 +42,6 @@ import com.l2jmobius.gameserver.model.Location;
|
|||||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
|
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||||
import com.l2jmobius.gameserver.model.actor.templates.L2NpcTemplate;
|
import com.l2jmobius.gameserver.model.actor.templates.L2NpcTemplate;
|
||||||
import com.l2jmobius.gameserver.model.effects.L2EffectType;
|
import com.l2jmobius.gameserver.model.effects.L2EffectType;
|
||||||
@@ -999,36 +998,12 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
}
|
}
|
||||||
|
|
||||||
offset += _actor.getTemplate().getCollisionRadius();
|
offset += _actor.getTemplate().getCollisionRadius();
|
||||||
if (target instanceof L2Character)
|
if (target.isCharacter())
|
||||||
{
|
{
|
||||||
offset += ((L2Character) target).getTemplate().getCollisionRadius();
|
offset += ((L2Character) target).getTemplate().getCollisionRadius();
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean needToMove;
|
if (!_actor.isInsideRadius(target, offset, false, false))
|
||||||
|
|
||||||
if (target.isDoor())
|
|
||||||
{
|
|
||||||
final L2DoorInstance dor = (L2DoorInstance) target;
|
|
||||||
int xPoint = 0;
|
|
||||||
int yPoint = 0;
|
|
||||||
for (int i : dor.getTemplate().getNodeX())
|
|
||||||
{
|
|
||||||
xPoint += i;
|
|
||||||
}
|
|
||||||
for (int i : dor.getTemplate().getNodeY())
|
|
||||||
{
|
|
||||||
yPoint += i;
|
|
||||||
}
|
|
||||||
xPoint /= 4;
|
|
||||||
yPoint /= 4;
|
|
||||||
needToMove = !_actor.isInsideRadius(xPoint, yPoint, dor.getTemplate().getNodeZ(), offset, false, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
needToMove = !_actor.isInsideRadius(target, offset, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needToMove)
|
|
||||||
{
|
{
|
||||||
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
|
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
|
||||||
if (getFollowTarget() != null)
|
if (getFollowTarget() != null)
|
||||||
@@ -1042,7 +1017,7 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_actor.isMovementDisabled())
|
if (_actor.isMovementDisabled() || (_actor.getMoveSpeed() <= 0))
|
||||||
{
|
{
|
||||||
// If player is trying attack target but he cannot move to attack target
|
// If player is trying attack target but he cannot move to attack target
|
||||||
// change his intention to idle
|
// change his intention to idle
|
||||||
@@ -1055,7 +1030,7 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// while flying there is no move to cast
|
// while flying there is no move to cast
|
||||||
if ((_actor.getAI().getIntention() == AI_INTENTION_CAST) && (_actor instanceof L2PcInstance) && _actor.isTransformed() && !_actor.getTransformation().isCombat())
|
if ((_actor.getAI().getIntention() == AI_INTENTION_CAST) && _actor.isPlayer() && _actor.isTransformed() && !_actor.getTransformation().isCombat())
|
||||||
{
|
{
|
||||||
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_STOPPED);
|
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_STOPPED);
|
||||||
_actor.sendPacket(ActionFailed.STATIC_PACKET);
|
_actor.sendPacket(ActionFailed.STATIC_PACKET);
|
||||||
@@ -1069,7 +1044,7 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
}
|
}
|
||||||
|
|
||||||
stopFollow();
|
stopFollow();
|
||||||
if ((target instanceof L2Character) && !(target instanceof L2DoorInstance))
|
if (target.isCharacter() && !target.isDoor())
|
||||||
{
|
{
|
||||||
if (((L2Character) target).isMoving())
|
if (((L2Character) target).isMoving())
|
||||||
{
|
{
|
||||||
|
@@ -35,12 +35,10 @@ import com.l2jmobius.gameserver.geoengine.geodata.BlockNull;
|
|||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.IGeoObject;
|
|
||||||
import com.l2jmobius.gameserver.model.L2Object;
|
import com.l2jmobius.gameserver.model.L2Object;
|
||||||
import com.l2jmobius.gameserver.model.L2World;
|
import com.l2jmobius.gameserver.model.L2World;
|
||||||
import com.l2jmobius.gameserver.model.Location;
|
import com.l2jmobius.gameserver.model.Location;
|
||||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
|
|
||||||
import com.l2jmobius.gameserver.util.MathUtil;
|
import com.l2jmobius.gameserver.util.MathUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -271,7 +269,7 @@ public class GeoEngine
|
|||||||
* @param geoY : Geodata Y
|
* @param geoY : Geodata Y
|
||||||
* @return {@link ABlock} : Block of geodata.
|
* @return {@link ABlock} : Block of geodata.
|
||||||
*/
|
*/
|
||||||
public final ABlock getBlock(int geoX, int geoY)
|
private final ABlock getBlock(int geoX, int geoY)
|
||||||
{
|
{
|
||||||
final int x = geoX / GeoStructure.BLOCK_CELLS_X;
|
final int x = geoX / GeoStructure.BLOCK_CELLS_X;
|
||||||
final int y = geoY / GeoStructure.BLOCK_CELLS_Y;
|
final int y = geoY / GeoStructure.BLOCK_CELLS_Y;
|
||||||
@@ -315,20 +313,6 @@ public class GeoEngine
|
|||||||
return block != null ? block.getHeightNearest(geoX, geoY, worldZ) : (short) worldZ;
|
return block != null ? block.getHeightNearest(geoX, geoY, worldZ) : (short) worldZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the height of cell, which is closest to given coordinates.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.
|
|
||||||
* @param geoX : Cell geodata X coordinate.
|
|
||||||
* @param geoY : Cell geodata Y coordinate.
|
|
||||||
* @param worldZ : Cell world Z coordinate.
|
|
||||||
* @return short : Cell geodata Z coordinate, closest to given coordinates.
|
|
||||||
*/
|
|
||||||
public final short getHeightNearestOriginal(int geoX, int geoY, int worldZ)
|
|
||||||
{
|
|
||||||
final ABlock block = getBlock(geoX, geoY);
|
|
||||||
return block != null ? block.getHeightNearestOriginal(geoX, geoY, worldZ) : (short) worldZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the NSWE flag byte of cell, which is closes to given coordinates.
|
* Returns the NSWE flag byte of cell, which is closes to given coordinates.
|
||||||
* @param geoX : Cell geodata X coordinate.
|
* @param geoX : Cell geodata X coordinate.
|
||||||
@@ -342,20 +326,6 @@ public class GeoEngine
|
|||||||
return block != null ? block.getNsweNearest(geoX, geoY, worldZ) : (byte) 0xFF;
|
return block != null ? block.getNsweNearest(geoX, geoY, worldZ) : (byte) 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the NSWE flag byte of cell, which is closes to given coordinates.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.
|
|
||||||
* @param geoX : Cell geodata X coordinate.
|
|
||||||
* @param geoY : Cell geodata Y coordinate.
|
|
||||||
* @param worldZ : Cell world Z coordinate.
|
|
||||||
* @return short : Cell NSWE flag byte coordinate, closest to given coordinates.
|
|
||||||
*/
|
|
||||||
public final byte getNsweNearestOriginal(int geoX, int geoY, int worldZ)
|
|
||||||
{
|
|
||||||
final ABlock block = getBlock(geoX, geoY);
|
|
||||||
return block != null ? block.getNsweNearestOriginal(geoX, geoY, worldZ) : (byte) 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if world coordinates has geo.
|
* Check if world coordinates has geo.
|
||||||
* @param worldX : World X
|
* @param worldX : World X
|
||||||
@@ -389,6 +359,11 @@ public class GeoEngine
|
|||||||
*/
|
*/
|
||||||
public final boolean canSeeTarget(L2Object origin, L2Object target)
|
public final boolean canSeeTarget(L2Object origin, L2Object target)
|
||||||
{
|
{
|
||||||
|
if (target.isDoor())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// get origin and target world coordinates
|
// get origin and target world coordinates
|
||||||
final int ox = origin.getX();
|
final int ox = origin.getX();
|
||||||
final int oy = origin.getY();
|
final int oy = origin.getY();
|
||||||
@@ -397,7 +372,7 @@ public class GeoEngine
|
|||||||
final int ty = target.getY();
|
final int ty = target.getY();
|
||||||
final int tz = target.getZ();
|
final int tz = target.getZ();
|
||||||
|
|
||||||
if (!target.isDoor() && DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceId(), false))
|
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceId(), true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -424,8 +399,7 @@ public class GeoEngine
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean door = target.isDoor();
|
final short gtz = getHeightNearest(gtx, gty, tz);
|
||||||
final short gtz = door ? getHeightNearestOriginal(gtx, gty, tz) : getHeightNearest(gtx, gty, tz);
|
|
||||||
|
|
||||||
// origin and target coordinates are same
|
// origin and target coordinates are same
|
||||||
if ((gox == gtx) && (goy == gty))
|
if ((gox == gtx) && (goy == gty))
|
||||||
@@ -447,7 +421,7 @@ public class GeoEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
// perform geodata check
|
// perform geodata check
|
||||||
return door ? checkSeeOriginal(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceId()) : checkSee(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceId());
|
return checkSee(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -466,7 +440,7 @@ public class GeoEngine
|
|||||||
final int ty = position.getY();
|
final int ty = position.getY();
|
||||||
final int tz = position.getZ();
|
final int tz = position.getZ();
|
||||||
|
|
||||||
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceId(), false))
|
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceId(), true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -525,7 +499,7 @@ public class GeoEngine
|
|||||||
* @param instanceId
|
* @param instanceId
|
||||||
* @return {@code boolean} : True, when target can be seen.
|
* @return {@code boolean} : True, when target can be seen.
|
||||||
*/
|
*/
|
||||||
protected final boolean checkSee(int gox, int goy, int goz, double oheight, int gtx, int gty, int gtz, double theight, int instanceId)
|
private final boolean checkSee(int gox, int goy, int goz, double oheight, int gtx, int gty, int gtz, double theight, int instanceId)
|
||||||
{
|
{
|
||||||
// get line of sight Z coordinates
|
// get line of sight Z coordinates
|
||||||
double losoz = goz + ((oheight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
double losoz = goz + ((oheight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
||||||
@@ -693,189 +667,6 @@ public class GeoEngine
|
|||||||
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple check for origin to target visibility.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.<br>
|
|
||||||
* NOTE: When two doors close between each other and the LoS check of one doors is performed through another door, result will not be accurate (the other door are skipped).
|
|
||||||
* @param gox : origin X geodata coordinate
|
|
||||||
* @param goy : origin Y geodata coordinate
|
|
||||||
* @param goz : origin Z geodata coordinate
|
|
||||||
* @param oheight : origin height (if instance of {@link Character})
|
|
||||||
* @param gtx : target X geodata coordinate
|
|
||||||
* @param gty : target Y geodata coordinate
|
|
||||||
* @param gtz : target Z geodata coordinate
|
|
||||||
* @param theight : target height (if instance of {@link Character} or {@link L2DoorInstance})
|
|
||||||
* @param instanceId
|
|
||||||
* @return {@code boolean} : True, when target can be seen.
|
|
||||||
*/
|
|
||||||
protected final boolean checkSeeOriginal(int gox, int goy, int goz, double oheight, int gtx, int gty, int gtz, double theight, int instanceId)
|
|
||||||
{
|
|
||||||
// get line of sight Z coordinates
|
|
||||||
double losoz = goz + ((oheight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
|
||||||
double lostz = gtz + ((theight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
|
||||||
|
|
||||||
// get X delta and signum
|
|
||||||
final int dx = Math.abs(gtx - gox);
|
|
||||||
final int sx = gox < gtx ? 1 : -1;
|
|
||||||
final byte dirox = sx > 0 ? GeoStructure.CELL_FLAG_E : GeoStructure.CELL_FLAG_W;
|
|
||||||
final byte dirtx = sx > 0 ? GeoStructure.CELL_FLAG_W : GeoStructure.CELL_FLAG_E;
|
|
||||||
|
|
||||||
// get Y delta and signum
|
|
||||||
final int dy = Math.abs(gty - goy);
|
|
||||||
final int sy = goy < gty ? 1 : -1;
|
|
||||||
final byte diroy = sy > 0 ? GeoStructure.CELL_FLAG_S : GeoStructure.CELL_FLAG_N;
|
|
||||||
final byte dirty = sy > 0 ? GeoStructure.CELL_FLAG_N : GeoStructure.CELL_FLAG_S;
|
|
||||||
|
|
||||||
// get Z delta
|
|
||||||
final int dm = Math.max(dx, dy);
|
|
||||||
final double dz = (lostz - losoz) / dm;
|
|
||||||
|
|
||||||
// get direction flag for diagonal movement
|
|
||||||
final byte diroxy = getDirXY(dirox, diroy);
|
|
||||||
final byte dirtxy = getDirXY(dirtx, dirty);
|
|
||||||
|
|
||||||
// delta, determines axis to move on (+..X axis, -..Y axis)
|
|
||||||
int d = dx - dy;
|
|
||||||
|
|
||||||
// NSWE direction of movement
|
|
||||||
byte diro;
|
|
||||||
byte dirt;
|
|
||||||
|
|
||||||
// clearDebugItems();
|
|
||||||
// dropDebugItem(728, 0, new GeoLocation(gox, goy, goz)); // blue potion
|
|
||||||
// dropDebugItem(728, 0, new GeoLocation(gtx, gty, gtz)); // blue potion
|
|
||||||
|
|
||||||
// initialize node values
|
|
||||||
int nox = gox;
|
|
||||||
int noy = goy;
|
|
||||||
int ntx = gtx;
|
|
||||||
int nty = gty;
|
|
||||||
byte nsweo = getNsweNearestOriginal(gox, goy, goz);
|
|
||||||
byte nswet = getNsweNearestOriginal(gtx, gty, gtz);
|
|
||||||
|
|
||||||
// loop
|
|
||||||
ABlock block;
|
|
||||||
int index;
|
|
||||||
for (int i = 0; i < ((dm + 1) / 2); i++)
|
|
||||||
{
|
|
||||||
// dropDebugItem(57, 0, new GeoLocation(gox, goy, goz)); // antidote
|
|
||||||
// dropDebugItem(1831, 0, new GeoLocation(gtx, gty, gtz)); // adena
|
|
||||||
|
|
||||||
// reset direction flag
|
|
||||||
diro = 0;
|
|
||||||
dirt = 0;
|
|
||||||
|
|
||||||
// calculate next point coordinates
|
|
||||||
int e2 = 2 * d;
|
|
||||||
if ((e2 > -dy) && (e2 < dx))
|
|
||||||
{
|
|
||||||
// calculate next point XY coordinates
|
|
||||||
d -= dy;
|
|
||||||
d += dx;
|
|
||||||
nox += sx;
|
|
||||||
ntx -= sx;
|
|
||||||
noy += sy;
|
|
||||||
nty -= sy;
|
|
||||||
diro |= diroxy;
|
|
||||||
dirt |= dirtxy;
|
|
||||||
}
|
|
||||||
else if (e2 > -dy)
|
|
||||||
{
|
|
||||||
// calculate next point X coordinate
|
|
||||||
d -= dy;
|
|
||||||
nox += sx;
|
|
||||||
ntx -= sx;
|
|
||||||
diro |= dirox;
|
|
||||||
dirt |= dirtx;
|
|
||||||
}
|
|
||||||
else if (e2 < dx)
|
|
||||||
{
|
|
||||||
// calculate next point Y coordinate
|
|
||||||
d += dx;
|
|
||||||
noy += sy;
|
|
||||||
nty -= sy;
|
|
||||||
diro |= diroy;
|
|
||||||
dirt |= dirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// get block of the next cell
|
|
||||||
block = getBlock(nox, noy);
|
|
||||||
|
|
||||||
// get index of particular layer, based on movement conditions
|
|
||||||
if ((nsweo & diro) == 0)
|
|
||||||
{
|
|
||||||
index = block.getIndexAboveOriginal(nox, noy, goz - GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = block.getIndexBelowOriginal(nox, noy, goz + GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layer does not exist, return
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer and next line of sight Z coordinate
|
|
||||||
goz = block.getHeightOriginal(index);
|
|
||||||
losoz += dz;
|
|
||||||
|
|
||||||
// perform line of sight check, return when fails
|
|
||||||
if ((goz - losoz) > Config.MAX_OBSTACLE_HEIGHT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer nswe
|
|
||||||
nsweo = block.getNsweOriginal(index);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// get block of the next cell
|
|
||||||
block = getBlock(ntx, nty);
|
|
||||||
|
|
||||||
// get index of particular layer, based on movement conditions
|
|
||||||
if ((nswet & dirt) == 0)
|
|
||||||
{
|
|
||||||
index = block.getIndexAboveOriginal(ntx, nty, gtz - GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = block.getIndexBelowOriginal(ntx, nty, gtz + GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layer does not exist, return
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer and next line of sight Z coordinate
|
|
||||||
gtz = block.getHeightOriginal(index);
|
|
||||||
lostz -= dz;
|
|
||||||
|
|
||||||
// perform line of sight check, return when fails
|
|
||||||
if ((gtz - lostz) > Config.MAX_OBSTACLE_HEIGHT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer nswe
|
|
||||||
nswet = block.getNsweOriginal(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update coords
|
|
||||||
gox = nox;
|
|
||||||
goy = noy;
|
|
||||||
gtx = ntx;
|
|
||||||
gty = nty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when iteration is completed, compare final Z coordinates
|
|
||||||
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check movement from coordinates to coordinates.
|
* Check movement from coordinates to coordinates.
|
||||||
* @param ox : origin X coordinate
|
* @param ox : origin X coordinate
|
||||||
|
@@ -958,7 +958,6 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
|
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
|
||||||
if (isFollowing())
|
if (isFollowing())
|
||||||
{
|
{
|
||||||
|
|
||||||
// allow larger hit range when the target is moving (check is run only once per second)
|
// allow larger hit range when the target is moving (check is run only once per second)
|
||||||
if (!_actor.isInsideRadius(target, offset + 100, false, false))
|
if (!_actor.isInsideRadius(target, offset + 100, false, false))
|
||||||
{
|
{
|
||||||
@@ -981,14 +980,11 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// while flying there is no move to cast
|
// while flying there is no move to cast
|
||||||
if (_actor.getAI().getIntention() == AI_INTENTION_CAST)
|
if (_actor.getAI().getIntention() == AI_INTENTION_CAST && _actor.isPlayer() && _actor.checkTransformed(transform -> !transform.isCombat()))
|
||||||
{
|
{
|
||||||
if (_actor.checkTransformed(transform -> !transform.isCombat()))
|
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_CANCELLED);
|
||||||
{
|
_actor.sendPacket(ActionFailed.STATIC_PACKET);
|
||||||
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_CANCELLED);
|
return true;
|
||||||
_actor.sendPacket(ActionFailed.STATIC_PACKET);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
|
// If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
|
||||||
|
@@ -35,13 +35,11 @@ import com.l2jmobius.gameserver.geoengine.geodata.BlockNull;
|
|||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.IGeoObject;
|
|
||||||
import com.l2jmobius.gameserver.instancemanager.WarpedSpaceManager;
|
import com.l2jmobius.gameserver.instancemanager.WarpedSpaceManager;
|
||||||
import com.l2jmobius.gameserver.model.L2Object;
|
import com.l2jmobius.gameserver.model.L2Object;
|
||||||
import com.l2jmobius.gameserver.model.L2World;
|
import com.l2jmobius.gameserver.model.L2World;
|
||||||
import com.l2jmobius.gameserver.model.Location;
|
import com.l2jmobius.gameserver.model.Location;
|
||||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
|
|
||||||
import com.l2jmobius.gameserver.model.instancezone.Instance;
|
import com.l2jmobius.gameserver.model.instancezone.Instance;
|
||||||
import com.l2jmobius.gameserver.util.MathUtil;
|
import com.l2jmobius.gameserver.util.MathUtil;
|
||||||
|
|
||||||
@@ -317,20 +315,6 @@ public class GeoEngine
|
|||||||
return block != null ? block.getHeightNearest(geoX, geoY, worldZ) : (short) worldZ;
|
return block != null ? block.getHeightNearest(geoX, geoY, worldZ) : (short) worldZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the height of cell, which is closest to given coordinates.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.
|
|
||||||
* @param geoX : Cell geodata X coordinate.
|
|
||||||
* @param geoY : Cell geodata Y coordinate.
|
|
||||||
* @param worldZ : Cell world Z coordinate.
|
|
||||||
* @return short : Cell geodata Z coordinate, closest to given coordinates.
|
|
||||||
*/
|
|
||||||
private final short getHeightNearestOriginal(int geoX, int geoY, int worldZ)
|
|
||||||
{
|
|
||||||
final ABlock block = getBlock(geoX, geoY);
|
|
||||||
return block != null ? block.getHeightNearestOriginal(geoX, geoY, worldZ) : (short) worldZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the NSWE flag byte of cell, which is closes to given coordinates.
|
* Returns the NSWE flag byte of cell, which is closes to given coordinates.
|
||||||
* @param geoX : Cell geodata X coordinate.
|
* @param geoX : Cell geodata X coordinate.
|
||||||
@@ -344,20 +328,6 @@ public class GeoEngine
|
|||||||
return block != null ? block.getNsweNearest(geoX, geoY, worldZ) : (byte) 0xFF;
|
return block != null ? block.getNsweNearest(geoX, geoY, worldZ) : (byte) 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the NSWE flag byte of cell, which is closes to given coordinates.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.
|
|
||||||
* @param geoX : Cell geodata X coordinate.
|
|
||||||
* @param geoY : Cell geodata Y coordinate.
|
|
||||||
* @param worldZ : Cell world Z coordinate.
|
|
||||||
* @return short : Cell NSWE flag byte coordinate, closest to given coordinates.
|
|
||||||
*/
|
|
||||||
private final byte getNsweNearestOriginal(int geoX, int geoY, int worldZ)
|
|
||||||
{
|
|
||||||
final ABlock block = getBlock(geoX, geoY);
|
|
||||||
return block != null ? block.getNsweNearestOriginal(geoX, geoY, worldZ) : (byte) 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if world coordinates has geo.
|
* Check if world coordinates has geo.
|
||||||
* @param worldX : World X
|
* @param worldX : World X
|
||||||
@@ -391,6 +361,11 @@ public class GeoEngine
|
|||||||
*/
|
*/
|
||||||
public final boolean canSeeTarget(L2Object origin, L2Object target)
|
public final boolean canSeeTarget(L2Object origin, L2Object target)
|
||||||
{
|
{
|
||||||
|
if (target.isDoor())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// get origin and target world coordinates
|
// get origin and target world coordinates
|
||||||
final int ox = origin.getX();
|
final int ox = origin.getX();
|
||||||
final int oy = origin.getY();
|
final int oy = origin.getY();
|
||||||
@@ -399,7 +374,7 @@ public class GeoEngine
|
|||||||
final int ty = target.getY();
|
final int ty = target.getY();
|
||||||
final int tz = target.getZ();
|
final int tz = target.getZ();
|
||||||
|
|
||||||
if (!target.isDoor() && DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), false))
|
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -430,8 +405,7 @@ public class GeoEngine
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean door = target.isDoor();
|
final short gtz = getHeightNearest(gtx, gty, tz);
|
||||||
final short gtz = door ? getHeightNearestOriginal(gtx, gty, tz) : getHeightNearest(gtx, gty, tz);
|
|
||||||
|
|
||||||
// origin and target coordinates are same
|
// origin and target coordinates are same
|
||||||
if ((gox == gtx) && (goy == gty))
|
if ((gox == gtx) && (goy == gty))
|
||||||
@@ -453,7 +427,7 @@ public class GeoEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
// perform geodata check
|
// perform geodata check
|
||||||
return door ? checkSeeOriginal(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld()) : checkSee(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld());
|
return checkSee(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -472,7 +446,7 @@ public class GeoEngine
|
|||||||
final int ty = position.getY();
|
final int ty = position.getY();
|
||||||
final int tz = position.getZ();
|
final int tz = position.getZ();
|
||||||
|
|
||||||
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), false))
|
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -703,189 +677,6 @@ public class GeoEngine
|
|||||||
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple check for origin to target visibility.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.<br>
|
|
||||||
* NOTE: When two doors close between each other and the LoS check of one doors is performed through another door, result will not be accurate (the other door are skipped).
|
|
||||||
* @param gox : origin X geodata coordinate
|
|
||||||
* @param goy : origin Y geodata coordinate
|
|
||||||
* @param goz : origin Z geodata coordinate
|
|
||||||
* @param oheight : origin height (if instance of {@link Character})
|
|
||||||
* @param gtx : target X geodata coordinate
|
|
||||||
* @param gty : target Y geodata coordinate
|
|
||||||
* @param gtz : target Z geodata coordinate
|
|
||||||
* @param theight : target height (if instance of {@link Character} or {@link L2DoorInstance})
|
|
||||||
* @param instance
|
|
||||||
* @return {@code boolean} : True, when target can be seen.
|
|
||||||
*/
|
|
||||||
private final boolean checkSeeOriginal(int gox, int goy, int goz, double oheight, int gtx, int gty, int gtz, double theight, Instance instance)
|
|
||||||
{
|
|
||||||
// get line of sight Z coordinates
|
|
||||||
double losoz = goz + ((oheight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
|
||||||
double lostz = gtz + ((theight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
|
||||||
|
|
||||||
// get X delta and signum
|
|
||||||
final int dx = Math.abs(gtx - gox);
|
|
||||||
final int sx = gox < gtx ? 1 : -1;
|
|
||||||
final byte dirox = sx > 0 ? GeoStructure.CELL_FLAG_E : GeoStructure.CELL_FLAG_W;
|
|
||||||
final byte dirtx = sx > 0 ? GeoStructure.CELL_FLAG_W : GeoStructure.CELL_FLAG_E;
|
|
||||||
|
|
||||||
// get Y delta and signum
|
|
||||||
final int dy = Math.abs(gty - goy);
|
|
||||||
final int sy = goy < gty ? 1 : -1;
|
|
||||||
final byte diroy = sy > 0 ? GeoStructure.CELL_FLAG_S : GeoStructure.CELL_FLAG_N;
|
|
||||||
final byte dirty = sy > 0 ? GeoStructure.CELL_FLAG_N : GeoStructure.CELL_FLAG_S;
|
|
||||||
|
|
||||||
// get Z delta
|
|
||||||
final int dm = Math.max(dx, dy);
|
|
||||||
final double dz = (lostz - losoz) / dm;
|
|
||||||
|
|
||||||
// get direction flag for diagonal movement
|
|
||||||
final byte diroxy = getDirXY(dirox, diroy);
|
|
||||||
final byte dirtxy = getDirXY(dirtx, dirty);
|
|
||||||
|
|
||||||
// delta, determines axis to move on (+..X axis, -..Y axis)
|
|
||||||
int d = dx - dy;
|
|
||||||
|
|
||||||
// NSWE direction of movement
|
|
||||||
byte diro;
|
|
||||||
byte dirt;
|
|
||||||
|
|
||||||
// clearDebugItems();
|
|
||||||
// dropDebugItem(728, 0, new GeoLocation(gox, goy, goz)); // blue potion
|
|
||||||
// dropDebugItem(728, 0, new GeoLocation(gtx, gty, gtz)); // blue potion
|
|
||||||
|
|
||||||
// initialize node values
|
|
||||||
int nox = gox;
|
|
||||||
int noy = goy;
|
|
||||||
int ntx = gtx;
|
|
||||||
int nty = gty;
|
|
||||||
byte nsweo = getNsweNearestOriginal(gox, goy, goz);
|
|
||||||
byte nswet = getNsweNearestOriginal(gtx, gty, gtz);
|
|
||||||
|
|
||||||
// loop
|
|
||||||
ABlock block;
|
|
||||||
int index;
|
|
||||||
for (int i = 0; i < ((dm + 1) / 2); i++)
|
|
||||||
{
|
|
||||||
// dropDebugItem(57, 0, new GeoLocation(gox, goy, goz)); // antidote
|
|
||||||
// dropDebugItem(1831, 0, new GeoLocation(gtx, gty, gtz)); // adena
|
|
||||||
|
|
||||||
// reset direction flag
|
|
||||||
diro = 0;
|
|
||||||
dirt = 0;
|
|
||||||
|
|
||||||
// calculate next point coordinates
|
|
||||||
int e2 = 2 * d;
|
|
||||||
if ((e2 > -dy) && (e2 < dx))
|
|
||||||
{
|
|
||||||
// calculate next point XY coordinates
|
|
||||||
d -= dy;
|
|
||||||
d += dx;
|
|
||||||
nox += sx;
|
|
||||||
ntx -= sx;
|
|
||||||
noy += sy;
|
|
||||||
nty -= sy;
|
|
||||||
diro |= diroxy;
|
|
||||||
dirt |= dirtxy;
|
|
||||||
}
|
|
||||||
else if (e2 > -dy)
|
|
||||||
{
|
|
||||||
// calculate next point X coordinate
|
|
||||||
d -= dy;
|
|
||||||
nox += sx;
|
|
||||||
ntx -= sx;
|
|
||||||
diro |= dirox;
|
|
||||||
dirt |= dirtx;
|
|
||||||
}
|
|
||||||
else if (e2 < dx)
|
|
||||||
{
|
|
||||||
// calculate next point Y coordinate
|
|
||||||
d += dx;
|
|
||||||
noy += sy;
|
|
||||||
nty -= sy;
|
|
||||||
diro |= diroy;
|
|
||||||
dirt |= dirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// get block of the next cell
|
|
||||||
block = getBlock(nox, noy);
|
|
||||||
|
|
||||||
// get index of particular layer, based on movement conditions
|
|
||||||
if ((nsweo & diro) == 0)
|
|
||||||
{
|
|
||||||
index = block.getIndexAboveOriginal(nox, noy, goz - GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = block.getIndexBelowOriginal(nox, noy, goz + GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layer does not exist, return
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer and next line of sight Z coordinate
|
|
||||||
goz = block.getHeightOriginal(index);
|
|
||||||
losoz += dz;
|
|
||||||
|
|
||||||
// perform line of sight check, return when fails
|
|
||||||
if ((goz - losoz) > Config.MAX_OBSTACLE_HEIGHT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer nswe
|
|
||||||
nsweo = block.getNsweOriginal(index);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// get block of the next cell
|
|
||||||
block = getBlock(ntx, nty);
|
|
||||||
|
|
||||||
// get index of particular layer, based on movement conditions
|
|
||||||
if ((nswet & dirt) == 0)
|
|
||||||
{
|
|
||||||
index = block.getIndexAboveOriginal(ntx, nty, gtz - GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = block.getIndexBelowOriginal(ntx, nty, gtz + GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layer does not exist, return
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer and next line of sight Z coordinate
|
|
||||||
gtz = block.getHeightOriginal(index);
|
|
||||||
lostz -= dz;
|
|
||||||
|
|
||||||
// perform line of sight check, return when fails
|
|
||||||
if ((gtz - lostz) > Config.MAX_OBSTACLE_HEIGHT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer nswe
|
|
||||||
nswet = block.getNsweOriginal(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update coords
|
|
||||||
gox = nox;
|
|
||||||
goy = noy;
|
|
||||||
gtx = ntx;
|
|
||||||
gty = nty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when iteration is completed, compare final Z coordinates
|
|
||||||
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check movement from coordinates to coordinates.
|
* Check movement from coordinates to coordinates.
|
||||||
* @param ox : origin X coordinate
|
* @param ox : origin X coordinate
|
||||||
|
@@ -958,7 +958,6 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
|
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
|
||||||
if (isFollowing())
|
if (isFollowing())
|
||||||
{
|
{
|
||||||
|
|
||||||
// allow larger hit range when the target is moving (check is run only once per second)
|
// allow larger hit range when the target is moving (check is run only once per second)
|
||||||
if (!_actor.isInsideRadius(target, offset + 100, false, false))
|
if (!_actor.isInsideRadius(target, offset + 100, false, false))
|
||||||
{
|
{
|
||||||
@@ -981,14 +980,11 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// while flying there is no move to cast
|
// while flying there is no move to cast
|
||||||
if (_actor.getAI().getIntention() == AI_INTENTION_CAST)
|
if (_actor.getAI().getIntention() == AI_INTENTION_CAST && _actor.isPlayer() && _actor.checkTransformed(transform -> !transform.isCombat()))
|
||||||
{
|
{
|
||||||
if (_actor.checkTransformed(transform -> !transform.isCombat()))
|
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_CANCELLED);
|
||||||
{
|
_actor.sendPacket(ActionFailed.STATIC_PACKET);
|
||||||
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_CANCELLED);
|
return true;
|
||||||
_actor.sendPacket(ActionFailed.STATIC_PACKET);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
|
// If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
|
||||||
|
@@ -35,13 +35,11 @@ import com.l2jmobius.gameserver.geoengine.geodata.BlockNull;
|
|||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.IGeoObject;
|
|
||||||
import com.l2jmobius.gameserver.instancemanager.WarpedSpaceManager;
|
import com.l2jmobius.gameserver.instancemanager.WarpedSpaceManager;
|
||||||
import com.l2jmobius.gameserver.model.L2Object;
|
import com.l2jmobius.gameserver.model.L2Object;
|
||||||
import com.l2jmobius.gameserver.model.L2World;
|
import com.l2jmobius.gameserver.model.L2World;
|
||||||
import com.l2jmobius.gameserver.model.Location;
|
import com.l2jmobius.gameserver.model.Location;
|
||||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
|
|
||||||
import com.l2jmobius.gameserver.model.instancezone.Instance;
|
import com.l2jmobius.gameserver.model.instancezone.Instance;
|
||||||
import com.l2jmobius.gameserver.util.MathUtil;
|
import com.l2jmobius.gameserver.util.MathUtil;
|
||||||
|
|
||||||
@@ -317,20 +315,6 @@ public class GeoEngine
|
|||||||
return block != null ? block.getHeightNearest(geoX, geoY, worldZ) : (short) worldZ;
|
return block != null ? block.getHeightNearest(geoX, geoY, worldZ) : (short) worldZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the height of cell, which is closest to given coordinates.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.
|
|
||||||
* @param geoX : Cell geodata X coordinate.
|
|
||||||
* @param geoY : Cell geodata Y coordinate.
|
|
||||||
* @param worldZ : Cell world Z coordinate.
|
|
||||||
* @return short : Cell geodata Z coordinate, closest to given coordinates.
|
|
||||||
*/
|
|
||||||
private final short getHeightNearestOriginal(int geoX, int geoY, int worldZ)
|
|
||||||
{
|
|
||||||
final ABlock block = getBlock(geoX, geoY);
|
|
||||||
return block != null ? block.getHeightNearestOriginal(geoX, geoY, worldZ) : (short) worldZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the NSWE flag byte of cell, which is closes to given coordinates.
|
* Returns the NSWE flag byte of cell, which is closes to given coordinates.
|
||||||
* @param geoX : Cell geodata X coordinate.
|
* @param geoX : Cell geodata X coordinate.
|
||||||
@@ -344,20 +328,6 @@ public class GeoEngine
|
|||||||
return block != null ? block.getNsweNearest(geoX, geoY, worldZ) : (byte) 0xFF;
|
return block != null ? block.getNsweNearest(geoX, geoY, worldZ) : (byte) 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the NSWE flag byte of cell, which is closes to given coordinates.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.
|
|
||||||
* @param geoX : Cell geodata X coordinate.
|
|
||||||
* @param geoY : Cell geodata Y coordinate.
|
|
||||||
* @param worldZ : Cell world Z coordinate.
|
|
||||||
* @return short : Cell NSWE flag byte coordinate, closest to given coordinates.
|
|
||||||
*/
|
|
||||||
private final byte getNsweNearestOriginal(int geoX, int geoY, int worldZ)
|
|
||||||
{
|
|
||||||
final ABlock block = getBlock(geoX, geoY);
|
|
||||||
return block != null ? block.getNsweNearestOriginal(geoX, geoY, worldZ) : (byte) 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if world coordinates has geo.
|
* Check if world coordinates has geo.
|
||||||
* @param worldX : World X
|
* @param worldX : World X
|
||||||
@@ -391,6 +361,11 @@ public class GeoEngine
|
|||||||
*/
|
*/
|
||||||
public final boolean canSeeTarget(L2Object origin, L2Object target)
|
public final boolean canSeeTarget(L2Object origin, L2Object target)
|
||||||
{
|
{
|
||||||
|
if (target.isDoor())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// get origin and target world coordinates
|
// get origin and target world coordinates
|
||||||
final int ox = origin.getX();
|
final int ox = origin.getX();
|
||||||
final int oy = origin.getY();
|
final int oy = origin.getY();
|
||||||
@@ -399,7 +374,7 @@ public class GeoEngine
|
|||||||
final int ty = target.getY();
|
final int ty = target.getY();
|
||||||
final int tz = target.getZ();
|
final int tz = target.getZ();
|
||||||
|
|
||||||
if (!target.isDoor() && DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), false))
|
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -430,8 +405,7 @@ public class GeoEngine
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean door = target.isDoor();
|
final short gtz = getHeightNearest(gtx, gty, tz);
|
||||||
final short gtz = door ? getHeightNearestOriginal(gtx, gty, tz) : getHeightNearest(gtx, gty, tz);
|
|
||||||
|
|
||||||
// origin and target coordinates are same
|
// origin and target coordinates are same
|
||||||
if ((gox == gtx) && (goy == gty))
|
if ((gox == gtx) && (goy == gty))
|
||||||
@@ -453,7 +427,7 @@ public class GeoEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
// perform geodata check
|
// perform geodata check
|
||||||
return door ? checkSeeOriginal(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld()) : checkSee(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld());
|
return checkSee(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -472,7 +446,7 @@ public class GeoEngine
|
|||||||
final int ty = position.getY();
|
final int ty = position.getY();
|
||||||
final int tz = position.getZ();
|
final int tz = position.getZ();
|
||||||
|
|
||||||
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), false))
|
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -703,189 +677,6 @@ public class GeoEngine
|
|||||||
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple check for origin to target visibility.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.<br>
|
|
||||||
* NOTE: When two doors close between each other and the LoS check of one doors is performed through another door, result will not be accurate (the other door are skipped).
|
|
||||||
* @param gox : origin X geodata coordinate
|
|
||||||
* @param goy : origin Y geodata coordinate
|
|
||||||
* @param goz : origin Z geodata coordinate
|
|
||||||
* @param oheight : origin height (if instance of {@link Character})
|
|
||||||
* @param gtx : target X geodata coordinate
|
|
||||||
* @param gty : target Y geodata coordinate
|
|
||||||
* @param gtz : target Z geodata coordinate
|
|
||||||
* @param theight : target height (if instance of {@link Character} or {@link L2DoorInstance})
|
|
||||||
* @param instance
|
|
||||||
* @return {@code boolean} : True, when target can be seen.
|
|
||||||
*/
|
|
||||||
private final boolean checkSeeOriginal(int gox, int goy, int goz, double oheight, int gtx, int gty, int gtz, double theight, Instance instance)
|
|
||||||
{
|
|
||||||
// get line of sight Z coordinates
|
|
||||||
double losoz = goz + ((oheight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
|
||||||
double lostz = gtz + ((theight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
|
||||||
|
|
||||||
// get X delta and signum
|
|
||||||
final int dx = Math.abs(gtx - gox);
|
|
||||||
final int sx = gox < gtx ? 1 : -1;
|
|
||||||
final byte dirox = sx > 0 ? GeoStructure.CELL_FLAG_E : GeoStructure.CELL_FLAG_W;
|
|
||||||
final byte dirtx = sx > 0 ? GeoStructure.CELL_FLAG_W : GeoStructure.CELL_FLAG_E;
|
|
||||||
|
|
||||||
// get Y delta and signum
|
|
||||||
final int dy = Math.abs(gty - goy);
|
|
||||||
final int sy = goy < gty ? 1 : -1;
|
|
||||||
final byte diroy = sy > 0 ? GeoStructure.CELL_FLAG_S : GeoStructure.CELL_FLAG_N;
|
|
||||||
final byte dirty = sy > 0 ? GeoStructure.CELL_FLAG_N : GeoStructure.CELL_FLAG_S;
|
|
||||||
|
|
||||||
// get Z delta
|
|
||||||
final int dm = Math.max(dx, dy);
|
|
||||||
final double dz = (lostz - losoz) / dm;
|
|
||||||
|
|
||||||
// get direction flag for diagonal movement
|
|
||||||
final byte diroxy = getDirXY(dirox, diroy);
|
|
||||||
final byte dirtxy = getDirXY(dirtx, dirty);
|
|
||||||
|
|
||||||
// delta, determines axis to move on (+..X axis, -..Y axis)
|
|
||||||
int d = dx - dy;
|
|
||||||
|
|
||||||
// NSWE direction of movement
|
|
||||||
byte diro;
|
|
||||||
byte dirt;
|
|
||||||
|
|
||||||
// clearDebugItems();
|
|
||||||
// dropDebugItem(728, 0, new GeoLocation(gox, goy, goz)); // blue potion
|
|
||||||
// dropDebugItem(728, 0, new GeoLocation(gtx, gty, gtz)); // blue potion
|
|
||||||
|
|
||||||
// initialize node values
|
|
||||||
int nox = gox;
|
|
||||||
int noy = goy;
|
|
||||||
int ntx = gtx;
|
|
||||||
int nty = gty;
|
|
||||||
byte nsweo = getNsweNearestOriginal(gox, goy, goz);
|
|
||||||
byte nswet = getNsweNearestOriginal(gtx, gty, gtz);
|
|
||||||
|
|
||||||
// loop
|
|
||||||
ABlock block;
|
|
||||||
int index;
|
|
||||||
for (int i = 0; i < ((dm + 1) / 2); i++)
|
|
||||||
{
|
|
||||||
// dropDebugItem(57, 0, new GeoLocation(gox, goy, goz)); // antidote
|
|
||||||
// dropDebugItem(1831, 0, new GeoLocation(gtx, gty, gtz)); // adena
|
|
||||||
|
|
||||||
// reset direction flag
|
|
||||||
diro = 0;
|
|
||||||
dirt = 0;
|
|
||||||
|
|
||||||
// calculate next point coordinates
|
|
||||||
int e2 = 2 * d;
|
|
||||||
if ((e2 > -dy) && (e2 < dx))
|
|
||||||
{
|
|
||||||
// calculate next point XY coordinates
|
|
||||||
d -= dy;
|
|
||||||
d += dx;
|
|
||||||
nox += sx;
|
|
||||||
ntx -= sx;
|
|
||||||
noy += sy;
|
|
||||||
nty -= sy;
|
|
||||||
diro |= diroxy;
|
|
||||||
dirt |= dirtxy;
|
|
||||||
}
|
|
||||||
else if (e2 > -dy)
|
|
||||||
{
|
|
||||||
// calculate next point X coordinate
|
|
||||||
d -= dy;
|
|
||||||
nox += sx;
|
|
||||||
ntx -= sx;
|
|
||||||
diro |= dirox;
|
|
||||||
dirt |= dirtx;
|
|
||||||
}
|
|
||||||
else if (e2 < dx)
|
|
||||||
{
|
|
||||||
// calculate next point Y coordinate
|
|
||||||
d += dx;
|
|
||||||
noy += sy;
|
|
||||||
nty -= sy;
|
|
||||||
diro |= diroy;
|
|
||||||
dirt |= dirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// get block of the next cell
|
|
||||||
block = getBlock(nox, noy);
|
|
||||||
|
|
||||||
// get index of particular layer, based on movement conditions
|
|
||||||
if ((nsweo & diro) == 0)
|
|
||||||
{
|
|
||||||
index = block.getIndexAboveOriginal(nox, noy, goz - GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = block.getIndexBelowOriginal(nox, noy, goz + GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layer does not exist, return
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer and next line of sight Z coordinate
|
|
||||||
goz = block.getHeightOriginal(index);
|
|
||||||
losoz += dz;
|
|
||||||
|
|
||||||
// perform line of sight check, return when fails
|
|
||||||
if ((goz - losoz) > Config.MAX_OBSTACLE_HEIGHT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer nswe
|
|
||||||
nsweo = block.getNsweOriginal(index);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// get block of the next cell
|
|
||||||
block = getBlock(ntx, nty);
|
|
||||||
|
|
||||||
// get index of particular layer, based on movement conditions
|
|
||||||
if ((nswet & dirt) == 0)
|
|
||||||
{
|
|
||||||
index = block.getIndexAboveOriginal(ntx, nty, gtz - GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = block.getIndexBelowOriginal(ntx, nty, gtz + GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layer does not exist, return
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer and next line of sight Z coordinate
|
|
||||||
gtz = block.getHeightOriginal(index);
|
|
||||||
lostz -= dz;
|
|
||||||
|
|
||||||
// perform line of sight check, return when fails
|
|
||||||
if ((gtz - lostz) > Config.MAX_OBSTACLE_HEIGHT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer nswe
|
|
||||||
nswet = block.getNsweOriginal(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update coords
|
|
||||||
gox = nox;
|
|
||||||
goy = noy;
|
|
||||||
gtx = ntx;
|
|
||||||
gty = nty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when iteration is completed, compare final Z coordinates
|
|
||||||
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check movement from coordinates to coordinates.
|
* Check movement from coordinates to coordinates.
|
||||||
* @param ox : origin X coordinate
|
* @param ox : origin X coordinate
|
||||||
|
@@ -958,7 +958,6 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
|
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
|
||||||
if (isFollowing())
|
if (isFollowing())
|
||||||
{
|
{
|
||||||
|
|
||||||
// allow larger hit range when the target is moving (check is run only once per second)
|
// allow larger hit range when the target is moving (check is run only once per second)
|
||||||
if (!_actor.isInsideRadius(target, offset + 100, false, false))
|
if (!_actor.isInsideRadius(target, offset + 100, false, false))
|
||||||
{
|
{
|
||||||
@@ -981,14 +980,11 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// while flying there is no move to cast
|
// while flying there is no move to cast
|
||||||
if (_actor.getAI().getIntention() == AI_INTENTION_CAST)
|
if (_actor.getAI().getIntention() == AI_INTENTION_CAST && _actor.isPlayer() && _actor.checkTransformed(transform -> !transform.isCombat()))
|
||||||
{
|
{
|
||||||
if (_actor.checkTransformed(transform -> !transform.isCombat()))
|
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_CANCELLED);
|
||||||
{
|
_actor.sendPacket(ActionFailed.STATIC_PACKET);
|
||||||
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_CANCELLED);
|
return true;
|
||||||
_actor.sendPacket(ActionFailed.STATIC_PACKET);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
|
// If not running, set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
|
||||||
|
@@ -35,13 +35,11 @@ import com.l2jmobius.gameserver.geoengine.geodata.BlockNull;
|
|||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
|
||||||
import com.l2jmobius.gameserver.geoengine.geodata.IGeoObject;
|
|
||||||
import com.l2jmobius.gameserver.instancemanager.WarpedSpaceManager;
|
import com.l2jmobius.gameserver.instancemanager.WarpedSpaceManager;
|
||||||
import com.l2jmobius.gameserver.model.L2Object;
|
import com.l2jmobius.gameserver.model.L2Object;
|
||||||
import com.l2jmobius.gameserver.model.L2World;
|
import com.l2jmobius.gameserver.model.L2World;
|
||||||
import com.l2jmobius.gameserver.model.Location;
|
import com.l2jmobius.gameserver.model.Location;
|
||||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||||
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
|
|
||||||
import com.l2jmobius.gameserver.model.instancezone.Instance;
|
import com.l2jmobius.gameserver.model.instancezone.Instance;
|
||||||
import com.l2jmobius.gameserver.util.MathUtil;
|
import com.l2jmobius.gameserver.util.MathUtil;
|
||||||
|
|
||||||
@@ -317,20 +315,6 @@ public class GeoEngine
|
|||||||
return block != null ? block.getHeightNearest(geoX, geoY, worldZ) : (short) worldZ;
|
return block != null ? block.getHeightNearest(geoX, geoY, worldZ) : (short) worldZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the height of cell, which is closest to given coordinates.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.
|
|
||||||
* @param geoX : Cell geodata X coordinate.
|
|
||||||
* @param geoY : Cell geodata Y coordinate.
|
|
||||||
* @param worldZ : Cell world Z coordinate.
|
|
||||||
* @return short : Cell geodata Z coordinate, closest to given coordinates.
|
|
||||||
*/
|
|
||||||
private final short getHeightNearestOriginal(int geoX, int geoY, int worldZ)
|
|
||||||
{
|
|
||||||
final ABlock block = getBlock(geoX, geoY);
|
|
||||||
return block != null ? block.getHeightNearestOriginal(geoX, geoY, worldZ) : (short) worldZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the NSWE flag byte of cell, which is closes to given coordinates.
|
* Returns the NSWE flag byte of cell, which is closes to given coordinates.
|
||||||
* @param geoX : Cell geodata X coordinate.
|
* @param geoX : Cell geodata X coordinate.
|
||||||
@@ -344,20 +328,6 @@ public class GeoEngine
|
|||||||
return block != null ? block.getNsweNearest(geoX, geoY, worldZ) : (byte) 0xFF;
|
return block != null ? block.getNsweNearest(geoX, geoY, worldZ) : (byte) 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the NSWE flag byte of cell, which is closes to given coordinates.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.
|
|
||||||
* @param geoX : Cell geodata X coordinate.
|
|
||||||
* @param geoY : Cell geodata Y coordinate.
|
|
||||||
* @param worldZ : Cell world Z coordinate.
|
|
||||||
* @return short : Cell NSWE flag byte coordinate, closest to given coordinates.
|
|
||||||
*/
|
|
||||||
private final byte getNsweNearestOriginal(int geoX, int geoY, int worldZ)
|
|
||||||
{
|
|
||||||
final ABlock block = getBlock(geoX, geoY);
|
|
||||||
return block != null ? block.getNsweNearestOriginal(geoX, geoY, worldZ) : (byte) 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if world coordinates has geo.
|
* Check if world coordinates has geo.
|
||||||
* @param worldX : World X
|
* @param worldX : World X
|
||||||
@@ -391,6 +361,11 @@ public class GeoEngine
|
|||||||
*/
|
*/
|
||||||
public final boolean canSeeTarget(L2Object origin, L2Object target)
|
public final boolean canSeeTarget(L2Object origin, L2Object target)
|
||||||
{
|
{
|
||||||
|
if (target.isDoor())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// get origin and target world coordinates
|
// get origin and target world coordinates
|
||||||
final int ox = origin.getX();
|
final int ox = origin.getX();
|
||||||
final int oy = origin.getY();
|
final int oy = origin.getY();
|
||||||
@@ -399,7 +374,7 @@ public class GeoEngine
|
|||||||
final int ty = target.getY();
|
final int ty = target.getY();
|
||||||
final int tz = target.getZ();
|
final int tz = target.getZ();
|
||||||
|
|
||||||
if (!target.isDoor() && DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), false))
|
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -430,8 +405,7 @@ public class GeoEngine
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean door = target.isDoor();
|
final short gtz = getHeightNearest(gtx, gty, tz);
|
||||||
final short gtz = door ? getHeightNearestOriginal(gtx, gty, tz) : getHeightNearest(gtx, gty, tz);
|
|
||||||
|
|
||||||
// origin and target coordinates are same
|
// origin and target coordinates are same
|
||||||
if ((gox == gtx) && (goy == gty))
|
if ((gox == gtx) && (goy == gty))
|
||||||
@@ -453,7 +427,7 @@ public class GeoEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
// perform geodata check
|
// perform geodata check
|
||||||
return door ? checkSeeOriginal(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld()) : checkSee(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld());
|
return checkSee(gox, goy, goz, oheight, gtx, gty, gtz, theight, origin.getInstanceWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -472,7 +446,7 @@ public class GeoEngine
|
|||||||
final int ty = position.getY();
|
final int ty = position.getY();
|
||||||
final int tz = position.getZ();
|
final int tz = position.getZ();
|
||||||
|
|
||||||
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), false))
|
if (DoorData.getInstance().checkIfDoorsBetween(ox, oy, oz, tx, ty, tz, origin.getInstanceWorld(), true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -703,189 +677,6 @@ public class GeoEngine
|
|||||||
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple check for origin to target visibility.<br>
|
|
||||||
* Geodata without {@link IGeoObject} are taken in consideration.<br>
|
|
||||||
* NOTE: When two doors close between each other and the LoS check of one doors is performed through another door, result will not be accurate (the other door are skipped).
|
|
||||||
* @param gox : origin X geodata coordinate
|
|
||||||
* @param goy : origin Y geodata coordinate
|
|
||||||
* @param goz : origin Z geodata coordinate
|
|
||||||
* @param oheight : origin height (if instance of {@link Character})
|
|
||||||
* @param gtx : target X geodata coordinate
|
|
||||||
* @param gty : target Y geodata coordinate
|
|
||||||
* @param gtz : target Z geodata coordinate
|
|
||||||
* @param theight : target height (if instance of {@link Character} or {@link L2DoorInstance})
|
|
||||||
* @param instance
|
|
||||||
* @return {@code boolean} : True, when target can be seen.
|
|
||||||
*/
|
|
||||||
private final boolean checkSeeOriginal(int gox, int goy, int goz, double oheight, int gtx, int gty, int gtz, double theight, Instance instance)
|
|
||||||
{
|
|
||||||
// get line of sight Z coordinates
|
|
||||||
double losoz = goz + ((oheight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
|
||||||
double lostz = gtz + ((theight * Config.PART_OF_CHARACTER_HEIGHT) / 100);
|
|
||||||
|
|
||||||
// get X delta and signum
|
|
||||||
final int dx = Math.abs(gtx - gox);
|
|
||||||
final int sx = gox < gtx ? 1 : -1;
|
|
||||||
final byte dirox = sx > 0 ? GeoStructure.CELL_FLAG_E : GeoStructure.CELL_FLAG_W;
|
|
||||||
final byte dirtx = sx > 0 ? GeoStructure.CELL_FLAG_W : GeoStructure.CELL_FLAG_E;
|
|
||||||
|
|
||||||
// get Y delta and signum
|
|
||||||
final int dy = Math.abs(gty - goy);
|
|
||||||
final int sy = goy < gty ? 1 : -1;
|
|
||||||
final byte diroy = sy > 0 ? GeoStructure.CELL_FLAG_S : GeoStructure.CELL_FLAG_N;
|
|
||||||
final byte dirty = sy > 0 ? GeoStructure.CELL_FLAG_N : GeoStructure.CELL_FLAG_S;
|
|
||||||
|
|
||||||
// get Z delta
|
|
||||||
final int dm = Math.max(dx, dy);
|
|
||||||
final double dz = (lostz - losoz) / dm;
|
|
||||||
|
|
||||||
// get direction flag for diagonal movement
|
|
||||||
final byte diroxy = getDirXY(dirox, diroy);
|
|
||||||
final byte dirtxy = getDirXY(dirtx, dirty);
|
|
||||||
|
|
||||||
// delta, determines axis to move on (+..X axis, -..Y axis)
|
|
||||||
int d = dx - dy;
|
|
||||||
|
|
||||||
// NSWE direction of movement
|
|
||||||
byte diro;
|
|
||||||
byte dirt;
|
|
||||||
|
|
||||||
// clearDebugItems();
|
|
||||||
// dropDebugItem(728, 0, new GeoLocation(gox, goy, goz)); // blue potion
|
|
||||||
// dropDebugItem(728, 0, new GeoLocation(gtx, gty, gtz)); // blue potion
|
|
||||||
|
|
||||||
// initialize node values
|
|
||||||
int nox = gox;
|
|
||||||
int noy = goy;
|
|
||||||
int ntx = gtx;
|
|
||||||
int nty = gty;
|
|
||||||
byte nsweo = getNsweNearestOriginal(gox, goy, goz);
|
|
||||||
byte nswet = getNsweNearestOriginal(gtx, gty, gtz);
|
|
||||||
|
|
||||||
// loop
|
|
||||||
ABlock block;
|
|
||||||
int index;
|
|
||||||
for (int i = 0; i < ((dm + 1) / 2); i++)
|
|
||||||
{
|
|
||||||
// dropDebugItem(57, 0, new GeoLocation(gox, goy, goz)); // antidote
|
|
||||||
// dropDebugItem(1831, 0, new GeoLocation(gtx, gty, gtz)); // adena
|
|
||||||
|
|
||||||
// reset direction flag
|
|
||||||
diro = 0;
|
|
||||||
dirt = 0;
|
|
||||||
|
|
||||||
// calculate next point coordinates
|
|
||||||
int e2 = 2 * d;
|
|
||||||
if ((e2 > -dy) && (e2 < dx))
|
|
||||||
{
|
|
||||||
// calculate next point XY coordinates
|
|
||||||
d -= dy;
|
|
||||||
d += dx;
|
|
||||||
nox += sx;
|
|
||||||
ntx -= sx;
|
|
||||||
noy += sy;
|
|
||||||
nty -= sy;
|
|
||||||
diro |= diroxy;
|
|
||||||
dirt |= dirtxy;
|
|
||||||
}
|
|
||||||
else if (e2 > -dy)
|
|
||||||
{
|
|
||||||
// calculate next point X coordinate
|
|
||||||
d -= dy;
|
|
||||||
nox += sx;
|
|
||||||
ntx -= sx;
|
|
||||||
diro |= dirox;
|
|
||||||
dirt |= dirtx;
|
|
||||||
}
|
|
||||||
else if (e2 < dx)
|
|
||||||
{
|
|
||||||
// calculate next point Y coordinate
|
|
||||||
d += dx;
|
|
||||||
noy += sy;
|
|
||||||
nty -= sy;
|
|
||||||
diro |= diroy;
|
|
||||||
dirt |= dirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// get block of the next cell
|
|
||||||
block = getBlock(nox, noy);
|
|
||||||
|
|
||||||
// get index of particular layer, based on movement conditions
|
|
||||||
if ((nsweo & diro) == 0)
|
|
||||||
{
|
|
||||||
index = block.getIndexAboveOriginal(nox, noy, goz - GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = block.getIndexBelowOriginal(nox, noy, goz + GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layer does not exist, return
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer and next line of sight Z coordinate
|
|
||||||
goz = block.getHeightOriginal(index);
|
|
||||||
losoz += dz;
|
|
||||||
|
|
||||||
// perform line of sight check, return when fails
|
|
||||||
if ((goz - losoz) > Config.MAX_OBSTACLE_HEIGHT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer nswe
|
|
||||||
nsweo = block.getNsweOriginal(index);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// get block of the next cell
|
|
||||||
block = getBlock(ntx, nty);
|
|
||||||
|
|
||||||
// get index of particular layer, based on movement conditions
|
|
||||||
if ((nswet & dirt) == 0)
|
|
||||||
{
|
|
||||||
index = block.getIndexAboveOriginal(ntx, nty, gtz - GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = block.getIndexBelowOriginal(ntx, nty, gtz + GeoStructure.CELL_IGNORE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layer does not exist, return
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer and next line of sight Z coordinate
|
|
||||||
gtz = block.getHeightOriginal(index);
|
|
||||||
lostz -= dz;
|
|
||||||
|
|
||||||
// perform line of sight check, return when fails
|
|
||||||
if ((gtz - lostz) > Config.MAX_OBSTACLE_HEIGHT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get layer nswe
|
|
||||||
nswet = block.getNsweOriginal(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update coords
|
|
||||||
gox = nox;
|
|
||||||
goy = noy;
|
|
||||||
gtx = ntx;
|
|
||||||
gty = nty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when iteration is completed, compare final Z coordinates
|
|
||||||
return Math.abs(goz - gtz) < (GeoStructure.CELL_HEIGHT * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check movement from coordinates to coordinates.
|
* Check movement from coordinates to coordinates.
|
||||||
* @param ox : origin X coordinate
|
* @param ox : origin X coordinate
|
||||||
|
Reference in New Issue
Block a user