GeoEngine door check improvements.

Contributed by Sahar.
This commit is contained in:
MobiusDev
2018-06-30 14:09:20 +00:00
parent 0ae00a3cd5
commit 94d1362588
16 changed files with 107 additions and 1832 deletions

View File

@@ -958,7 +958,6 @@ public class L2CharacterAI extends AbstractAI
// Caller should be L2Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
if (isFollowing())
{
// allow larger hit range when the target is moving (check is run only once per second)
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
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);
return true;
}
_actor.sendPacket(SystemMessageId.THE_DISTANCE_IS_TOO_FAR_AND_SO_THE_CASTING_HAS_BEEN_STOPPED);
_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

View File

@@ -35,13 +35,11 @@ import com.l2jmobius.gameserver.geoengine.geodata.BlockNull;
import com.l2jmobius.gameserver.geoengine.geodata.GeoFormat;
import com.l2jmobius.gameserver.geoengine.geodata.GeoLocation;
import com.l2jmobius.gameserver.geoengine.geodata.GeoStructure;
import com.l2jmobius.gameserver.geoengine.geodata.IGeoObject;
import com.l2jmobius.gameserver.instancemanager.WarpedSpaceManager;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.Location;
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.util.MathUtil;
@@ -317,20 +315,6 @@ public class GeoEngine
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.
* @param geoX : Cell geodata X coordinate.
@@ -344,20 +328,6 @@ public class GeoEngine
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.
* @param worldX : World X
@@ -391,6 +361,11 @@ public class GeoEngine
*/
public final boolean canSeeTarget(L2Object origin, L2Object target)
{
if (target.isDoor())
{
return true;
}
// get origin and target world coordinates
final int ox = origin.getX();
final int oy = origin.getY();
@@ -399,7 +374,7 @@ public class GeoEngine
final int ty = target.getY();
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;
}
@@ -430,8 +405,7 @@ public class GeoEngine
return true;
}
final boolean door = target.isDoor();
final short gtz = door ? getHeightNearestOriginal(gtx, gty, tz) : getHeightNearest(gtx, gty, tz);
final short gtz = getHeightNearest(gtx, gty, tz);
// origin and target coordinates are same
if ((gox == gtx) && (goy == gty))
@@ -453,7 +427,7 @@ public class GeoEngine
}
// 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 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;
}
@@ -703,189 +677,6 @@ public class GeoEngine
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.
* @param ox : origin X coordinate