AI movement rework for return to spawn and long range paths.
This commit is contained in:
@ -41,7 +41,6 @@ import org.l2jmobius.gameserver.model.actor.Attackable;
|
||||
import org.l2jmobius.gameserver.model.actor.Creature;
|
||||
import org.l2jmobius.gameserver.model.actor.Playable;
|
||||
import org.l2jmobius.gameserver.model.actor.Player;
|
||||
import org.l2jmobius.gameserver.model.actor.instance.Defender;
|
||||
import org.l2jmobius.gameserver.model.actor.instance.GrandBoss;
|
||||
import org.l2jmobius.gameserver.model.actor.instance.Guard;
|
||||
import org.l2jmobius.gameserver.model.actor.instance.Monster;
|
||||
@ -468,16 +467,23 @@ public class AttackableAI extends CreatureAI
|
||||
}
|
||||
|
||||
// Check if the mob should not return to spawn point
|
||||
if (!npc.canReturnToSpawnPoint())
|
||||
if (!npc.canReturnToSpawnPoint()
|
||||
/* || npc.isReturningToSpawnPoint() */ ) // Commented because sometimes it stops movement.
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the actor is a guard
|
||||
if (((npc instanceof Guard) || (npc instanceof Defender)) && !npc.isWalker() && !npc.isRandomWalkingEnabled())
|
||||
// Order this attackable to return to its spawn because there's no target to attack
|
||||
if (!npc.isWalker() && ((getTarget() == null) || getTarget().isInvisible() || (getTarget().isPlayer() && !getTarget().getActingPlayer().isAlikeDead())))
|
||||
{
|
||||
// Order to the GuardInstance to return to its home location because there's no target to attack
|
||||
npc.returnHome();
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not leave dead player
|
||||
if ((getTarget() != null) && getTarget().isPlayer() && getTarget().getActingPlayer().isAlikeDead())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Minions following leader
|
||||
@ -651,13 +657,19 @@ public class AttackableAI extends CreatureAI
|
||||
}
|
||||
|
||||
Creature target = npc.getMostHated();
|
||||
if (target == null)
|
||||
{
|
||||
setIntention(AI_INTENTION_ACTIVE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (getTarget() != target)
|
||||
{
|
||||
setTarget(target);
|
||||
}
|
||||
|
||||
// Check if target is dead or if timeout is expired to stop this attack
|
||||
if ((target == null) || target.isAlikeDead())
|
||||
if (target.isAlikeDead())
|
||||
{
|
||||
// Stop hating this target after the attack timeout or if target is dead
|
||||
npc.stopHating(target);
|
||||
|
@ -1737,6 +1737,7 @@ public class Attackable extends Npc
|
||||
|
||||
if (hasAI() && (getSpawn() != null))
|
||||
{
|
||||
setReturningToSpawnPoint(true);
|
||||
getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, getSpawn().getLocation());
|
||||
}
|
||||
}
|
||||
|
@ -3469,10 +3469,10 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
|
||||
// Movement checks.
|
||||
if ((Config.PATHFINDING > 0) && !(this instanceof FriendlyNpc))
|
||||
{
|
||||
final double originalDistance = distance;
|
||||
final int originalX = x;
|
||||
final int originalY = y;
|
||||
int originalX = x;
|
||||
int originalY = y;
|
||||
final int originalZ = z;
|
||||
final double originalDistance = distance;
|
||||
final int gtx = (originalX - World.WORLD_X_MIN) >> 4;
|
||||
final int gty = (originalY - World.WORLD_Y_MIN) >> 4;
|
||||
if (isOnGeodataPath())
|
||||
@ -3512,31 +3512,55 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
|
||||
{
|
||||
// Path calculation -- overrides previous movement check
|
||||
m.geoPath = PathFinding.getInstance().findPath(curX, curY, curZ, originalX, originalY, originalZ, getInstanceWorld(), isPlayer());
|
||||
if ((m.geoPath == null) || (m.geoPath.size() < 2)) // No path found
|
||||
boolean found = (m.geoPath != null) && (m.geoPath.size() > 1);
|
||||
|
||||
// If not found and it is an Attackable, attempt to find closest path to move location.
|
||||
if (!found && isAttackable())
|
||||
{
|
||||
if (isPlayer() && !_isFlying && !isInWater)
|
||||
int xMin = Math.min(curX, originalX);
|
||||
int xMax = Math.max(curX, originalX);
|
||||
int yMin = Math.min(curY, originalY);
|
||||
int yMax = Math.max(curY, originalY);
|
||||
final int maxDiff = Math.min(Math.max(xMax - xMin, yMax - yMin), 500);
|
||||
xMin -= maxDiff;
|
||||
xMax += maxDiff;
|
||||
yMin -= maxDiff;
|
||||
yMax += maxDiff;
|
||||
int destinationX = 0;
|
||||
int destinationY = 0;
|
||||
double shortDistance = Double.MAX_VALUE;
|
||||
double tempDistance;
|
||||
List<AbstractNodeLoc> tempPath;
|
||||
for (int sX = xMin; sX < xMax; sX += 500)
|
||||
{
|
||||
return;
|
||||
for (int sY = yMin; sY < yMax; sY += 500)
|
||||
{
|
||||
tempDistance = Math.sqrt(Math.pow(sX - originalX, 2) + Math.pow(sY - originalY, 2));
|
||||
if (tempDistance < shortDistance)
|
||||
{
|
||||
tempPath = PathFinding.getInstance().findPath(curX, curY, curZ, sX, sY, originalZ, getInstanceWorld(), false);
|
||||
found = (tempPath != null) && (tempPath.size() > 1);
|
||||
if (found)
|
||||
{
|
||||
shortDistance = tempDistance;
|
||||
m.geoPath = tempPath;
|
||||
destinationX = sX;
|
||||
destinationY = sY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
found = (m.geoPath != null) && (m.geoPath.size() > 1);
|
||||
if (found)
|
||||
{
|
||||
originalX = destinationX;
|
||||
originalY = destinationY;
|
||||
}
|
||||
// if (!isPlayable() && !isMinion() && (Math.abs(z - curZ) > 140))
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// if (isSummon() && !((Summon) this).getFollowStatus())
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
|
||||
m.disregardingGeodata = true;
|
||||
|
||||
x = originalX;
|
||||
y = originalY;
|
||||
z = originalZ;
|
||||
distance = originalDistance;
|
||||
}
|
||||
else
|
||||
|
||||
if (found)
|
||||
{
|
||||
m.onGeodataPathIndex = 0; // on first segment
|
||||
m.onGeodataPathIndex = 0; // On first segment.
|
||||
m.geoPathGtx = gtx;
|
||||
m.geoPathGty = gty;
|
||||
m.geoPathAccurateTx = originalX;
|
||||
@ -3551,6 +3575,20 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
|
||||
sin = dy / distance;
|
||||
cos = dx / distance;
|
||||
}
|
||||
else // No path found.
|
||||
{
|
||||
if (isPlayer() && !_isFlying && !isInWater)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m.disregardingGeodata = true;
|
||||
|
||||
x = originalX;
|
||||
y = originalY;
|
||||
z = originalZ;
|
||||
distance = originalDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@ public class FriendlyNpc extends Attackable
|
||||
{
|
||||
super(template);
|
||||
setInstanceType(InstanceType.FriendlyNpc);
|
||||
setCanReturnToSpawnPoint(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Reference in New Issue
Block a user