AI movement rework for return to spawn and long range paths.

This commit is contained in:
MobiusDevelopment
2022-07-22 23:34:26 +00:00
parent c9a3a26302
commit 563794ef55
140 changed files with 2367 additions and 951 deletions

View File

@@ -137,9 +137,6 @@ AggroDistanceCheckRestoreLife = True
# Default: False
GuardAttackAggroMob = False
# True - Allows guards to use return skill after combat.
# Default: False
EnableGuardReturn = True
# ---------------------------------------------------------------------------
# Pets

View File

@@ -746,7 +746,6 @@ public class Config
public static boolean AGGRO_DISTANCE_CHECK_INSTANCES;
public static boolean AGGRO_DISTANCE_CHECK_RESTORE_LIFE;
public static boolean GUARD_ATTACK_AGGRO_MOB;
public static boolean ENABLE_GUARD_RETURN;
public static boolean ALLOW_WYVERN_UPGRADER;
public static List<Integer> LIST_PET_RENT_NPC;
public static double RAID_HP_REGEN_MULTIPLIER;
@@ -2239,7 +2238,6 @@ public class Config
AGGRO_DISTANCE_CHECK_INSTANCES = npcConfig.getBoolean("AggroDistanceCheckInstances", false);
AGGRO_DISTANCE_CHECK_RESTORE_LIFE = npcConfig.getBoolean("AggroDistanceCheckRestoreLife", true);
GUARD_ATTACK_AGGRO_MOB = npcConfig.getBoolean("GuardAttackAggroMob", false);
ENABLE_GUARD_RETURN = npcConfig.getBoolean("EnableGuardReturn", false);
ALLOW_WYVERN_UPGRADER = npcConfig.getBoolean("AllowWyvernUpgrader", false);
final String[] listPetRentNpc = npcConfig.getString("ListPetRentNpc", "30827").split(",");
LIST_PET_RENT_NPC = new ArrayList<>(listPetRentNpc.length);

View File

@@ -27,7 +27,6 @@ import java.util.concurrent.Future;
import org.l2jmobius.Config;
import org.l2jmobius.commons.threads.ThreadPool;
import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.data.xml.SkillData;
import org.l2jmobius.gameserver.enums.AISkillScope;
import org.l2jmobius.gameserver.enums.AIType;
import org.l2jmobius.gameserver.geoengine.GeoEngine;
@@ -602,30 +601,29 @@ public class AttackableAI extends CreatureAI
npc.getAttackByList().clear();
}
// If this is a festival monster, then it remains in the same location.
// if (npc instanceof FestivalMonster)
// {
// return;
// }
// 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 GuardInstance
if ((npc instanceof Guard) && !npc.isWalker())
// 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())))
{
if (Config.ENABLE_GUARD_RETURN && (npc.getSpawn() != null) && (Util.calculateDistance(npc, npc.getSpawn(), false, false) > 50) && /* !npc.isInsideZone(ZoneId.SIEGE) && */!npc.isCastingNow())
{
// Custom guard teleport to spawn.
npc.clearAggroList();
npc.doCast(SkillData.getInstance().getSkill(1050, 1));
}
else
{
// Order to the GuardInstance to return to its home location because there's no target to attack
npc.returnHome();
}
npc.setWalking();
npc.returnHome();
return;
}
// If this is a festival monster, then it remains in the same location.
if (npc instanceof FestivalMonster)
// Do not leave dead player
if ((getTarget() != null) && getTarget().isPlayer() && getTarget().getActingPlayer().isAlikeDead())
{
return;
}
@@ -681,7 +679,6 @@ public class AttackableAI extends CreatureAI
// Order to the Monster to random walk (1/100)
else if ((npc.getSpawn() != null) && (Rnd.get(RANDOM_WALK_RATE) == 0) && npc.isRandomWalkingEnabled())
{
for (Skill sk : npc.getTemplate().getAISkills(AISkillScope.BUFF))
{
if (cast(sk))

View File

@@ -1688,6 +1688,7 @@ public class Attackable extends Npc
if (hasAI() && (getSpawn() != null))
{
setReturningToSpawnPoint(true);
getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, getSpawn().getLocation());
}
}

View File

@@ -4433,10 +4433,10 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
// Movement checks.
if ((Config.PATHFINDING > 0) && !(this instanceof QuestGuard))
{
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())
@@ -4476,31 +4476,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, getInstanceId(), 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, getInstanceId(), 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;
@@ -4515,6 +4539,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;
}
}
}

View File

@@ -41,6 +41,7 @@ public class QuestGuard extends Guard
{
super(template);
setInstanceType(InstanceType.QuestGuard);
setCanReturnToSpawnPoint(false);
}
@Override