fix projectiles colliding with dead entities
This commit is contained in:
+37
-22
@@ -217,47 +217,62 @@ export default class Ability {
|
|||||||
name: 'Shield Throw',
|
name: 'Shield Throw',
|
||||||
castTime: 0.25,
|
castTime: 0.25,
|
||||||
cooldown: 5,
|
cooldown: 5,
|
||||||
|
damage: 90,
|
||||||
deceleratePerTick: 90,
|
deceleratePerTick: 90,
|
||||||
radius: 110,
|
radius: 110,
|
||||||
range: 1025,
|
range: 1025,
|
||||||
speed: 2400,
|
speed: 2400,
|
||||||
effect: function shieldThrowEffect(caster, cursor) {
|
effect: function shieldThrowEffect(caster, cursor) {
|
||||||
const ability = this
|
const ability = this
|
||||||
|
const amount = ability.damage
|
||||||
|
let onTheWayBack = false
|
||||||
|
let collided = new Set()
|
||||||
|
|
||||||
const accelerateLogic = function accelerateLogic() {
|
const shieldThrowCollision = function shieldThrowCollision(projectile, collidingEntity) {
|
||||||
const projectile = this
|
if (collidingEntity == null) { return }
|
||||||
projectile.speed += ability.deceleratePerTick
|
if (collidingEntity.id == caster.id) { return }
|
||||||
}
|
if (caster.team == null || collidingEntity.team == null || collidingEntity.team != caster.team) { return }
|
||||||
|
const entityId = collidingEntity.id
|
||||||
|
|
||||||
const decelerateLogic = function decelerateLogic() {
|
if (!collided.has(entityId)) {
|
||||||
const projectile = this
|
collidingEntity.heal(amount, caster)
|
||||||
if (projectile.speed - ability.deceleratePerTick >= ability.deceleratePerTick) {
|
collided.add(entityId)
|
||||||
projectile.speed = projectile.speed - ability.deceleratePerTick
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const shieldThrowReturn = function shieldThrowReturn(projectile, homingTarget) {
|
const accelerateLogic = function accelerateLogic(projectile) {
|
||||||
const returnProjectile = new Projectile({
|
if (onTheWayBack) {
|
||||||
homingTarget: caster,
|
projectile.speed += ability.deceleratePerTick
|
||||||
logic: accelerateLogic,
|
}
|
||||||
owner: caster.id,
|
else {
|
||||||
position: projectile.position.clone(),
|
if (projectile.speed - ability.deceleratePerTick >= ability.deceleratePerTick) {
|
||||||
radius: ability.radius,
|
projectile.speed = projectile.speed - ability.deceleratePerTick
|
||||||
speed: ability.deceleratePerTick,
|
}
|
||||||
visionRange: ability.radius,
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
caster.game?.spawnProjectile(returnProjectile)
|
const shieldThrowSecondAfter = function shieldThrowSecondAfter(projectile, homingTarget) {
|
||||||
|
caster.heal(amount, caster)
|
||||||
|
caster.heal(amount, caster) // NOTE: duplicated on purpose
|
||||||
|
}
|
||||||
|
|
||||||
|
const shieldThrowFirstAfter = function shieldThrowFirstAfter(projectile, homingTarget) {
|
||||||
|
projectile.destination = null
|
||||||
|
projectile.homingTarget = caster
|
||||||
|
onTheWayBack = true
|
||||||
|
collided.clear()
|
||||||
|
projectile.after = shieldThrowSecondAfter
|
||||||
}
|
}
|
||||||
|
|
||||||
const projectile = new Projectile({
|
const projectile = new Projectile({
|
||||||
after: shieldThrowReturn,
|
after: shieldThrowFirstAfter,
|
||||||
logic: decelerateLogic,
|
logic: accelerateLogic,
|
||||||
|
onCollide: shieldThrowCollision,
|
||||||
owner: caster.id,
|
owner: caster.id,
|
||||||
position: caster.position.clone(),
|
position: caster.position.clone(),
|
||||||
radius: ability.radius,
|
radius: ability.radius,
|
||||||
speed: ability.speed,
|
speed: ability.speed,
|
||||||
visionRange: ability.radius,
|
visionRange: ability.radius * 1.5,
|
||||||
})
|
})
|
||||||
|
|
||||||
projectile.destination = caster.position.clone().add(cursor.clone().sub(caster.position).normalize().multiplyScalar(ability.range + caster.radius))
|
projectile.destination = caster.position.clone().add(cursor.clone().sub(caster.position).normalize().multiplyScalar(ability.range + caster.radius))
|
||||||
|
|||||||
+8
-3
@@ -177,6 +177,7 @@ export default class Entity {
|
|||||||
this.moveAction(cursor, true)
|
this.moveAction(cursor, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: buffer skill inputs
|
||||||
castAction(slot, cursor, halt = false) {
|
castAction(slot, cursor, halt = false) {
|
||||||
if (this.dead) { return }
|
if (this.dead) { return }
|
||||||
|
|
||||||
@@ -295,10 +296,13 @@ export default class Entity {
|
|||||||
this.cooldowns[id] = this.game?.currentTick ?? 0
|
this.cooldowns[id] = this.game?.currentTick ?? 0
|
||||||
}
|
}
|
||||||
|
|
||||||
closestTargetTo(cursor, range) {
|
closestTargetTo(cursor, range, targetAllies = false) {
|
||||||
const entities = this.game?.entities
|
const entities = this.game?.entities
|
||||||
if (entities == null) { return }
|
if (entities == null) { return }
|
||||||
const targetsInRange = entities.filter((it) => this.team != it.team && it.distanceTo(cursor) <= range + this.radius + it.radius)
|
const targetsInRange = targetAllies
|
||||||
|
? entities.filter((it) => this.team == it.team && it.distanceTo(cursor) <= range + this.radius + it.radius)
|
||||||
|
: entities.filter((it) => this.team != it.team && it.distanceTo(cursor) <= range + this.radius + it.radius)
|
||||||
|
|
||||||
if (targetsInRange.length < 1) { return }
|
if (targetsInRange.length < 1) { return }
|
||||||
|
|
||||||
const absoluteClosestTarget = targetsInRange.reduce((e1, e2) => (e1?.distanceTo(cursor) ?? Infinity) < e2.distanceTo(cursor) ? e1 : e2, null)
|
const absoluteClosestTarget = targetsInRange.reduce((e1, e2) => (e1?.distanceTo(cursor) ?? Infinity) < e2.distanceTo(cursor) ? e1 : e2, null)
|
||||||
@@ -321,6 +325,7 @@ export default class Entity {
|
|||||||
return entitiesAndTerrains.filter((it) => !it.dead && it.collision && !((this.ghosting && it.ghostable) || (this.ghostable && it.ghosting)) && SATX.bboxCheck(bbox, it.bbox))
|
return entitiesAndTerrains.filter((it) => !it.dead && it.collision && !((this.ghosting && it.ghostable) || (this.ghostable && it.ghosting)) && SATX.bboxCheck(bbox, it.bbox))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: add shielding logic
|
||||||
damage(amount, source = null) {
|
damage(amount, source = null) {
|
||||||
if (this.dead) { return }
|
if (this.dead) { return }
|
||||||
|
|
||||||
@@ -399,7 +404,7 @@ export default class Entity {
|
|||||||
return this.buffs.some((it) => it.id == id) && this.game?.buffs.some((it) => it.id == id)
|
return this.buffs.some((it) => it.id == id) && this.game?.buffs.some((it) => it.id == id)
|
||||||
}
|
}
|
||||||
|
|
||||||
heal(amount) {
|
heal(amount, _source) {
|
||||||
if (this.dead) { return }
|
if (this.dead) { return }
|
||||||
|
|
||||||
this.health = Math.min(Math.max(0, this.health + amount), this.maxHealth)
|
this.health = Math.min(Math.max(0, this.health + amount), this.maxHealth)
|
||||||
|
|||||||
+2
-2
@@ -22,8 +22,8 @@ export class Dungeon {
|
|||||||
game.addTerrain(new Terrain([new Vector2(2000, 1500), new Vector2(2500, 1000), new Vector2(2500, 1500)], false))
|
game.addTerrain(new Terrain([new Vector2(2000, 1500), new Vector2(2500, 1000), new Vector2(2500, 1500)], false))
|
||||||
game.spawnEntity(new Entity(Template.player({ id: '6', spawnPosition: new Vector2(2400, 1400), team: enemy, logic: castQ })))
|
game.spawnEntity(new Entity(Template.player({ id: '6', spawnPosition: new Vector2(2400, 1400), team: enemy, logic: castQ })))
|
||||||
|
|
||||||
game.spawnEntity(new Entity(Template.player({ id: '1', spawnPosition: new Vector2(1500, 700), team, dead: true })))
|
game.spawnEntity(new Entity(Template.player({ id: '1', spawnPosition: new Vector2(200, 1300), team, health: 10 })))
|
||||||
game.spawnEntity(new Entity(Template.player({ id: '2', spawnPosition: new Vector2(200, 1300), team, health: 10 })))
|
game.spawnEntity(new Entity(Template.player({ id: '2', spawnPosition: new Vector2(1500, 700), team, dead: true })))
|
||||||
|
|
||||||
game.spawnEntity(new Entity(Template.basilisk({ id: 'boss', spawnPosition: new Vector2(2200, 750), team: Team.neutral })))
|
game.spawnEntity(new Entity(Template.basilisk({ id: 'boss', spawnPosition: new Vector2(2200, 750), team: Team.neutral })))
|
||||||
|
|
||||||
|
|||||||
+5
-2
@@ -123,6 +123,9 @@ export default class Projectile {
|
|||||||
this.#after(this, this.#homingTarget)
|
this.#after(this, this.#homingTarget)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.destination == null) { return }
|
||||||
|
if (!this.position.equals(this.destination)) { return }
|
||||||
|
|
||||||
this.despawn()
|
this.despawn()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +134,7 @@ export default class Projectile {
|
|||||||
|
|
||||||
const bbox = this.bbox
|
const bbox = this.bbox
|
||||||
const entitiesAndTerrains = this.game?.entities ?? []
|
const entitiesAndTerrains = this.game?.entities ?? []
|
||||||
const bboxCheckedObstacles = entitiesAndTerrains.filter((it) => SATX.bboxCheck(bbox, it.bbox))
|
const bboxCheckedObstacles = entitiesAndTerrains.filter((it) => !it.dead && SATX.bboxCheck(bbox, it.bbox))
|
||||||
if (bboxCheckedObstacles.length > 0) {
|
if (bboxCheckedObstacles.length > 0) {
|
||||||
const collider = this.collider()
|
const collider = this.collider()
|
||||||
const colliding = bboxCheckedObstacles.filter((it) => it.colliders().some((c) => SATX.collideObject(collider, c)))
|
const colliding = bboxCheckedObstacles.filter((it) => it.colliders().some((c) => SATX.collideObject(collider, c)))
|
||||||
@@ -155,7 +158,7 @@ export default class Projectile {
|
|||||||
if (this.#onCollide != null) {
|
if (this.#onCollide != null) {
|
||||||
const bbox = Entity.tunnelBbox(prevPos.x, prevPos.y, this.position.x, this.position.y, this.radius)
|
const bbox = Entity.tunnelBbox(prevPos.x, prevPos.y, this.position.x, this.position.y, this.radius)
|
||||||
const entitiesAndTerrains = this.game?.entities ?? []
|
const entitiesAndTerrains = this.game?.entities ?? []
|
||||||
const bboxCheckedObstacles = entitiesAndTerrains.filter((it) => SATX.bboxCheck(bbox, it.bbox))
|
const bboxCheckedObstacles = entitiesAndTerrains.filter((it) => !it.dead && SATX.bboxCheck(bbox, it.bbox))
|
||||||
if (bboxCheckedObstacles.length > 0) {
|
if (bboxCheckedObstacles.length > 0) {
|
||||||
const collider = Entity.tunnelCollider(prevPos.x, prevPos.y, this.position.x, this.position.y, this.radius)
|
const collider = Entity.tunnelCollider(prevPos.x, prevPos.y, this.position.x, this.position.y, this.radius)
|
||||||
const colliding = bboxCheckedObstacles.filter((it) => it.colliders().some((c) => SATX.collideObject(collider, c)))
|
const colliding = bboxCheckedObstacles.filter((it) => it.colliders().some((c) => SATX.collideObject(collider, c)))
|
||||||
|
|||||||
Reference in New Issue
Block a user