diff --git a/public/js/ui.js b/public/js/ui.js
index bf2149d..ae35db4 100644
--- a/public/js/ui.js
+++ b/public/js/ui.js
@@ -14,6 +14,7 @@
status: document.getElementById('player-status'),
effectsContainer: document.getElementById('player-effects'),
buffsList: document.getElementById('player-effects')?.querySelector('.player-buffs'),
+ // ИСПРАВЛЕНО: Селектор для списка дебаффов игрока
debuffsList: document.getElementById('player-effects')?.querySelector('.player-debuffs')
},
opponent: { // Панель для персонажа-противника ЭТОГО клиента
@@ -24,7 +25,9 @@
resourceFill: document.getElementById('opponent-resource-fill'), resourceText: document.getElementById('opponent-resource-text'),
status: document.getElementById('opponent-status'),
effectsContainer: document.getElementById('opponent-effects'),
+ // ИСПРАВЛЕНО: Селектор для списка баффов оппонента
buffsList: document.getElementById('opponent-effects')?.querySelector('.opponent-buffs'),
+ // ИСПРАВЛЕНО: Селектор для списка дебаффов оппонента
debuffsList: document.getElementById('opponent-effects')?.querySelector('.opponent-debuffs')
},
controls: {
@@ -39,8 +42,7 @@
gameOver: {
screen: document.getElementById('game-over-screen'),
message: document.getElementById('result-message'),
- // restartButton: document.getElementById('restart-game-button'), // Старый ID, заменен
- returnToMenuButton: document.getElementById('return-to-menu-button'), // Новый ID
+ returnToMenuButton: document.getElementById('return-to-menu-button'),
modalContent: document.getElementById('game-over-screen')?.querySelector('.modal-content')
},
gameHeaderTitle: document.querySelector('.game-header h1'),
@@ -55,7 +57,7 @@
if (!logListElement) return;
const li = document.createElement('li');
li.textContent = message;
- const config = window.GAME_CONFIG || {}; // Получаем конфиг из глобальной области
+ const config = window.GAME_CONFIG || {};
// Формируем класс для лога на основе типа (используем константы из конфига или фоллбэк)
const logTypeClass = config[`LOG_TYPE_${type.toUpperCase()}`] ? `log-${config[`LOG_TYPE_${type.toUpperCase()}`]}` : `log-${type}`;
li.className = logTypeClass;
@@ -70,63 +72,69 @@
// Базовая проверка наличия необходимых элементов и данных
if (!elements || !elements.hpFill || !elements.hpText || !elements.resourceFill || !elements.resourceText || !elements.status || !fighterState || !fighterBaseStats) {
- // console.warn(`updateFighterPanelUI: Отсутствуют элементы UI, состояние бойца или базовые статы для панели ${panelRole}.`);
// Если панель должна быть видима, но нет данных, можно ее скрыть или показать плейсхолдер
if (elements && elements.panel && elements.panel.style.display !== 'none') {
// console.warn(`updateFighterPanelUI: Нет данных для видимой панели ${panelRole}.`);
// elements.panel.style.opacity = '0.5'; // Пример: сделать полупрозрачной, если нет данных
}
+ // ВАЖНО: Очистить содержимое панели, если данных нет.
+ if (elements) {
+ if(elements.name) elements.name.innerHTML = (panelRole === 'player') ? ' Ожидание данных...' : ' Ожидание игрока...';
+ if(elements.hpText) elements.hpText.textContent = 'N/A';
+ if(elements.resourceText) elements.resourceText.textContent = 'N/A';
+ if(elements.status) elements.status.textContent = 'Неизвестно';
+ if(elements.buffsList) elements.buffsList.innerHTML = 'Нет';
+ if(elements.debuffsList) elements.debuffsList.innerHTML = 'Нет';
+ if(elements.avatar) elements.avatar.src = 'images/default_avatar.png';
+ if(panelRole === 'player' && uiElements.playerResourceTypeIcon) uiElements.playerResourceTypeIcon.className = 'fas fa-question';
+ if(panelRole === 'opponent' && uiElements.opponentResourceTypeIcon) uiElements.opponentResourceTypeIcon.className = 'fas fa-question';
+ if(panelRole === 'player' && uiElements.playerResourceBarContainer) uiElements.playerResourceBarContainer.classList.remove('mana', 'stamina', 'dark-energy');
+ if(panelRole === 'opponent' && uiElements.opponentResourceBarContainer) uiElements.opponentResourceBarContainer.classList.remove('mana', 'stamina', 'dark-energy');
+ if(elements.panel) elements.panel.style.opacity = '0.5'; // Затемняем
+ }
return;
}
- // Если панель была полупрозрачной (из-за отсутствия данных), а теперь данные есть, делаем ее полностью видимой
- // if (elements.panel && elements.panel.style.opacity !== '1' && fighterState && fighterBaseStats) {
- // elements.panel.style.opacity = '1';
- // }
+ if (elements.panel) elements.panel.style.opacity = '1'; // Делаем видимой, если данные есть
// Обновление имени и иконки персонажа
if (elements.name) {
let iconClass = 'fa-question'; // Иконка по умолчанию
- // let accentColor = 'var(--text-muted)'; // Цвет по умолчанию - теперь берется из CSS через классы иконок
const characterKey = fighterBaseStats.characterKey;
// Определяем класс иконки в зависимости от персонажа
- if (characterKey === 'elena') { iconClass = 'fa-hat-wizard icon-player'; } // icon-player имеет цвет через CSS
- else if (characterKey === 'almagest') { iconClass = 'fa-staff-aesculapius icon-almagest'; } // icon-almagest имеет цвет через CSS
- else if (characterKey === 'balard') { iconClass = 'fa-khanda icon-opponent'; } // icon-opponent имеет цвет через CSS
+ if (characterKey === 'elena') { iconClass = 'fa-hat-wizard icon-player'; }
+ else if (characterKey === 'almagest') { iconClass = 'fa-staff-aesculapius icon-almagest'; }
+ else if (characterKey === 'balard') { iconClass = 'fa-khanda icon-opponent'; }
else { /* console.warn(`updateFighterPanelUI: Неизвестный characterKey "${characterKey}" для иконки имени.`); */ }
- // Обновляем innerHTML имени, включая иконку и текст. Добавляем "(Вы)" для управляемого персонажа.
let nameHtml = ` ${fighterBaseStats.name || 'Неизвестно'}`;
if (isControlledByThisClient) nameHtml += " (Вы)";
elements.name.innerHTML = nameHtml;
- // Цвет имени теперь задается CSS через классы icon-player/opponent/almagest, примененные к самой иконке
- // elements.name.style.color = accentColor; // Эту строку можно удалить, если цвет задан через CSS
}
// Обновление аватара
if (elements.avatar && fighterBaseStats.avatarPath) {
elements.avatar.src = fighterBaseStats.avatarPath;
// Обновляем рамку аватара в зависимости от персонажа
- elements.avatar.classList.remove('avatar-elena', 'avatar-almagest', 'avatar-balard'); // Убираем старые классы
- elements.avatar.classList.add(`avatar-${fighterBaseStats.characterKey}`); // Добавляем класс для текущего персонажа
+ elements.avatar.classList.remove('avatar-elena', 'avatar-almagest', 'avatar-balard');
+ elements.avatar.classList.add(`avatar-${fighterBaseStats.characterKey}`);
} else if (elements.avatar) {
- elements.avatar.src = 'images/default_avatar.png'; // Запасной аватар
- elements.avatar.classList.remove('avatar-elena', 'avatar-almagest', 'avatar-balard'); // Убираем старые классы
+ elements.avatar.src = 'images/default_avatar.png';
+ elements.avatar.classList.remove('avatar-elena', 'avatar-almagest', 'avatar-balard');
}
// Обновление полос здоровья и ресурса
- const maxHp = Math.max(1, fighterBaseStats.maxHp); // Избегаем деления на ноль
+ const maxHp = Math.max(1, fighterBaseStats.maxHp);
const maxRes = Math.max(1, fighterBaseStats.maxResource);
const currentHp = Math.max(0, fighterState.currentHp);
const currentRes = Math.max(0, fighterState.currentResource);
elements.hpFill.style.width = `${(currentHp / maxHp) * 100}%`;
- elements.hpText.textContent = `${Math.round(currentHp)} / ${fighterBaseStats.maxHp}`;
- // ИСПРАВЛЕНО: Убрано округление для отображения текущего ресурса
+ elements.hpText.textContent = `${Math.round(currentHp)} / ${fighterBaseStats.maxHp}`; // Здоровье округляем
elements.resourceFill.style.width = `${(currentRes / maxRes) * 100}%`;
- elements.resourceText.textContent = `${currentRes} / ${fighterBaseStats.maxResource}`; // <-- ИСПРАВЛЕНО
+ elements.resourceText.textContent = `${currentRes} / ${fighterBaseStats.maxResource}`; // Ресурс не округляем
// Обновление типа ресурса и иконки (mana/stamina/dark-energy)
@@ -134,124 +142,158 @@
const resourceIconElementToUpdate = (panelRole === 'player') ? uiElements.playerResourceTypeIcon : uiElements.opponentResourceTypeIcon;
if (resourceBarContainerToUpdate && resourceIconElementToUpdate) {
- resourceBarContainerToUpdate.classList.remove('mana', 'stamina', 'dark-energy'); // Сначала удаляем все классы ресурсов
- let resourceClass = 'mana'; let iconClass = 'fa-flask'; // Значения по умолчанию (для Маны)
+ resourceBarContainerToUpdate.classList.remove('mana', 'stamina', 'dark-energy');
+ let resourceClass = 'mana'; let iconClass = 'fa-flask';
if (fighterBaseStats.resourceName === 'Ярость') { resourceClass = 'stamina'; iconClass = 'fa-fire-alt'; }
- else if (fighterBaseStats.resourceName === 'Темная Энергия') { resourceClass = 'dark-energy'; iconClass = 'fa-skull'; } // Или другую иконку для темной энергии
+ else if (fighterBaseStats.resourceName === 'Темная Энергия') { resourceClass = 'dark-energy'; iconClass = 'fa-skull'; } // или fa-wand-magic-sparkles, fa-star-half-alt и т.д.
+ else { console.warn(`updateFighterPanelUI: Unknown resource name "${fighterBaseStats.resourceName}" for icon/color.`); iconClass = 'fa-question-circle'; }
resourceBarContainerToUpdate.classList.add(resourceClass);
- resourceIconElementToUpdate.className = `fas ${iconClass}`; // Обновляем класс иконки
+ resourceIconElementToUpdate.className = `fas ${iconClass}`;
}
// Обновление статуса (Готов/Защищается)
const statusText = fighterState.isBlocking ? (config.STATUS_BLOCKING || 'Защищается') : (config.STATUS_READY || 'Готов(а)');
elements.status.textContent = statusText;
- elements.status.classList.toggle(config.CSS_CLASS_BLOCKING || 'blocking', fighterState.isBlocking); // Применяем класс для стилизации статуса "Защищается"
+ elements.status.classList.toggle(config.CSS_CLASS_BLOCKING || 'blocking', fighterState.isBlocking);
// Обновление подсветки и рамки панели (в зависимости от персонажа)
if (elements.panel) {
- let borderColorVar = 'var(--panel-border)'; // Цвет по умолчанию
- // Снимаем все старые классы для рамки
+ let borderColorVar = 'var(--panel-border)';
elements.panel.classList.remove('panel-elena', 'panel-almagest', 'panel-balard');
- // Применяем класс для рамки в зависимости от персонажа
- if (fighterBaseStats.characterKey === 'elena') { elements.panel.classList.add('panel-elena'); borderColorVar = 'var(--accent-player)'; } // Цвет рамки через CSS переменную
- else if (fighterBaseStats.characterKey === 'almagest') { elements.panel.classList.add('panel-almagest'); borderColorVar = 'var(--accent-almagest)'; } // Цвет рамки через CSS переменную
- else if (fighterBaseStats.characterKey === 'balard') { elements.panel.classList.add('panel-balard'); borderColorVar = 'var(--accent-opponent)'; } // Цвет рамки через CSS переменную
+ if (fighterBaseStats.characterKey === 'elena') { elements.panel.classList.add('panel-elena'); borderColorVar = 'var(--accent-player)'; }
+ else if (fighterBaseStats.characterKey === 'almagest') { elements.panel.classList.add('panel-almagest'); borderColorVar = 'var(--accent-almagest)'; }
+ else if (fighterBaseStats.characterKey === 'balard') { elements.panel.classList.add('panel-balard'); borderColorVar = 'var(--accent-opponent)'; }
+ else { console.warn(`updateFighterPanelUI: Unknown character key "${fighterBaseStats.characterKey}" for panel border color.`); }
+
- // Обновляем тень (свечение). Цвет свечения тоже может быть переменной.
let glowColorVar = 'rgba(0, 0, 0, 0.4)'; // Базовая тень
if (fighterBaseStats.characterKey === 'elena') glowColorVar = 'var(--panel-glow-player)';
- else if (fighterBaseStats.characterKey === 'almagest' || fighterBaseStats.characterKey === 'balard') glowColorVar = 'var(--panel-glow-opponent)'; // Используем одну тень для всех оппонентов (Балард/Альмагест)
+ // В твоем CSS --panel-glow-opponent используется для обоих Баларда и Альмагест
+ else if (fighterBaseStats.characterKey === 'almagest' || fighterBaseStats.characterKey === 'balard') glowColorVar = 'var(--panel-glow-opponent)';
- // Устанавливаем рамку и тень
elements.panel.style.borderColor = borderColorVar;
- // Используем переменную для свечения. Базовая тень inset оставлена как есть.
elements.panel.style.boxShadow = `0 0 15px ${glowColorVar}, inset 0 0 10px rgba(0, 0, 0, 0.3)`;
}
}
+ /**
+ * Генерирует HTML для списка эффектов.
+ * @param {Array