From 55e5e8117c2d13042f9011a9402121814f68be2b Mon Sep 17 00:00:00 2001 From: Thayol Date: Thu, 23 Jan 2025 11:17:16 +0900 Subject: [PATCH] exclude dead entities from auto-attack target selection --- public/client.js | 90 +++++++++++++++++++++++++---------------------- public/index.html | 45 ++++-------------------- src/ability.js | 2 +- src/entity.js | 4 +-- src/game.js | 2 +- 5 files changed, 58 insertions(+), 85 deletions(-) diff --git a/public/client.js b/public/client.js index 6aff89e..861dd8d 100644 --- a/public/client.js +++ b/public/client.js @@ -467,36 +467,50 @@ function connectWebSocket() { if (playerId != null) { const player = state.entities.find((e) => e.id == playerId) if (player != null) { - for (let abilityIndex = 0; abilityIndex < 7; abilityIndex++) { - const abilityKey = ['a', 'q', 'w', 'e', 'r', 'd', 'f'][abilityIndex] - if (player.abilities[abilityKey] != null) { - const abilityId = player.abilities[abilityKey] - const ability = state.abilities.find((it) => it.id == abilityId) - const lastCast = player.cooldowns[ability.id] ?? -Infinity - const cooldownDuration = (ability.cooldown * state.tickRate) ?? 0 - const remainingCooldown = (lastCast + cooldownDuration) - state.currentTick - let cssPercentage = '100%' - let text = '' - if (remainingCooldown > 0) { - const cooldownPercentage = 1 - (remainingCooldown / cooldownDuration) - cssPercentage = `${Math.round(100 * cooldownPercentage)}%` - if (remainingCooldown / state.tickRate <= 5) { - text = `${(Math.round(10 * remainingCooldown / state.tickRate) / 10).toFixed(1)}` - } - else { - text = `${Math.round(remainingCooldown / state.tickRate)}` - } - } + const playerAbilities = player.abilities - if (player.casting?.ability == ability.id) { - document.getElementById(`ability-${abilityIndex}-cooldown`).style.clipPath = `polygon(50% 0%, 0% 100%, 100% 100%)` // triangle + let abilitiesHTML = '' + + let i = 0 + for (const [abilityKey, _abilityId] of Object.entries(playerAbilities)) { + i++ + const abilityKeyText = abilityKey.toUpperCase() + const abilityTemplate = `
${abilityKeyText}
` + abilitiesHTML += abilityTemplate + } + + if (document.getElementById(`abilities`).innerHTML != abilitiesHTML) { + document.getElementById(`abilities`).innerHTML = abilitiesHTML + } + + let abilityIndex = 0 + for (const [_abilityKey, abilityId] of Object.entries(playerAbilities)) { + abilityIndex++ + const ability = state.abilities.find((it) => it.id == abilityId) + const lastCast = player.cooldowns[ability.id] ?? -Infinity + const cooldownDuration = (ability.cooldown * state.tickRate) ?? 0 + const remainingCooldown = (lastCast + cooldownDuration) - state.currentTick + let cssPercentage = '100%' + let text = '' + if (remainingCooldown > 0) { + const cooldownPercentage = 1 - (remainingCooldown / cooldownDuration) + cssPercentage = `${Math.round(100 * cooldownPercentage)}%` + if (remainingCooldown / state.tickRate <= 5) { + text = `${(Math.round(10 * remainingCooldown / state.tickRate) / 10).toFixed(1)}` } else { - document.getElementById(`ability-${abilityIndex}-cooldown`).style.clipPath = `polygon(0 ${cssPercentage}, 100% ${cssPercentage}, 100% 100%, 0 100%)` + text = `${Math.round(remainingCooldown / state.tickRate)}` } - - document.getElementById(`ability-${abilityIndex}-cooldown-text`).innerHTML = text } + + if (player.casting?.ability == ability.id) { + document.getElementById(`ability-${abilityIndex}-cooldown`).style.clipPath = `polygon(50% 0%, 0% 100%, 100% 100%)` // triangle + } + else { + document.getElementById(`ability-${abilityIndex}-cooldown`).style.clipPath = `polygon(0 ${cssPercentage}, 100% ${cssPercentage}, 100% 100%, 0 100%)` + } + + document.getElementById(`ability-${abilityIndex}-cooldown-text`).innerHTML = text } let buffs = `` @@ -577,24 +591,14 @@ window.addEventListener('load', () => { websocket.send(JSON.stringify({ action: 'halt', id: playerId })) } - if (event.code == 'KeyQ') { - websocket.send(JSON.stringify({ action: 'cast', slot: 'q', id: playerId, x, y })) - } - if (event.code == 'KeyW') { - websocket.send(JSON.stringify({ action: 'cast', slot: 'w', id: playerId, x, y })) - } - if (event.code == 'KeyE') { - websocket.send(JSON.stringify({ action: 'cast', slot: 'e', id: playerId, x, y })) - } - if (event.code == 'KeyR') { - websocket.send(JSON.stringify({ action: 'cast', slot: 'r', id: playerId, x, y })) - } - if (event.code == 'KeyD') { - websocket.send(JSON.stringify({ action: 'cast', slot: 'd', id: playerId, x, y })) - } - if (event.code == 'KeyF') { - websocket.send(JSON.stringify({ action: 'cast', slot: 'f', id: playerId, x, y })) - } + const alreadyBound = ['A', 'X', 'S', 'H'] + const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('').forEach((letter) => { + if (alreadyBound.includes(letter)) { return } + + if (event.code == `Key${letter}`) { + websocket.send(JSON.stringify({ action: 'cast', slot: letter.toLowerCase(), id: playerId, x, y })) + } + }) } }) diff --git a/public/index.html b/public/index.html index 8883ce4..ec296b2 100644 --- a/public/index.html +++ b/public/index.html @@ -58,12 +58,12 @@ border-right: none; } - .hud { + .abilities { + display: none; position: fixed; gap: 10px; padding: 15px; padding-bottom: 10px; - display: flex; inset: auto 0 0 0; width: fit-content; margin: auto; @@ -74,6 +74,10 @@ border-bottom: none; } + .abilities:has(.ability) { + display: flex; + } + .ability { position: relative; flex: 1 0 0; @@ -178,42 +182,7 @@
-
-
- A -
-
-
-
- Q -
-
-
-
- W -
-
-
-
- E -
-
-
-
- R -
-
-
-
- D -
-
-
-
- F -
-
-
+
diff --git a/src/ability.js b/src/ability.js index 4687ce5..ecb00a0 100644 --- a/src/ability.js +++ b/src/ability.js @@ -85,7 +85,7 @@ export default class Ability { const entities = projectile.game?.entities ?? [] const pos = projectile.position projectile.despawn() - const nearbyDeadTeammates = entities.filter((it) => it.dead && it.team == team) + const nearbyDeadTeammates = entities.filter((it) => it.dead && it.team == team && it.distanceTo(pos) <= ability.radius) const closestDeadTeammate = nearbyDeadTeammates.reduce((e1, e2) => (e1?.distanceTo(pos) ?? Infinity) < e2.distanceTo(pos) ? e1 : e2, null) if (closestDeadTeammate != null) { closestDeadTeammate.revive(closestDeadTeammate.maxHealth / 4) diff --git a/src/entity.js b/src/entity.js index 6a61030..a6dc525 100644 --- a/src/entity.js +++ b/src/entity.js @@ -300,8 +300,8 @@ export default class Entity { const entities = this.game?.entities if (entities == null) { return } 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) + ? entities.filter((it) => !it.dead && this.team == it.team && it.distanceTo(cursor) <= range + this.radius + it.radius) + : entities.filter((it) => !it.dead && this.team != it.team && it.distanceTo(cursor) <= range + this.radius + it.radius) if (targetsInRange.length < 1) { return } diff --git a/src/game.js b/src/game.js index 393decd..b8aa223 100644 --- a/src/game.js +++ b/src/game.js @@ -41,7 +41,7 @@ export default class Game { if (options.action == 'attack') { entity.attackAction(new Vector2(options.x, options.y)) } if (options.action == 'cast') { entity.castAction(options.slot, new Vector2(options.x, options.y)) } - if (options.action == 'halt') { entity.haltAction(), delay } + if (options.action == 'halt') { entity.haltAction() } if (options.action == 'stop') { entity.stopAction() } if (options.action == 'move') { entity.moveAction(new Vector2(options.x, options.y)) } }