Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,24 @@ default boolean avoidWilderness() {
return true;
}

@ConfigItem(
keyName = "avoidDangerousNpcs",
name = "Avoid dangerous NPCs",
description = "Route around tiles next to aggressive NPCs that attack you while passing<br>" +
"(e.g. undead trees at Draynor Manor). A penalty, not a block, so chokepoints still work.",
position = 1,
section = sectionSettings
)
default boolean avoidDangerousNpcs() {
return true;
}

Comment thread
bgatfa marked this conversation as resolved.
@ConfigItem(
keyName = "useAgilityShortcuts",
name = "Use agility shortcuts",
description = "Whether to include agility shortcuts in the path.<br>" +
"You must also have the required agility level",
position = 1,
position = 2,
section = sectionSettings
)
default boolean useAgilityShortcuts() {
Expand All @@ -149,7 +161,7 @@ default boolean useAgilityShortcuts() {
name = "Use grapple shortcuts",
description = "Whether to include crossbow grapple agility shortcuts in the path.<br>" +
"You must also have the required agility, ranged and strength levels",
position = 2,
position = 3,
section = sectionSettings
)
default boolean useGrappleShortcuts() {
Expand All @@ -161,7 +173,7 @@ default boolean useGrappleShortcuts() {
name = "Use boats",
description = "Whether to include small boats in the path<br>" +
"(e.g. the boat to Fishing Platform)",
position = 3,
position = 4,
section = sectionSettings
)
default boolean useBoats() {
Expand All @@ -172,7 +184,7 @@ default boolean useBoats() {
keyName = "useCanoes",
name = "Use canoes",
description = "Whether to include canoes in the path",
position = 4,
position = 5,
section = sectionSettings
)
default boolean useCanoes() {
Expand All @@ -183,7 +195,7 @@ default boolean useCanoes() {
keyName = "useCharterShips",
name = "Use charter ships",
description = "Whether to include charter ships in the path",
position = 5,
position = 6,
section = sectionSettings
)
default boolean useCharterShips() {
Expand All @@ -195,7 +207,7 @@ default boolean useCharterShips() {
name = "Use ships",
description = "Whether to include passenger ships in the path<br>" +
"(e.g. the customs ships to Karamja)",
position = 6,
position = 7,
section = sectionSettings
)
default boolean useShips() {
Expand All @@ -207,7 +219,7 @@ default boolean useShips() {
name = "Use fairy rings",
description = "Whether to include fairy rings in the path.<br>" +
"You must also have completed the required quests or miniquests",
position = 7,
position = 8,
section = sectionSettings
)
default boolean useFairyRings() {
Expand All @@ -218,7 +230,7 @@ default boolean useFairyRings() {
keyName = "useGnomeGliders",
name = "Use gnome gliders",
description = "Whether to include gnome gliders in the path",
position = 8,
position = 9,
section = sectionSettings
)
default boolean useGnomeGliders() {
Expand All @@ -230,7 +242,7 @@ default boolean useGnomeGliders() {
name = "Use minecarts",
description = "Whether to include minecarts in the path<br>" +
"(e.g. the Keldagrim and Lovakengj minecart networks)",
position = 9,
position = 10,
section = sectionSettings
)
default boolean useMinecarts() {
Expand All @@ -241,7 +253,7 @@ default boolean useMinecarts() {
keyName = "useSpiritTrees",
name = "Use spirit trees",
description = "Whether to include spirit trees in the path",
position = 10,
position = 11,
section = sectionSettings
)
default boolean useSpiritTrees() {
Expand All @@ -253,7 +265,7 @@ default boolean useSpiritTrees() {
name = "Use teleportation items",
description = "Whether to include teleportation items from the player's inventory and equipment.<br>" +
"Options labelled (perm) only use permanent non-charge items.",
position = 11,
position = 12,
section = sectionSettings
)
default TeleportationItem useTeleportationItems() {
Expand All @@ -265,7 +277,7 @@ default TeleportationItem useTeleportationItems() {
name = "Use teleportation levers",
description = "Whether to include teleportation levers in the path<br>" +
"(e.g. the lever from Edgeville to Wilderness)",
position = 12,
position = 13,
section = sectionSettings
)
default boolean useTeleportationLevers() {
Expand All @@ -277,7 +289,7 @@ default boolean useTeleportationLevers() {
name = "Use teleportation portals",
description = "Whether to include teleportation portals in the path<br>" +
"(e.g. the portal from Ferox Enclave to Castle Wars)",
position = 13,
position = 14,
section = sectionSettings
)
default boolean useTeleportationPortals() {
Expand All @@ -288,7 +300,7 @@ default boolean useTeleportationPortals() {
keyName = "useTeleportationSpells",
name = "Use teleportation spells",
description = "Whether to include teleportation spells in the path",
position = 14,
position = 15,
section = sectionSettings
)
default boolean useTeleportationSpells() {
Expand All @@ -300,7 +312,7 @@ default boolean useTeleportationSpells() {
name = "Use teleportation to minigames",
description = "Whether to include teleportation to minigames/activities/grouping in the path<br>" +
"(e.g. the Nightmare Zone minigame teleport). These teleports share a 20 minute cooldown.",
position = 15,
position = 16,
section = sectionSettings
)
default boolean useTeleportationMinigames() {
Expand All @@ -311,7 +323,7 @@ default boolean useTeleportationMinigames() {
keyName = "useWildernessObelisks",
name = "Use wilderness obelisks",
description = "Whether to include wilderness obelisks in the path",
position = 16,
position = 17,
section = sectionSettings
)
default boolean useWildernessObelisks() {
Expand All @@ -322,7 +334,7 @@ default boolean useWildernessObelisks() {
keyName = "useNpcs",
name = "Use npcs",
description = "Whether to include npc transports in the path<br>(e.g. Tree gnome village maze or Lumbridge cellar)",
position = 17,
position = 18,
section = sectionSettings
)
default boolean useNpcs() {
Expand All @@ -333,7 +345,7 @@ default boolean useNpcs() {
keyName = "useQuetzals",
name = "Use quetzals",
description = "Whether to include quetzals in the path.<br>",
position = 18,
position = 19,
section = sectionSettings
)
default boolean useQuetzals() {
Expand All @@ -344,7 +356,7 @@ default boolean useQuetzals() {
keyName = "useMagicCarpets",
name = "Use Magic Carpets",
description = "Whether to include magic carpets in the path.<br>",
position = 19,
position = 20,
section = sectionSettings
)
default boolean useMagicCarpets() {
Expand All @@ -355,7 +367,7 @@ default boolean useMagicCarpets() {
keyName = "useHotAirBalloons",
name = "Use Hot Air Balloons",
description = "Whether to include hot air balloons in the path.",
position = 19,
position = 21,
section = sectionSettings
)
default boolean useHotAirBalloons() {
Expand All @@ -366,7 +378,7 @@ default boolean useHotAirBalloons() {
keyName = "useMagicMushtrees",
name = "Use Magic Mushtrees",
description = "Whether to include magic mushtrees in the path.",
position = 19,
position = 22,
section = sectionSettings
)
default boolean useMagicMushtrees() {
Expand All @@ -377,7 +389,7 @@ default boolean useMagicMushtrees() {
keyName = "useSeasonalTransports",
name = "Use Seasonal Transports",
description = "Whether to include seasonal League transports (e.g. Map of Alacrity) in the path. League worlds only.",
position = 19,
position = 23,
section = sectionSettings
)
default boolean useSeasonalTransports() {
Expand All @@ -388,7 +400,7 @@ default boolean useSeasonalTransports() {
keyName = "usePoh",
name = "Use Player-owned-house Teleports",
description = "Whether to include teleportation through the PoH",
position = 20,
position = 24,
section = sectionSettings
)
default boolean usePoh() {
Expand All @@ -400,7 +412,7 @@ default boolean usePoh() {
name = "Cancel instead of recalculating",
description = "Whether the path should be cancelled rather than recalculated " +
"when the recalculate distance limit is exceeded",
position = 21,
position = 25,
section = sectionSettings
)
default boolean cancelInstead() {
Expand All @@ -411,7 +423,7 @@ default boolean cancelInstead() {
keyName = "showTransportInfo",
name = "Show transport info",
description = "Whether to display transport destination hint info, e.g. which chat option and text to click",
position = 22,
position = 26,
section = sectionSettings
)
default boolean showTransportInfo() {
Expand All @@ -423,7 +435,7 @@ default boolean showTransportInfo() {
name = "Teleport distance",
description = "Distance before using a teleport<br>" +
"(This is to avoid using teleports when you are to close",
position = 23,
position = 27,
section = sectionSettings
)
default int distanceBeforeUsingTeleport() {
Expand All @@ -438,7 +450,7 @@ default int distanceBeforeUsingTeleport() {
keyName = "recalculateDistance",
name = "Recalculate distance",
description = "Distance from the path the player should be for it to be recalculated (-1 for never)",
position = 24,
position = 28,
section = sectionSettings
)
default int recalculateDistance() {
Expand All @@ -453,7 +465,7 @@ default int recalculateDistance() {
keyName = "finishDistance",
name = "Finish distance",
description = "Distance from the target tile at which the path should be ended (-1 for never)",
position = 25,
position = 29,
section = sectionSettings
)
default int reachedDistance() {
Expand All @@ -464,7 +476,7 @@ default int reachedDistance() {
keyName = "showTileCounter",
name = "Show tile counter",
description = "Whether to display the number of tiles travelled, number of tiles remaining or disable counting",
position = 26,
position = 30,
section = sectionSettings
)
default TileCounter showTileCounter() {
Expand All @@ -475,7 +487,7 @@ default TileCounter showTileCounter() {
keyName = "tileCounterStep",
name = "Tile counter step",
description = "The number of tiles between the displayed tile counter numbers",
position = 27,
position = 31,
section = sectionSettings
)
default int tileCounterStep()
Expand All @@ -495,7 +507,7 @@ default int tileCounterStep()
name = "Calculation cutoff",
description = "The cutoff threshold in number of ticks (0.6 seconds) of no progress being<br>" +
"made towards the path target before the calculation will be stopped",
position = 28,
position = 32,
section = sectionSettings
)
default int calculationCutoff()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ private static int packedPointFromOrdinal(int startPacked, OrdinalDirection dire
private volatile long cachedRegionIdTime = 0;
private static final long REGION_CACHE_MS = 5000;
private static final int TOA_PUZZLE_REGION = 14162;
// Extra g-cost (in tile-distance units) for stepping onto a tile next to an aggressive-NPC
// hazard. High enough to strongly prefer a detour, but a penalty (not a block) so a true
// chokepoint is still traversable.
private static final int DANGEROUS_TILE_PENALTY = 100;

private int getCachedRegionId() {
long now = System.currentTimeMillis();
Expand Down Expand Up @@ -261,7 +265,18 @@ public List<Node> getNeighbors(Node node, VisitedTiles visited, PathfinderConfig
}

if (traversable[i]) {
neighbors.add(new Node(neighborPacked, node));
if (config.isAvoidDangerousNpcs()
&& config.isDangerousAdjacentTile(neighborPacked)
&& !targets.contains(neighborPacked)) {
// Penalty (not a skip): the path keeps >=2 tiles from the hazard when a
// reasonable detour exists, but a chokepoint still routes through.
int penalizedCost = node.cost
+ WorldPointUtil.distanceBetween(node.packedPosition, neighborPacked)
+ DANGEROUS_TILE_PENALTY;
neighbors.add(new Node(neighborPacked, node, penalizedCost));
} else {
neighbors.add(new Node(neighborPacked, node));
}
Comment thread
bgatfa marked this conversation as resolved.
} else if (Math.abs(d.x + d.y) == 1 && isBlocked(x + d.x, y + d.y, z)) {
// The transport starts from a blocked adjacent tile, e.g. fairy ring
// Only checks non-teleport transports (includes portals and levers, but not items and spells)
Expand Down Expand Up @@ -354,7 +369,16 @@ public List<Node> getReverseNeighbors(Node node, VisitedTiles visitedBackward, P
}

if (traversable[i]) {
neighbors.add(new Node(prevPacked, node));
if (config.isAvoidDangerousNpcs() && config.isDangerousAdjacentTile(prevPacked)) {
// Mirror the forward danger penalty so the bidirectional search costs the same
// edge consistently from both ends and can't pick a hazard-adjacent meeting.
int penalizedCost = node.cost
+ WorldPointUtil.distanceBetween(node.packedPosition, prevPacked)
+ DANGEROUS_TILE_PENALTY;
neighbors.add(new Node(prevPacked, node, penalizedCost));
} else {
neighbors.add(new Node(prevPacked, node));
}
} else if (Math.abs(d.x + d.y) == 1
&& isBlocked(WorldPointUtil.unpackWorldX(prevPacked), WorldPointUtil.unpackWorldY(prevPacked), z)) {
int wx = WorldPointUtil.unpackWorldX(prevPacked);
Expand Down
Loading