feat: добавлена визуальная индикация выстрелов на портах

Реализована подсветка портов при выстрелах от ESP:

**Типы подсветки:**
- 🔴 Красная (miss) - выстрел на пустом порту (notshot) или ошибка (shotErr/shotErrA)
- 🟡 Желтая (shot) - начало выстрела (startshot)
- 🟢 Зеленая (hit) - успешный выстрел (shot)

**Изменения:**

1. **useWebSocket.js:**
   - Добавлены команды выстрелов в список системных сообщений
   - shot, startshot, notshot, shotErr, shotErrA

2. **useGamePorts.js (handlePortMessage):**
   - case 'notshot' → highlight: 'miss' (1 сек)
   - case 'startshot' → highlight: 'shot' (2 сек)
   - case 'shot' → highlight: 'hit' (1 сек) + обновление патронов
   - case 'shotErr/shotErrA' → highlight: 'miss' (2 сек)

**Логика:**
- Попытка выстрела БЕЗ игры → красная подсветка 1 сек
- Начало выстрела → желтая подсветка 2 сек
- Успешный выстрел → зеленая подсветка 1 сек
- Ошибка выстрела → красная подсветка 2 сек
- Автоочистка через setTimeout

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-13 12:50:13 +03:00
parent 5bfa281e63
commit 7b08d68141
2 changed files with 65 additions and 0 deletions

View File

@@ -1051,6 +1051,67 @@ export function useGamePorts() {
} }
break break
case 'notshot':
// Попытка выстрела на пустом порту - красная подсветка
logger.info(`🔴 notshot на порту ${portNumber} - пустой порт`)
ports[portNumber].highlight = 'miss'
// Автоочистка через 1 секунду
setTimeout(() => {
if (ports[portNumber].highlight === 'miss') {
ports[portNumber].highlight = null
}
}, 1000)
break
case 'startshot':
// Начало выстрела - желтая подсветка
logger.info(`🟡 startshot на порту ${portNumber}`)
ports[portNumber].highlight = 'shot'
// Автоочистка через 2 секунды (если не придет shot)
setTimeout(() => {
if (ports[portNumber].highlight === 'shot') {
ports[portNumber].highlight = null
}
}, 2000)
break
case 'shot':
// Успешный выстрел - зеленая подсветка
logger.info(`🟢 shot на порту ${portNumber}, осталось патронов: ${data.patr}`)
ports[portNumber].highlight = 'hit'
// Обновляем патроны если пришли в data
if (data.patr !== undefined) {
ports[portNumber].patr = data.patr
}
if (data.patrOk !== undefined) {
ports[portNumber].patrOk = data.patrOk
}
// Автоочистка через 1 секунду
setTimeout(() => {
if (ports[portNumber].highlight === 'hit') {
ports[portNumber].highlight = null
}
}, 1000)
break
case 'shotErr':
case 'shotErrA':
// Ошибка выстрела (осечка или замыкание) - красная подсветка
logger.info(`🔴 ${data.do} на порту ${portNumber}`)
ports[portNumber].highlight = 'miss'
// Автоочистка через 2 секунды
setTimeout(() => {
if (ports[portNumber].highlight === 'miss') {
ports[portNumber].highlight = null
}
}, 2000)
break
default: default:
logger.warn('Обрабатываю неизвестное сообщение порта как общее обновление:', data.do) logger.warn('Обрабатываю неизвестное сообщение порта как общее обновление:', data.do)
// Пытаемся обработать как общее обновление порта // Пытаемся обработать как общее обновление порта

View File

@@ -55,6 +55,8 @@ export function useWebSocket() {
data.do === 'start' || data.do === 'endGame' || data.do === 'pause' || data.do === 'resume' || data.do === 'start' || data.do === 'endGame' || data.do === 'pause' || data.do === 'resume' ||
data.do === 'bonus' || data.do === 'deleteGamer' || data.do === 'cancelGame' || data.do === 'bonus' || data.do === 'deleteGamer' || data.do === 'cancelGame' ||
data.do === 'move' || data.do === 'moveGamer' || data.do === 'move' || data.do === 'moveGamer' ||
data.do === 'shot' || data.do === 'startshot' || data.do === 'notshot' ||
data.do === 'shotErr' || data.do === 'shotErrA' ||
data.do === 'sharikStartGame' || data.do === 'sharikEndGame' || data.do === 'sharikStartGame' || data.do === 'sharikEndGame' ||
data.do === 'sharikCancelGame' || data.do === 'sharikDeleteGamer') { data.do === 'sharikCancelGame' || data.do === 'sharikDeleteGamer') {
// Передаем системные сообщения в глобальный обработчик // Передаем системные сообщения в глобальный обработчик
@@ -66,6 +68,8 @@ export function useWebSocket() {
if (data.do === 'start' || data.do === 'endGame' || data.do === 'pause' || if (data.do === 'start' || data.do === 'endGame' || data.do === 'pause' ||
data.do === 'resume' || data.do === 'bonus' || data.do === 'deleteGamer' || data.do === 'cancelGame' || data.do === 'resume' || data.do === 'bonus' || data.do === 'deleteGamer' || data.do === 'cancelGame' ||
data.do === 'move' || data.do === 'moveGamer' || data.do === 'move' || data.do === 'moveGamer' ||
data.do === 'shot' || data.do === 'startshot' || data.do === 'notshot' ||
data.do === 'shotErr' || data.do === 'shotErrA' ||
data.do === 'sharikStartGame' || data.do === 'sharikEndGame' || data.do === 'sharikStartGame' || data.do === 'sharikEndGame' ||
data.do === 'sharikCancelGame' || data.do === 'sharikDeleteGamer') { data.do === 'sharikCancelGame' || data.do === 'sharikDeleteGamer') {
// Продолжаем выполнение для promise обработки // Продолжаем выполнение для promise обработки