Fixed characters reaching targets with less speed.

Contributed by Sahar.
This commit is contained in:
MobiusDevelopment
2021-03-07 22:32:06 +00:00
parent 24bfda4669
commit f1eb56cafa
94 changed files with 1612 additions and 398 deletions
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2555,6 +2555,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2784,6 +2785,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2797,6 +2804,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2810,6 +2823,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -2987,6 +3006,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -2996,14 +3016,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3061,7 +3096,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3211,6 +3253,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3236,12 +3283,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3468,6 +3516,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2555,6 +2555,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2784,6 +2785,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2797,6 +2804,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2810,6 +2823,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -2987,6 +3006,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -2996,14 +3016,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3061,7 +3096,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3211,6 +3253,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3236,12 +3283,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3468,6 +3516,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2555,6 +2555,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2784,6 +2785,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2797,6 +2804,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2810,6 +2823,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -2987,6 +3006,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -2996,14 +3016,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3061,7 +3096,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3211,6 +3253,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3236,12 +3283,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3468,6 +3516,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2555,6 +2555,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2784,6 +2785,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2797,6 +2804,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2810,6 +2823,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -2987,6 +3006,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -2996,14 +3016,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3061,7 +3096,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3211,6 +3253,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3236,12 +3283,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3468,6 +3516,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2555,6 +2555,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2784,6 +2785,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2797,6 +2804,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2810,6 +2823,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -2987,6 +3006,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -2996,14 +3016,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3061,7 +3096,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3211,6 +3253,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3236,12 +3283,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3468,6 +3516,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2555,6 +2555,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2784,6 +2785,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2797,6 +2804,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2810,6 +2823,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -2987,6 +3006,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -2996,14 +3016,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3061,7 +3096,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3211,6 +3253,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3236,12 +3283,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3468,6 +3516,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2555,6 +2555,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2784,6 +2785,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2797,6 +2804,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2810,6 +2823,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -2987,6 +3006,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -2996,14 +3016,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3061,7 +3096,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3211,6 +3253,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3236,12 +3283,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3468,6 +3516,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2555,6 +2555,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2783,6 +2784,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2796,6 +2803,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2809,6 +2822,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -2986,6 +3005,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -2995,14 +3015,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3060,7 +3095,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3210,6 +3252,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3235,12 +3282,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3467,6 +3515,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2555,6 +2555,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2783,6 +2784,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2796,6 +2803,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2809,6 +2822,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -2986,6 +3005,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -2995,14 +3015,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3060,7 +3095,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3210,6 +3252,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3235,12 +3282,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3467,6 +3515,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2555,6 +2555,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2783,6 +2784,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2796,6 +2803,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2809,6 +2822,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -2986,6 +3005,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -2995,14 +3015,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3060,7 +3095,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3210,6 +3252,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3235,12 +3282,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3467,6 +3515,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -476,7 +476,7 @@ abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_accessor.moveTo(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _accessor.moveTo(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
// Mobius: Solves moving to wrong Z when not using geodata, // Mobius: Solves moving to wrong Z when not using geodata,
// but probably is not accurate and you should use geodata. // but probably is not accurate and you should use geodata.
@@ -977,7 +977,7 @@ public class CreatureAI extends AbstractAI
return true; return true;
} }
// 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, offsetWithCollision + 30, false, false)) if (!_actor.isInsideRadius(target, offsetWithCollision + 100, false, false))
{ {
return true; return true;
} }
@@ -1018,7 +1018,7 @@ public class CreatureAI extends AbstractAI
return true; return true;
} }
if (getFollowTarget() != null) if (isFollowing())
{ {
stopFollow(); stopFollow();
} }
@@ -4202,14 +4202,15 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
/** /**
* Accessor to Creature moveToLocation() method with an interaction area. * Accessor to Creature moveToLocation() method with an interaction area.
* @param target The target to follow, if any.
* @param x the x * @param x the x
* @param y the y * @param y the y
* @param z the z * @param z the z
* @param offset the offset * @param offset the offset
*/ */
public void moveTo(int x, int y, int z, int offset) public void moveTo(WorldObject target, int x, int y, int z, int offset)
{ {
moveToLocation(x, y, z, offset); moveToLocation(target, x, y, z, offset);
} }
/** /**
@@ -4287,6 +4288,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; public int _moveTimestamp;
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -4809,6 +4811,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -4823,6 +4831,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -4837,6 +4851,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -5042,6 +5062,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -5052,13 +5073,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else // otherwise we need saved temporary values to avoid rounding errors else // otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -5116,8 +5153,16 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
if (this instanceof BoatInstance) {
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
if (isBoat())
{ {
((BoatInstance) this).updatePeopleInTheBoat(m._xDestination, m._yDestination, m._zDestination); ((BoatInstance) this).updatePeopleInTheBoat(m._xDestination, m._yDestination, m._zDestination);
} }
@@ -5298,6 +5343,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
return _target; return _target;
} }
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -5318,12 +5368,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
* <b><u>Example of use</u>:</b><br> * <b><u>Example of use</u>:</b><br>
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li><br> * <li>FollowTask</li><br>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
protected void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) protected void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Block movement during Event start // Block movement during Event start
if (isPlayer()) if (isPlayer())
@@ -5599,6 +5650,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -92,7 +92,7 @@ public class DoorInstance extends Creature
} }
@Override @Override
public void moveTo(int x, int y, int z, int offset) public void moveTo(WorldObject target, int x, int y, int z, int offset)
{ {
} }
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius(followTarget, followRange, true, false)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius(followTarget, followRangeWithCollision, true, false))
{ {
if (!creature.isInsideRadius(followTarget, 3000, true, false)) if (!creature.isInsideRadius(followTarget, 3000, true, false))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -476,7 +476,7 @@ abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_accessor.moveTo(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _accessor.moveTo(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
// Mobius: Solves moving to wrong Z when not using geodata, // Mobius: Solves moving to wrong Z when not using geodata,
// but probably is not accurate and you should use geodata. // but probably is not accurate and you should use geodata.
@@ -977,7 +977,7 @@ public class CreatureAI extends AbstractAI
return true; return true;
} }
// 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, offsetWithCollision + 30, false, false)) if (!_actor.isInsideRadius(target, offsetWithCollision + 100, false, false))
{ {
return true; return true;
} }
@@ -1018,7 +1018,7 @@ public class CreatureAI extends AbstractAI
return true; return true;
} }
if (getFollowTarget() != null) if (isFollowing())
{ {
stopFollow(); stopFollow();
} }
@@ -4248,14 +4248,15 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
/** /**
* Accessor to Creature moveToLocation() method with an interaction area. * Accessor to Creature moveToLocation() method with an interaction area.
* @param target The target to follow, if any.
* @param x the x * @param x the x
* @param y the y * @param y the y
* @param z the z * @param z the z
* @param offset the offset * @param offset the offset
*/ */
public void moveTo(int x, int y, int z, int offset) public void moveTo(WorldObject target, int x, int y, int z, int offset)
{ {
moveToLocation(x, y, z, offset); moveToLocation(target, x, y, z, offset);
} }
/** /**
@@ -4333,6 +4334,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; public int _moveTimestamp;
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -4855,6 +4857,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -4869,6 +4877,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -4883,6 +4897,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -5088,6 +5108,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -5098,13 +5119,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else // otherwise we need saved temporary values to avoid rounding errors else // otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -5162,8 +5199,16 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
if (this instanceof BoatInstance) {
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
if (isBoat())
{ {
((BoatInstance) this).updatePeopleInTheBoat(m._xDestination, m._yDestination, m._zDestination); ((BoatInstance) this).updatePeopleInTheBoat(m._xDestination, m._yDestination, m._zDestination);
} }
@@ -5344,6 +5389,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
return _target; return _target;
} }
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -5364,12 +5414,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
* <b><u>Example of use</u>:</b><br> * <b><u>Example of use</u>:</b><br>
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li><br> * <li>FollowTask</li><br>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
protected void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) protected void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Block movement during Event start // Block movement during Event start
if (isPlayer()) if (isPlayer())
@@ -5645,6 +5696,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -92,7 +92,7 @@ public class DoorInstance extends Creature
} }
@Override @Override
public void moveTo(int x, int y, int z, int offset) public void moveTo(WorldObject target, int x, int y, int z, int offset)
{ {
} }
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius(followTarget, followRange, true, false)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius(followTarget, followRangeWithCollision, true, false))
{ {
if (!creature.isInsideRadius(followTarget, 3000, true, false)) if (!creature.isInsideRadius(followTarget, 3000, true, false))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -530,7 +530,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -971,7 +971,7 @@ public class CreatureAI extends AbstractAI
return true; return true;
} }
if (getFollowTarget() != null) if (isFollowing())
{ {
stopFollow(); stopFollow();
} }
@@ -1019,10 +1019,10 @@ public class CreatureAI extends AbstractAI
if (!_actor.isInsideRadius2D(target, offsetWithCollision)) if (!_actor.isInsideRadius2D(target, offsetWithCollision))
{ {
// Caller should be Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp // Caller should be Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
if (getFollowTarget() != null) 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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -1077,7 +1077,7 @@ public class CreatureAI extends AbstractAI
return true; return true;
} }
if (getFollowTarget() != null) if (isFollowing())
{ {
stopFollow(); stopFollow();
} }
@@ -3349,6 +3349,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -3714,6 +3715,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -3727,6 +3734,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -3740,6 +3753,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -3929,6 +3948,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -3938,14 +3958,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -4003,7 +4038,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -4151,6 +4193,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return _target; return _target;
} }
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -4176,12 +4223,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -4408,6 +4456,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -530,7 +530,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -971,7 +971,7 @@ public class CreatureAI extends AbstractAI
return true; return true;
} }
if (getFollowTarget() != null) if (isFollowing())
{ {
stopFollow(); stopFollow();
} }
@@ -1019,10 +1019,10 @@ public class CreatureAI extends AbstractAI
if (!_actor.isInsideRadius2D(target, offsetWithCollision)) if (!_actor.isInsideRadius2D(target, offsetWithCollision))
{ {
// Caller should be Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp // Caller should be Playable and thinkAttack/thinkCast/thinkInteract/thinkPickUp
if (getFollowTarget() != null) 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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -1077,7 +1077,7 @@ public class CreatureAI extends AbstractAI
return true; return true;
} }
if (getFollowTarget() != null) if (isFollowing())
{ {
stopFollow(); stopFollow();
} }
@@ -3351,6 +3351,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -3716,6 +3717,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -3729,6 +3736,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -3742,6 +3755,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -3931,6 +3950,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -3940,14 +3960,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -4005,7 +4040,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -4153,6 +4195,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return _target; return _target;
} }
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -4178,12 +4225,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -4410,6 +4458,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2555,6 +2555,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2784,6 +2785,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2797,6 +2804,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2810,6 +2823,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -2987,6 +3006,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -2996,14 +3016,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3061,7 +3096,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3211,6 +3253,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3236,12 +3283,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3468,6 +3516,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2555,6 +2555,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2784,6 +2785,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2797,6 +2804,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2810,6 +2823,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -2987,6 +3006,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -2996,14 +3016,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3061,7 +3096,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3211,6 +3253,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3236,12 +3283,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3468,6 +3516,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2555,6 +2555,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2784,6 +2785,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2797,6 +2804,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2810,6 +2823,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -2987,6 +3006,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -2996,14 +3016,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3061,7 +3096,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3211,6 +3253,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3236,12 +3283,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3468,6 +3516,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2556,6 +2556,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2797,6 +2798,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2810,6 +2817,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2823,6 +2836,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -3000,6 +3019,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -3009,14 +3029,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3074,7 +3109,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3224,6 +3266,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3249,12 +3296,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3481,6 +3529,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2556,6 +2556,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2797,6 +2798,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2810,6 +2817,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2823,6 +2836,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -3000,6 +3019,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -3009,14 +3029,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3074,7 +3109,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3224,6 +3266,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3249,12 +3296,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3481,6 +3529,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2556,6 +2556,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2796,6 +2797,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2809,6 +2816,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2822,6 +2835,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -2999,6 +3018,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -3008,14 +3028,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3073,7 +3108,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3223,6 +3265,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3248,12 +3295,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3480,6 +3528,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2555,6 +2555,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2784,6 +2785,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2797,6 +2804,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2810,6 +2823,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -2987,6 +3006,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -2996,14 +3016,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3061,7 +3096,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3211,6 +3253,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3236,12 +3283,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3468,6 +3516,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2559,6 +2559,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2799,6 +2800,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2812,6 +2819,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2825,6 +2838,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -3002,6 +3021,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -3011,14 +3031,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3076,7 +3111,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3226,6 +3268,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3251,12 +3298,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3483,6 +3531,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {
@@ -467,7 +467,7 @@ public abstract class AbstractAI implements Ctrl
} }
// Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
_actor.moveToLocation(pawn.getX(), pawn.getY(), pawn.getZ(), offset); _actor.moveToLocation(pawn, pawn.getX(), pawn.getY(), pawn.getZ(), offset);
if (!_actor.isMoving()) if (!_actor.isMoving())
{ {
@@ -29,7 +29,6 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config; import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
@@ -67,8 +66,6 @@ import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
*/ */
public class CreatureAI extends AbstractAI public class CreatureAI extends AbstractAI
{ {
private static final Logger LOGGER = Logger.getLogger(CreatureAI.class.getName());
public static class IntentionCommand public static class IntentionCommand
{ {
protected final CtrlIntention _crtlIntention; protected final CtrlIntention _crtlIntention;
@@ -474,9 +471,9 @@ public class CreatureAI extends AbstractAI
// Set the AI pick up target // Set the AI pick up target
setTarget(object); setTarget(object);
if ((object.getX() == 0) && (object.getY() == 0)) // TODO: Find the drop&spawn bug if ((object.getX() == 0) && (object.getY() == 0))
{ {
LOGGER.warning("Object in coords 0,0 - using a temporary fix"); // LOGGER.warning("Object in coords 0,0 - using a temporary fix");
object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5); object.setXYZ(getActor().getX(), getActor().getY(), getActor().getZ() + 5);
} }
@@ -884,7 +881,7 @@ public class CreatureAI extends AbstractAI
{ {
if (worldPosition == null) if (worldPosition == null)
{ {
LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!"); // LOGGER.warning("maybeMoveToPosition: worldPosition == NULL!");
return false; return false;
} }
@@ -954,7 +951,7 @@ public class CreatureAI extends AbstractAI
// Get the distance between the current position of the Creature and the target (x,y) // Get the distance between the current position of the Creature and the target (x,y)
if (target == null) if (target == null)
{ {
LOGGER.warning("maybeMoveToPawn: target == NULL!"); // LOGGER.warning("maybeMoveToPawn: target == NULL!");
return false; return false;
} }
if (offsetValue < 0) if (offsetValue < 0)
@@ -974,7 +971,7 @@ public class CreatureAI extends AbstractAI
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.isInsideRadius2D(target, offsetWithCollision + 30)) if (!_actor.isInsideRadius2D(target, offsetWithCollision + 100))
{ {
return true; return true;
} }
@@ -2566,6 +2566,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// to recalculate position // to recalculate position
public int _moveStartTime; public int _moveStartTime;
public int _moveTimestamp; // last update public int _moveTimestamp; // last update
public WorldObject _target;
public int _xDestination; public int _xDestination;
public int _yDestination; public int _yDestination;
public int _zDestination; public int _zDestination;
@@ -2806,6 +2807,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getX();
}
return m._xDestination; return m._xDestination;
} }
return getX(); return getX();
@@ -2819,6 +2826,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getY();
}
return m._yDestination; return m._yDestination;
} }
return getY(); return getY();
@@ -2832,6 +2845,12 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
final MoveData m = _move; final MoveData m = _move;
if (m != null) if (m != null)
{ {
final WorldObject target = m._target;
if (target != null)
{
return target.getZ();
}
return m._zDestination; return m._zDestination;
} }
return getZ(); return getZ();
@@ -3009,6 +3028,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
return false; return false;
} }
final WorldObject target = m._target;
final int xPrev = getX(); final int xPrev = getX();
final int yPrev = getY(); final int yPrev = getY();
final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations final int zPrev = getZ(); // the z coordinate may be modified by coordinate synchronizations
@@ -3018,14 +3038,29 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (Config.COORD_SYNCHRONIZE == 1) if (Config.COORD_SYNCHRONIZE == 1)
// the only method that can modify x,y while moving (otherwise _move would/should be set null) // the only method that can modify x,y while moving (otherwise _move would/should be set null)
{ {
dx = m._xDestination - xPrev; if (target != null)
dy = m._yDestination - yPrev; {
dx = target.getX() - xPrev;
dy = target.getY() - yPrev;
}
else
{
dx = m._xDestination - xPrev;
dy = m._yDestination - yPrev;
}
} }
else else // otherwise we need saved temporary values to avoid rounding errors
// otherwise we need saved temporary values to avoid rounding errors
{ {
dx = m._xDestination - m._xAccurate; if (target != null)
dy = m._yDestination - m._yAccurate; {
dx = target.getX() - m._xAccurate;
dy = target.getY() - m._yAccurate;
}
else
{
dx = m._xDestination - m._xAccurate;
dy = m._yDestination - m._yAccurate;
}
} }
// Z coordinate will follow client values // Z coordinate will follow client values
@@ -3083,7 +3118,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (distFraction > 1) if (distFraction > 1)
{ {
// Set the position of the Creature to the destination // Set the position of the Creature to the destination
super.setXYZ(m._xDestination, m._yDestination, m._zDestination); if (target != null)
{
super.setXYZ(target.getX(), target.getY(), target.getZ());
}
else
{
super.setXYZ(m._xDestination, m._yDestination, m._zDestination);
}
} }
else else
{ {
@@ -3233,6 +3275,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// called from AIAccessor only // called from AIAccessor only
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue)
{
moveToLocation(null, xValue, yValue, zValue, offsetValue);
}
/** /**
* Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br> * Calculate movement data for a move to location action and add the Creature to movingObjects of GameTimeController (only called by AI Accessor).<br>
* <br> * <br>
@@ -3258,12 +3305,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li> * <li>AI : onIntentionMoveTo(Location), onIntentionPickUp(WorldObject), onIntentionInteract(WorldObject)</li>
* <li>FollowTask</li> * <li>FollowTask</li>
* </ul> * </ul>
* @param target The target to follow, if any.
* @param xValue The X position of the destination * @param xValue The X position of the destination
* @param yValue The Y position of the destination * @param yValue The Y position of the destination
* @param zValue The Y position of the destination * @param zValue The Y position of the destination
* @param offsetValue The size of the interaction area of the Creature targeted * @param offsetValue The size of the interaction area of the Creature targeted
*/ */
public void moveToLocation(int xValue, int yValue, int zValue, int offsetValue) public void moveToLocation(WorldObject target, int xValue, int yValue, int zValue, int offsetValue)
{ {
// Get the Move Speed of the Creature // Get the Move Speed of the Creature
final double speed = _stat.getMoveSpeed(); final double speed = _stat.getMoveSpeed();
@@ -3490,6 +3538,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Calculate the number of ticks between the current position and the destination // Calculate the number of ticks between the current position and the destination
// One tick added for rounding reasons // One tick added for rounding reasons
final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed); final int ticksToMove = 1 + (int) ((GameTimeController.TICKS_PER_SECOND * distance) / speed);
m._target = target;
m._xDestination = x; m._xDestination = x;
m._yDestination = y; m._yDestination = y;
m._zDestination = z; // this is what was requested from client m._zDestination = z; // this is what was requested from client
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI; import org.l2jmobius.gameserver.ai.CreatureAI;
import org.l2jmobius.gameserver.ai.CtrlEvent;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.Summon;
@@ -95,7 +96,8 @@ public class CreatureFollowTaskManager
} }
final int followRange = range == -1 ? Rnd.get(50, 100) : range; final int followRange = range == -1 ? Rnd.get(50, 100) : range;
if (!creature.isInsideRadius3D(followTarget, followRange)) final int followRangeWithCollision = followRange + creature.getTemplate().getCollisionRadius() + ((Creature) followTarget).getTemplate().getCollisionRadius();
if (!creature.isInsideRadius3D(followTarget, followRangeWithCollision))
{ {
if (!creature.isInsideRadius3D(followTarget, 3000)) if (!creature.isInsideRadius3D(followTarget, 3000))
{ {
@@ -109,6 +111,10 @@ public class CreatureFollowTaskManager
} }
ai.moveToPawn(followTarget, followRange); ai.moveToPawn(followTarget, followRange);
} }
else
{
ThreadPool.execute(() -> ai.notifyEvent(CtrlEvent.EVT_ARRIVED));
}
} }
else else
{ {