mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2026-08-28 05:45:10 -06:00
Overlapping NPC and player fix, diagonal dumb pathing dumbness fix
This commit is contained in:
parent
6c01044bdb
commit
2caba4e6dd
2 changed files with 46 additions and 0 deletions
|
|
@ -405,6 +405,16 @@ object CombatMovementIntents {
|
|||
}
|
||||
} else {
|
||||
destinations.add(MovementDestination(targetLocation, pathfinder, allowPartialPath = true))
|
||||
if (chebyshevToFootprint(attacker, target, targetLocation) <= target.size()) {
|
||||
val border = CombatMovementPlanner.borderTiles(target, targetLocation, attacker.size())
|
||||
val walkable = border.filter { RegionManager.isTeleportPermitted(it) }
|
||||
val sorted = walkable.sortedWith(
|
||||
compareBy<Location> { it.getDistance(attacker.location) }.thenBy { it.x }.thenBy { it.y }
|
||||
)
|
||||
for (location in sorted) {
|
||||
destinations.add(MovementDestination(location, pathfinder, allowPartialPath = true))
|
||||
}
|
||||
}
|
||||
}
|
||||
trace.candidateCount += destinations.size
|
||||
return destinations
|
||||
|
|
@ -695,6 +705,12 @@ object CombatMovementIntents {
|
|||
return dx * dx + dy * dy
|
||||
}
|
||||
|
||||
private fun chebyshevToFootprint(attacker: Entity, target: Entity, targetLocation: Location): Int {
|
||||
val closestX = attacker.location.x.coerceIn(targetLocation.x, targetLocation.x + target.size() - 1)
|
||||
val closestY = attacker.location.y.coerceIn(targetLocation.y, targetLocation.y + target.size() - 1)
|
||||
return maxOf(kotlin.math.abs(attacker.location.x - closestX), kotlin.math.abs(attacker.location.y - closestY))
|
||||
}
|
||||
|
||||
private fun shouldUseTargetFootprintRoute(attacker: Entity, target: Entity, pathfinder: Pathfinder): Boolean {
|
||||
if (attacker.properties.combatPulse.style != CombatStyle.MELEE || occupiedTilesOverlap(attacker, target)) {
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -1187,6 +1187,36 @@ class CombatMovementTests {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun dumbMeleeNpcShouldStepToAttackTileWhenDiagonallyAdjacentOnOpenTerrain() {
|
||||
TestUtils.getMockPlayer("combat_open_diagonal_adjacent_target").use { player ->
|
||||
val origin = Location.create(3200, 3600, 0)
|
||||
place(player, origin)
|
||||
|
||||
val npc = NPC.create(100, origin.transform(1, 1, 0))
|
||||
npc.init()
|
||||
try {
|
||||
configureMelee(npc)
|
||||
assertFalse(meleeReach(npc, player), "Precondition: NPC should be diagonally adjacent, not in melee range.")
|
||||
|
||||
npc.attack(player)
|
||||
CombatMovementIntents.clear()
|
||||
CombatMovementIntents.request(npc, player)
|
||||
CombatMovementIntents.resolve()
|
||||
npc.walkingQueue.update()
|
||||
|
||||
assertTrue(
|
||||
meleeReach(npc, player),
|
||||
"A diagonally-adjacent dumb NPC on open terrain should step to an orthogonally-adjacent attack tile."
|
||||
)
|
||||
assertTrue(npc.properties.combatPulse.isAttacking)
|
||||
} finally {
|
||||
npc.clear()
|
||||
CombatMovementIntents.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun dumbMeleeNpcShouldNotSidestepAroundImmediateSafespotBlocker() {
|
||||
TestUtils.getMockPlayer("combat_cardinal_north_safespot_target").use { player ->
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue