untangle abilities

This commit is contained in:
2025-01-22 23:41:53 +09:00
parent 59b5a603a0
commit 441a73355e
2 changed files with 202 additions and 209 deletions
+177 -205
View File
@@ -29,131 +29,6 @@ export default class Ability {
static get noEffect() { return function noEffect() {} } static get noEffect() { return function noEffect() {} }
static straightShot = new Ability({
id: 'straight_shot',
name: 'Straight Shot',
castTime: 0.25,
cooldown: 1,
damage: 83,
radius: 60,
range: 1200,
visualRadius: 20,
speed: 2000,
effect: function straightShotEffect(caster, cursor) {
const ability = this
const straightShotCollision = function straightShotCollision(projectile, collidingEntity) {
if (projectile.game == null) { return }
if (collidingEntity == null) { return }
if (collidingEntity.id == caster.id) { return }
if (collidingEntity.team == (caster.team ?? 'unknown')) { return }
collidingEntity.damage(ability.damage, caster)
projectile.despawn()
}
const projectile = new Projectile({
onCollide: straightShotCollision,
owner: caster.id,
position: caster.position.clone(),
radius: ability.radius,
speed: ability.speed,
visualRadius: ability.visualRadius,
})
projectile.destination = caster.position.clone().add(cursor.clone().sub(caster.position).normalize().multiplyScalar(ability.range + caster.radius))
caster.game?.spawnProjectile(projectile)
caster.cooldown(ability.id)
},
})
static rangedAttack = new Ability({
id: 'ranged_attack',
name: 'Ranged Attack',
castTime: (1.6 * 0.18839),
cooldown: 1.6,
damage: 60,
moveCancelable: true,
radius: 5,
range: 500,
speed: 2000,
effect: function rangedAttackEffect(caster, targetId) {
const ability = this
const target = caster.game?.entities.find((it) => it.id == targetId)
if (target == null) { return }
const rangedAttackAfter = function rangedAttackAfter() {
target.damage(ability.damage, caster)
}
const projectile = new Projectile({
after: rangedAttackAfter,
homingTarget: target,
owner: caster.id,
position: caster.position.clone(),
radius: ability.radius,
speed: ability.speed,
})
caster.game?.spawnProjectile(projectile)
caster.cooldown(ability.id)
},
})
static meleeAttack = new Ability({
id: 'melee_attack',
name: 'Melee Attack',
castTime: (1.4 * 0.22),
cooldown: 1.4,
moveCancelable: true,
damage: 60,
radius: 5,
range: 100,
effect: function meleeAttackEffect(caster, targetId) {
const ability = this
const target = caster.game?.entities.find((it) => it.id == targetId)
if (target == null) { return }
target.damage(ability.damage, caster)
caster.cooldown(ability.id)
},
})
static shieldThrow = new Ability({
id: 'shield_throw',
name: 'Shield Throw',
castTime: 0.25,
cooldown: 5,
radius: 110,
range: 1025,
speed: 2400,
effect: function shieldThrowEffect(caster, cursor) {
const ability = this
const shieldThrowReturn = function shieldThrowReturn(projectile, homingTarget) {
const returnProjectile = new Projectile({
owner: caster.id,
position: projectile.position.clone(),
radius: ability.radius,
speed: ability.speed,
homingTarget: caster,
})
caster.game?.spawnProjectile(returnProjectile)
}
const projectile = new Projectile({
after: shieldThrowReturn,
owner: caster.id,
position: caster.position.clone(),
radius: ability.radius,
speed: ability.speed,
})
projectile.destination = caster.position.clone().add(cursor.clone().sub(caster.position).normalize().multiplyScalar(ability.range + caster.radius))
caster.game?.spawnProjectile(projectile)
caster.cooldown(ability.id)
},
})
static blink = new Ability({ static blink = new Ability({
id: 'blink', id: 'blink',
name: 'Blink', name: 'Blink',
@@ -174,92 +49,13 @@ export default class Ability {
}, },
}) })
static expose = new Ability({
id: 'expose',
name: 'Expose',
castTime: 0.25,
cooldown: 6,
radius: 80,
range: 1200,
speed: 1700,
visualRadius: 50,
effect: function exposeEffect(caster, cursor) {
const ability = this
const exposeCollision = function exposeCollision(projectile, collidingEntity) {
if (projectile.game == null) { return }
if (collidingEntity == null) { return }
if (collidingEntity.team == caster.id) { return }
if (collidingEntity.team == (caster.team ?? 'unknown')) { return }
collidingEntity.applyBuff(Buff.exposed.id, caster.id)
projectile.despawn()
}
const projectile = new Projectile({
onCollide: exposeCollision,
owner: caster.id,
position: caster.position.clone(),
radius: ability.radius,
speed: ability.speed,
visualRadius: ability.visualRadius,
})
projectile.destination = caster.position.clone().add(cursor.clone().sub(caster.position).normalize().multiplyScalar(ability.range + caster.radius))
caster.game?.spawnProjectile(projectile)
caster.cooldown(ability.id)
},
})
static control = new Ability({
id: 'control',
name: 'Control',
castTime: 1,
cooldown: 5,
effect: function controlEffect(caster, cursor) { },
})
static castingVision = new Ability({
id: 'casting_vision',
name: 'Casting Vision',
radius: 300,
duration: 2,
effect: function castingVisionEffect(caster, cursor) {
const ability = this
const currentTick = caster.game?.currentTick ?? 0
const duration = caster.game?.secToTick(ability.duration) ?? 0
const despawnAfter = currentTick + duration
const castingVisionLogic = function castingVisionLogic(projectile) {
const currentTick = projectile.game?.currentTick ?? 0
if (currentTick > despawnAfter) {
projectile.despawn()
}
}
const projectile = new Projectile({
logic: castingVisionLogic,
owner: caster.id,
position: cursor.clone(),
visionRange: ability.radius,
})
caster.game?.spawnProjectile(projectile)
},
})
static circleOfResurrectionChannel = new Ability({
id: 'channel:circle_of_resurrection',
name: 'Channeling: Circle of Resurrection',
castTime: 3,
})
static circleOfResurrection = new Ability({ static circleOfResurrection = new Ability({
id: 'circle_of_resurrection', id: 'circle_of_resurrection',
name: 'Circle of Resurrection', name: 'Circle of Resurrection',
castTime: 0.5, castTime: 0.5,
cooldown: 100, cooldown: 100,
duration: 3, duration: 3,
moveCancelable: true,
radius: 300, radius: 300,
range: 300, range: 300,
effect: function circleOfResurrectionEffect(caster, cursor) { effect: function circleOfResurrectionEffect(caster, cursor) {
@@ -312,4 +108,180 @@ export default class Ability {
} }
}, },
}) })
static circleOfResurrectionChannel = new Ability({
id: 'channel:circle_of_resurrection',
name: 'Channeling: Circle of Resurrection',
castTime: 3,
moveCancelable: true,
})
static control = new Ability({
id: 'control',
name: 'Control',
castTime: 1,
cooldown: 5,
effect: function controlEffect(caster, cursor) { },
})
static expose = new Ability({
id: 'expose',
name: 'Expose',
castTime: 0.25,
cooldown: 6,
radius: 80,
range: 1200,
speed: 1700,
visualRadius: 50,
effect: function exposeEffect(caster, cursor) {
const ability = this
const exposeCollision = function exposeCollision(projectile, collidingEntity) {
if (projectile.game == null) { return }
if (collidingEntity == null) { return }
if (collidingEntity.team == caster.id) { return }
if (collidingEntity.team == (caster.team ?? 'unknown')) { return }
collidingEntity.applyBuff(Buff.exposed.id, caster.id)
projectile.despawn()
}
const projectile = new Projectile({
onCollide: exposeCollision,
owner: caster.id,
position: caster.position.clone(),
radius: ability.radius,
speed: ability.speed,
visualRadius: ability.visualRadius,
})
projectile.destination = caster.position.clone().add(cursor.clone().sub(caster.position).normalize().multiplyScalar(ability.range + caster.radius))
caster.game?.spawnProjectile(projectile)
caster.cooldown(ability.id)
},
})
static meleeAttack = new Ability({
id: 'melee_attack',
name: 'Melee Attack',
castTime: (1.4 * 0.22),
cooldown: 1.4,
moveCancelable: true,
damage: 60,
radius: 5,
range: 100,
effect: function meleeAttackEffect(caster, targetId) {
const ability = this
const target = caster.game?.entities.find((it) => it.id == targetId)
if (target == null) { return }
target.damage(ability.damage, caster)
caster.cooldown(ability.id)
},
})
static rangedAttack = new Ability({
id: 'ranged_attack',
name: 'Ranged Attack',
castTime: (1.6 * 0.18839),
cooldown: 1.6,
damage: 60,
moveCancelable: true,
radius: 5,
range: 500,
speed: 2000,
effect: function rangedAttackEffect(caster, targetId) {
const ability = this
const target = caster.game?.entities.find((it) => it.id == targetId)
if (target == null) { return }
const rangedAttackAfter = function rangedAttackAfter() {
target.damage(ability.damage, caster)
}
const projectile = new Projectile({
after: rangedAttackAfter,
homingTarget: target,
owner: caster.id,
position: caster.position.clone(),
radius: ability.radius,
speed: ability.speed,
})
caster.game?.spawnProjectile(projectile)
caster.cooldown(ability.id)
},
})
static shieldThrow = new Ability({
id: 'shield_throw',
name: 'Shield Throw',
castTime: 0.25,
cooldown: 5,
radius: 110,
range: 1025,
speed: 2400,
effect: function shieldThrowEffect(caster, cursor) {
const ability = this
const shieldThrowReturn = function shieldThrowReturn(projectile, homingTarget) {
const returnProjectile = new Projectile({
owner: caster.id,
position: projectile.position.clone(),
radius: ability.radius,
speed: ability.speed,
homingTarget: caster,
})
caster.game?.spawnProjectile(returnProjectile)
}
const projectile = new Projectile({
after: shieldThrowReturn,
owner: caster.id,
position: caster.position.clone(),
radius: ability.radius,
speed: ability.speed,
})
projectile.destination = caster.position.clone().add(cursor.clone().sub(caster.position).normalize().multiplyScalar(ability.range + caster.radius))
caster.game?.spawnProjectile(projectile)
caster.cooldown(ability.id)
},
})
static straightShot = new Ability({
id: 'straight_shot',
name: 'Straight Shot',
castTime: 0.25,
cooldown: 1,
damage: 83,
radius: 60,
range: 1200,
visualRadius: 20,
speed: 2000,
effect: function straightShotEffect(caster, cursor) {
const ability = this
const straightShotCollision = function straightShotCollision(projectile, collidingEntity) {
if (projectile.game == null) { return }
if (collidingEntity == null) { return }
if (collidingEntity.id == caster.id) { return }
if (collidingEntity.team == (caster.team ?? 'unknown')) { return }
collidingEntity.damage(ability.damage, caster)
projectile.despawn()
}
const projectile = new Projectile({
onCollide: straightShotCollision,
owner: caster.id,
position: caster.position.clone(),
radius: ability.radius,
speed: ability.speed,
visualRadius: ability.visualRadius,
})
projectile.destination = caster.position.clone().add(cursor.clone().sub(caster.position).normalize().multiplyScalar(ability.range + caster.radius))
caster.game?.spawnProjectile(projectile)
caster.cooldown(ability.id)
},
})
} }
+25 -4
View File
@@ -1,7 +1,7 @@
import { Vector2 } from 'three' import { Vector2 } from 'three'
import Ability from './ability.js'
import Buff from './buff.js' import Buff from './buff.js'
import Pathfind from './pathfind.js' import Pathfind from './pathfind.js'
import Projectile from './projectile.js'
import SAT from 'sat' import SAT from 'sat'
import SATX from './satx.js' import SATX from './satx.js'
import Team from './team.js' import Team from './team.js'
@@ -184,7 +184,7 @@ export default class Entity {
if (ability == null) { return } if (ability == null) { return }
if (this.casting != null) { if (this.casting != null) {
const abilityBeingCasted = this.game?.abilities.filter((it) => it.id == this.casting.ability) const abilityBeingCasted = this.game?.abilities.find((it) => it.id == this.casting.ability)
if (abilityBeingCasted != null && abilityBeingCasted.id == ability.id) { if (abilityBeingCasted != null && abilityBeingCasted.id == ability.id) {
return false return false
} }
@@ -229,7 +229,7 @@ export default class Entity {
moveAction(cursor, attack = false) { moveAction(cursor, attack = false) {
if (this.dead) { return } if (this.dead) { return }
if (this.casting != null && this.game?.abilities.filter((it) => it.id == this.casting.ability)?.moveCancelable) { if (this.casting != null && this.game?.abilities.find((it) => it.id == this.casting.ability)?.moveCancelable) {
if (!attack && !(this.casting != null && this.casting.ability == this.abilities[0])) { if (!attack && !(this.casting != null && this.casting.ability == this.abilities[0])) {
this.casting = null this.casting = null
} }
@@ -637,7 +637,28 @@ export default class Entity {
const enemiesNearby = (this.game?.entities ?? []).some((it) => !it.dead && it.team == enemyTeam && it.distanceTo(this.position) <= (it.visionRange + this.radius)) const enemiesNearby = (this.game?.entities ?? []).some((it) => !it.dead && it.team == enemyTeam && it.distanceTo(this.position) <= (it.visionRange + this.radius))
if (enemiesNearby) { if (enemiesNearby) {
Ability.castingVision.effect(this, this.position) const radius = 300
const duration = this.game?.secToTick(2) ?? 0
if (duration <= 0) { return }
const currentTick = this.game?.currentTick ?? 0
const despawnAfter = currentTick + duration
const castingVisionLogic = function castingVisionLogic(projectile) {
const currentTick = projectile.game?.currentTick ?? 0
if (currentTick > despawnAfter) {
projectile.despawn()
}
}
const projectile = new Projectile({
logic: castingVisionLogic,
owner: this.id,
position: this.position.clone(),
visionRange: radius,
})
this.game?.spawnProjectile(projectile)
} }
} }