fix auto-attack targeting
This commit is contained in:
+1
-1
@@ -68,7 +68,7 @@ export default class Ability {
|
||||
let closest = null
|
||||
let distance = Infinity
|
||||
caster.game?.entities.filter((e) => e.team != caster.team && e.position.clone().sub(caster.position).length() < ability.range).forEach((e) => {
|
||||
const newDistance = e.position.clone().sub(cursor).length() < distance
|
||||
const newDistance = e.position.clone().sub(cursor).length()
|
||||
if (newDistance < distance) {
|
||||
closest = e
|
||||
distance = newDistance
|
||||
|
||||
+14
-19
@@ -27,6 +27,7 @@ export default class Entity {
|
||||
#dest = null
|
||||
#game = null
|
||||
#logic = null
|
||||
#move = false
|
||||
#path = []
|
||||
#position = new Vector2()
|
||||
#scheduledPathfinding = null
|
||||
@@ -87,7 +88,7 @@ export default class Entity {
|
||||
this.moveAction(x, y, true)
|
||||
}
|
||||
|
||||
castAction(slot, x, y, clearDestination = true) {
|
||||
castAction(slot, x, y, halt = true) {
|
||||
const ability = this.abilities[slot]
|
||||
|
||||
if (this.casting != null) {
|
||||
@@ -99,8 +100,8 @@ export default class Entity {
|
||||
return false
|
||||
}
|
||||
|
||||
if (clearDestination) {
|
||||
this.#dest = null
|
||||
if (halt) {
|
||||
this.#move = false
|
||||
}
|
||||
|
||||
const cursor = new Vector2(x, y)
|
||||
@@ -117,21 +118,22 @@ export default class Entity {
|
||||
}
|
||||
|
||||
haltAction() {
|
||||
this.#dest = null
|
||||
this.#move = false
|
||||
}
|
||||
|
||||
moveAction(x, y, attack = false) {
|
||||
this.#attack = attack
|
||||
if (this.casting != null && (!this.#attack || this.casting.ability.id != this.abilities[0].id)) {
|
||||
this.casting = null
|
||||
}
|
||||
|
||||
this.#attack = attack
|
||||
this.#move = true
|
||||
this.#dest = SATX.fixCollisions(new Vector2(x, y), this.collidables(), this.radius, this.game?.width, this.game?.height)
|
||||
}
|
||||
|
||||
stopAction() {
|
||||
this.casting = null
|
||||
this.#dest = null
|
||||
this.#move = true
|
||||
this.#attack = false
|
||||
}
|
||||
|
||||
@@ -160,14 +162,6 @@ export default class Entity {
|
||||
return entityColliders.concat(terrainColliders)
|
||||
}
|
||||
|
||||
// DEPRECATED: hulls were a failed concept for position fixing
|
||||
collidableHulls() {
|
||||
const entityColliders = (this.game?.entities ?? []).filter((e) => e.id != this.id).map((e) => e.collider)
|
||||
const terrainColliders = (this.game?.terrains ?? []).map((t) => t.hull)
|
||||
|
||||
return entityColliders.concat(terrainColliders)
|
||||
}
|
||||
|
||||
cooldown(id) {
|
||||
this.cooldowns[id] = this.game?.currentTick ?? 0
|
||||
}
|
||||
@@ -207,7 +201,7 @@ export default class Entity {
|
||||
this.fixPosition()
|
||||
}
|
||||
|
||||
takeStep(distanceTraveled = 0) {
|
||||
move(distanceTraveled = 0) {
|
||||
if (this.casting != null) { return false }
|
||||
|
||||
if (this.#attack && this.game?.entities.some((e) => e.team != this.team && e.position.clone().sub(this.position).length() < this.abilities[0].range)) {
|
||||
@@ -221,8 +215,8 @@ export default class Entity {
|
||||
return true
|
||||
}
|
||||
|
||||
if (this.#dest == null) { return false }
|
||||
|
||||
if (!this.#move || this.#dest == null) { return false }
|
||||
|
||||
const collidables = this.collidables()
|
||||
const fixedDest = SATX.clamp(SATX.fixCollisions(this.#dest, collidables, this.radius), this.game?.width, this.game?.height, this.radius)
|
||||
const tunnel = SATX.entityTunnel(this.#position.x, this.#position.y, fixedDest.x, fixedDest.y, this.radius)
|
||||
@@ -268,10 +262,11 @@ export default class Entity {
|
||||
if (this.position.equals(destination)) {
|
||||
this.#path = this.#path.slice(1)
|
||||
if (this.#path.length > 0) {
|
||||
this.takeStep(distance)
|
||||
this.move(distance)
|
||||
}
|
||||
else {
|
||||
this.#dest = null
|
||||
this.#move = false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,7 +274,7 @@ export default class Entity {
|
||||
|
||||
update() {
|
||||
this.cast()
|
||||
this.takeStep()
|
||||
this.move()
|
||||
this.fixPosition()
|
||||
if (this.#logic != null) {
|
||||
this.#logic()
|
||||
|
||||
+3
-78
@@ -35,11 +35,6 @@ app.ws('/ws', async (req, res) => {
|
||||
}
|
||||
console.log(message)
|
||||
|
||||
// DEPRECATED: teleporting is now directly possible via Ability...
|
||||
if (message.action == 'teleport') {
|
||||
entity.teleport(new Vector2(message.x, message.y))
|
||||
}
|
||||
|
||||
if (message.action == 'attack') {
|
||||
entity.attackAction(message.x, message.y)
|
||||
}
|
||||
@@ -62,79 +57,6 @@ app.ws('/ws', async (req, res) => {
|
||||
})
|
||||
})
|
||||
|
||||
// function testScenario() {
|
||||
// const entity1 = new Entity()
|
||||
// entity1.id = '1'
|
||||
// entity1.teleport(new Vector2(200, 500))
|
||||
// entity1.radius = 50
|
||||
// entity1.maxHealth = 100
|
||||
// entity1.health = 80
|
||||
// game.spawnEntity(entity1)
|
||||
|
||||
// const entity2 = new Entity()
|
||||
// entity2.id = '2'
|
||||
// entity2.teleport(new Vector2(110, 110))
|
||||
// entity2.radius = 50
|
||||
// entity2.maxHealth = 50
|
||||
// entity2.health = 50
|
||||
// game.spawnEntity(entity2)
|
||||
|
||||
// const horseshoe = new Terrain([
|
||||
// { x: 400, y: 200 },
|
||||
// { x: 600, y: 200 },
|
||||
// { x: 700, y: 300 },
|
||||
// { x: 650, y: 600 },
|
||||
// { x: 400, y: 600 },
|
||||
// { x: 400, y: 450 },
|
||||
// { x: 600, y: 500 },
|
||||
// { x: 600, y: 300 },
|
||||
// { x: 400, y: 300 },
|
||||
// ])
|
||||
// horseshoe.id = 'horseshoe'
|
||||
// game.addTerrain(horseshoe)
|
||||
|
||||
// const stopsign = new Terrain([
|
||||
// { x: 800, y: 800 },
|
||||
// { x: 900, y: 900 },
|
||||
// { x: 900, y: 1000 },
|
||||
// { x: 800, y: 1100 },
|
||||
// { x: 800, y: 1100 },
|
||||
// { x: 700, y: 1100 },
|
||||
// { x: 600, y: 1000 },
|
||||
// { x: 600, y: 900 },
|
||||
// { x: 700, y: 800 },
|
||||
// ])
|
||||
// stopsign.id = 'stopsign'
|
||||
// game.addTerrain(stopsign)
|
||||
|
||||
// const box = new Terrain([
|
||||
// { x: 1200, y: 700 },
|
||||
// { x: 1200, y: 800 },
|
||||
// { x: 1300, y: 800 },
|
||||
// { x: 1300, y: 700 },
|
||||
// ])
|
||||
// box.id = 'box'
|
||||
// game.addTerrain(box)
|
||||
|
||||
// const diamond = new Terrain([
|
||||
// { x: 1000, y: 300 },
|
||||
// { x: 1100, y: 400 },
|
||||
// { x: 1000, y: 500 },
|
||||
// { x: 900, y: 400 },
|
||||
// ])
|
||||
// diamond.id = 'diamond'
|
||||
// game.addTerrain(diamond)
|
||||
|
||||
// const pole = new Terrain([
|
||||
// { x: 400, y: 1000 },
|
||||
// { x: 410, y: 1000 },
|
||||
// { x: 410, y: 1010 },
|
||||
// { x: 400, y: 1010 },
|
||||
// ])
|
||||
// pole.id = 'pole'
|
||||
// game.addTerrain(pole)
|
||||
// }
|
||||
|
||||
function laneScenario() {
|
||||
const entity1 = new Entity({
|
||||
id: '1',
|
||||
@@ -197,6 +119,9 @@ function laneScenario() {
|
||||
if (entity.id == '2') {
|
||||
entity.teleport(new Vector2(1600, 1800))
|
||||
}
|
||||
if (entity.id == '3') {
|
||||
entity.teleport(new Vector2(1800, 1600))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-7
@@ -4,19 +4,26 @@ import PriorityQueue from './priority-queue.js'
|
||||
import SATX from './satx.js'
|
||||
|
||||
export default class Pathfind {
|
||||
static precision = 0.001
|
||||
static multiplier = 1000 // (1 / this.precision)
|
||||
static precision = 0.01
|
||||
static multiplier = 1000000 // (1 / this.precision) * 10^expected_digit_count / 10
|
||||
|
||||
static key2(a, b) {
|
||||
return `${a},${b}`
|
||||
}
|
||||
|
||||
// TODO: Value exceeds safe integer limit: collisions cause waypointing anomalies
|
||||
// Fowler-Noll-Vo hash prime and offset basis for small keyspaces
|
||||
static floatKey4(a, b, c, d) {
|
||||
return Math.floor(a * Pathfind.multiplier) +
|
||||
Math.floor(b * Pathfind.multiplier) * Pathfind.multiplier +
|
||||
Math.floor(c * Pathfind.multiplier) * Pathfind.multiplier ** 2 +
|
||||
Math.floor(d * Pathfind.multiplier) * Pathfind.multiplier ** 3
|
||||
const prime = 16777619
|
||||
let result = 2166136261
|
||||
result ^= Math.floor(a * Pathfind.multiplier)
|
||||
result *= prime
|
||||
result ^= Math.floor(b * Pathfind.multiplier)
|
||||
result *= prime
|
||||
result ^= Math.floor(c * Pathfind.multiplier)
|
||||
result *= prime
|
||||
result ^= Math.floor(d * Pathfind.multiplier)
|
||||
result *= prime
|
||||
return result
|
||||
}
|
||||
|
||||
static uniqueWaypoints(waypoints) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import QuickHull from 'quickhull' // DEPRECATED: hulls were a failed concept for position fixing
|
||||
import SAT from 'sat'
|
||||
import { Shape, ShapeUtils, Vector2 } from 'three'
|
||||
|
||||
@@ -26,7 +25,6 @@ export default class Terrain {
|
||||
}
|
||||
|
||||
get colliders() { return this.#colliders }
|
||||
get hull() { return this.#hull } // DEPRECATED: hulls were a failed concept for position fixing
|
||||
get unadjustedWaypoints() { return this.#unadjustedWaypoints }
|
||||
get vertices() { return this.#vertices }
|
||||
|
||||
@@ -76,16 +74,6 @@ export default class Terrain {
|
||||
}
|
||||
|
||||
this.#colliders = ShapeUtils.triangulateShape(points.shape, points.holes).map(indicesToPolygon)
|
||||
this.#calculateHull()
|
||||
}
|
||||
|
||||
// DEPRECATED: hulls were a failed concept for position fixing
|
||||
#calculateHull() {
|
||||
const vertices = QuickHull(this.#vertices.map((v) => ({ x: v.x, y: v.y }))).map((v) => new Vector2(v.x, v.y))
|
||||
const first = vertices.at(0)
|
||||
const satPoints = [new SAT.Vector(...first.toArray()), ...vertices.slice(1).map((v) => new SAT.Vector(...v.clone(first).sub(first).toArray()))]
|
||||
|
||||
this.#hull = new SAT.Polygon(satPoints[0], [new SAT.Vector(), ...satPoints.slice(1)])
|
||||
}
|
||||
|
||||
#calculatePosition() {
|
||||
|
||||
Reference in New Issue
Block a user