Initial entity targetting support

main
idylls 1 year ago
parent 5e2e229177
commit fbbab95896
Signed by: idylls
GPG Key ID: 52D7502B0C319049

@ -63,16 +63,17 @@ class Overlay
val tiles = client.scene.tiles[z]
val _hoveredTile = client.selectedSceneTile
val hoveredTarget = getHoveredTarget(client)
val hoveredPathTiles = if (
config.highlightHoveredPath()
&& _hoveredTile != null
&& hoveredTarget != null
) {
val hoveredTile = _hoveredTile.sceneLocation
val requestedTiles = hoveredTarget.getRequestedTiles()
findPath(
findShortestPathAll(
playerTrueTile,
hoveredTile,
requestedTiles,
collisionFlags,
tiles,
)

@ -28,6 +28,25 @@ fun buildPath(
return list
}
fun findShortestPathAll(
from: ScenePoint,
to: Set<ScenePoint>,
collisionFlags: Array<IntArray>,
tiles: Array<Array<RLTile?>>,
): List<ScenePoint>? {
return to
.mapNotNull({ to_ -> findPath(from, to_, collisionFlags, tiles) })
.minByOrNull({ p ->
// minimize zig-zaggedness (manhattan distance) when choosing
// between multiple possible minimal paths
p.windowed(2).fold(0, { acc, w ->
val (a, b) = w
acc + abs(a.x - b.x) + abs(a.y - b.y)
}) + p.size
})
}
fun findPath(
from: ScenePoint,
to: ScenePoint,

@ -0,0 +1,130 @@
package net.idylls.pathos
import net.runelite.api.Client
import net.runelite.api.MenuAction
import net.runelite.api.Point
import net.runelite.api.TileObject
import net.runelite.api.GameObject
import net.runelite.api.Actor as RLActor
import net.runelite.api.Tile as RLTile
sealed class Target {
class Actor(val actor: RLActor) : Target()
class Tile(val tile: RLTile) : Target()
class Object(val obj: TileObject) : Target()
fun getRequestedTiles(): Set<ScenePoint> {
val meleeTiles = { x: Int, y: Int ->
val points = mutableSetOf<ScenePoint>()
if (x > 0) {
points.add(Point(x - 1, y))
}
if (y > 0) {
points.add(Point(x, y - 1))
}
if (x < 128) {
points.add(Point(x + 1, y))
}
if (y < 128) {
points.add(Point(x, y + 1))
}
points
}
return when (this) {
is Tile -> setOf(this.tile.sceneLocation)
is Actor -> {
val lp = this.actor.localLocation
meleeTiles(lp.sceneX, lp.sceneY)
}
is Object -> when (this.obj) {
is GameObject -> {
val min = this.obj.sceneMinLocation
val max = this.obj.sceneMaxLocation
val points = mutableSetOf<ScenePoint>()
for (y in min.y..max.y) {
for (x in min.x..max.x) {
points.add(Point(x, y))
}
}
points
}
else -> {
val lp = this.obj.localLocation
setOf(Point(lp.sceneX, lp.sceneY))
}
}
}
}
}
fun findTileObject(client: Client, x: Int, y: Int, id: Int): TileObject? {
val scene = client.scene
val tiles = scene.tiles
val plane = tiles[client.plane]
if (x < 0 || y < 0 || x > plane.size || y > plane[0].size) {
return null
}
val tile = tiles[client.plane][x][y] ?: return null
val objects = tile.gameObjects
objects.find({ g -> g?.id == id})?.let { return it }
tile.wallObject?.let {
if (it.id == id) {
return it
}
}
tile.decorativeObject?.let {
if (it.id == id) {
return it
}
}
tile.groundObject?.let {
if (it.id == id) {
return it
}
}
return null
}
fun getHoveredTarget(client: Client): Target? {
val entries = client.menuEntries
if (entries.size == 0) {
throw Error("Entries should never be 0")
}
// TODO: Handle menu open
val entry = entries[entries.size - 1]
if (entry.type == MenuAction.CANCEL) {
return null
}
if (entry.type == MenuAction.WALK) {
return client.selectedSceneTile?.let { Target.Tile(it) }
}
entry.actor?.let { return Target.Actor(it) }
val tileObject = findTileObject(
client,
entry.param0,
entry.param1,
entry.identifier,
) ?: return null
return Target.Object(tileObject)
}
Loading…
Cancel
Save