From e1533ea03d6ab21ba0407f301a51bd38322ab7db Mon Sep 17 00:00:00 2001 From: Bonchellon Date: Tue, 27 Jan 2026 22:57:31 +0300 Subject: [PATCH] 123 --- public/game.js | 92 ++++++++++++++++++++++++++++++----------------- public/index.html | 36 +++++++++++++------ public/styles.css | 20 +++++++++-- server.js | 1 + 4 files changed, 102 insertions(+), 47 deletions(-) diff --git a/public/game.js b/public/game.js index fbc5ee7..af5354b 100644 --- a/public/game.js +++ b/public/game.js @@ -282,11 +282,12 @@ yourIndex = -1; const spectatorBadge = $('spectator-badge'); if (!spectatorBadge) { - const badge = document.createElement('div'); - badge.id = 'spectator-badge'; - badge.style.cssText = 'position: fixed; top: 1rem; right: 1rem; background: rgba(212,168,75,0.9); color: #000; padding: 0.5rem 1rem; border-radius: 8px; font-weight: 700; z-index: 200;'; - badge.textContent = '👁 НАБЛЮДАТЕЛЬ'; - document.body.appendChild(badge); + const badge = document.createElement('div'); + badge.id = 'spectator-badge'; + badge.style.cssText = 'position: fixed; top: 1rem; right: 1rem; background: rgba(212,168,75,0.9); color: #000; padding: 0.5rem 1rem; border-radius: 8px; font-weight: 700; z-index: 200; display: flex; align-items: center; gap: 0.5rem;'; + badge.innerHTML = 'НАБЛЮДАТЕЛЬ'; + document.body.appendChild(badge); + if (typeof lucide !== 'undefined') lucide.createIcons(); } } else { const spectatorBadge = $('spectator-badge'); @@ -367,6 +368,11 @@ resetBtn.classList.toggle('hidden', state.yourIndex !== 0); } bindGameEvents(state); + + // Обновляем иконки Lucide после рендеринга + if (typeof lucide !== 'undefined') { + setTimeout(() => lucide.createIcons(), 100); + } } function showGameOver(state) { @@ -435,18 +441,22 @@ const isCurrent = state.currentPlayerIndex === i; const isDead = p.health <= 0 || p.isDead; const name = p.name || 'Игрок ' + (i + 1); + const isAI = p.isAI || false; const minions = (p.board || []).map((m, j) => renderBoardMinion(m, i, j, state, true, false)); const heroBar = renderHeroTarget(i, state); const heroDrop = renderHeroDropZone(i, state); const canSteal = !state.isSpectator && state.currentPlayerIndex === state.yourIndex && spellMode.active && spellMode.cardId && cardDb[spellMode.cardId]?.spellEffect === 'steal_cards'; return `
-
${escapeHtml(name)}${isDead ? ' ' : ''}
+
+ ${isAI ? '' : ''} + ${escapeHtml(name)}${isDead ? ' ' : ''} +
- ❤ ${p.health ?? 30} - ${(p.armor || 0) > 0 ? `🛡 ${p.armor}` : ''} - 🔵 ${p.mana ?? 0}/${p.maxMana ?? 0} - ${p.deck && p.deck.length > 0 ? `📚 ${p.deck.length}` : ''} + ${p.health ?? 30} + ${(p.armor || 0) > 0 ? `${p.armor}` : ''} + ${p.mana ?? 0}/${p.maxMana ?? 0} + ${p.deck && p.deck.length > 0 ? `${p.deck.length}` : ''}
${heroDrop}${heroBar}${minions.join('')}
`; @@ -526,7 +536,7 @@ const attackerName = attackerCard?.name || 'Миньон'; const targetName = targetCard?.name || 'Миньон'; const damage = logEntry.damage || attackerMinion?.attack || 0; - text = who(attackerIdx) + ' → ' + attackerName + ' ⚔ атакует ' + targetName + ' (' + damage + ' урона) → ' + who(targetIdx); + text = who(attackerIdx) + ' → ' + attackerName + ' атакует ' + targetName + ' (' + damage + ' урона) → ' + who(targetIdx); } } else if (logEntry.type === 'attackHero' && logEntry.fromPlayer !== undefined && logEntry.toPlayer !== undefined) { const attackerPlayer = state.players[logEntry.fromPlayer]; @@ -537,10 +547,10 @@ const attackerCard = cardDb[attackerMinion?.cardId]; const attackerName = attackerCard?.name || 'Миньон'; const damage = logEntry.damage || attackerMinion?.attack || 0; - text = who(logEntry.fromPlayer) + ' → ' + attackerName + ' ⚔ атакует героя ' + who(logEntry.toPlayer) + ' (' + damage + ' урона)!'; + text = who(logEntry.fromPlayer) + ' → ' + attackerName + ' атакует героя ' + who(logEntry.toPlayer) + ' (' + damage + ' урона)!'; } else { const damage = logEntry.damage || 0; - text = who(logEntry.fromPlayer) + ' ⚔ атакует героя ' + who(logEntry.toPlayer) + ' (' + damage + ' урона)!'; + text = who(logEntry.fromPlayer) + ' атакует героя ' + who(logEntry.toPlayer) + ' (' + damage + ' урона)!'; } } } else if (logEntry.type === 'spell' && logEntry.fromPlayer !== undefined && logEntry.toPlayer !== undefined) { @@ -1112,7 +1122,7 @@ var heroCls = 'drop-target drop-target-hero' + (spellHero ? ' spell-target' : '') + (heroAb ? ' hero-ability-target' : ''); var title = spellHero ? 'Цель заклинания' : (heroAb ? 'Цель геройской способности' : 'Перетащи сюда миньона для атаки по лидеру'); return '
' - + '' + + '' + '' + escapeHtml(name) + '' + '
'; } @@ -1124,7 +1134,7 @@ return `
-
+
${escapeHtml(name)} (лидер)
${p?.health ?? 30}
@@ -2183,7 +2193,8 @@ const statusColor = room.gameStarted ? 'var(--amber)' : 'var(--cyan)'; const playersText = room.players.length > 0 ? room.players.join(', ') : 'Нет игроков'; const canJoin = !room.gameStarted && room.playerCount < room.maxPlayers; - const actionText = room.gameStarted ? '👁 Наблюдать' : (canJoin ? '▶ Подключиться' : 'Полная'); + const actionIcon = room.gameStarted ? '' : (canJoin ? '' : ''); + const actionText = room.gameStarted ? 'Наблюдать' : (canJoin ? 'Подключиться' : 'Полная'); const actionClass = room.gameStarted ? 'btn-ghost' : (canJoin ? 'btn-primary' : 'btn-ghost'); const actionDisabled = !room.gameStarted && !canJoin; @@ -2196,33 +2207,38 @@
Игроки: ${room.playerCount}/${room.maxPlayers}
${room.spectators > 0 ? `
Наблюдателей: ${room.spectators}
` : ''} - ${room.hasAI ? '
🤖 ИИ
' : ''} + ${room.hasAI ? '
ИИ
' : ''}
${escapeHtml(playersText)}
- +
`; }).join(''); // Обработчики подключения к комнатам $all('.room-item button').forEach(btn => { - btn.addEventListener('click', function() { - const code = this.dataset.roomCode; - const name = ($('browse-name')?.value || '').trim() || 'Игрок'; - if (!code) return; - - if (!socket || !socket.connected) { - const url = window.location.origin; - connect(url); - socket.once('connect', () => { + btn.addEventListener('click', function() { + const code = this.dataset.roomCode; + const name = ($('browse-name')?.value || '').trim() || 'Игрок'; + if (!code) return; + + if (!socket || !socket.connected) { + const url = window.location.origin; + connect(url); + socket.once('connect', () => { + socket.emit('joinRoom', { code, name }); + }); + } else { socket.emit('joinRoom', { code, name }); - }); - } else { - socket.emit('joinRoom', { code, name }); - } + } + }); }); - }); - }; + + // Обновляем иконки Lucide после создания кнопок + if (typeof lucide !== 'undefined') { + setTimeout(() => lucide.createIcons(), 100); + } + }; $('btn-instructions')?.addEventListener('click', () => { $('instructions-overlay')?.classList.remove('hidden'); }); @@ -2803,9 +2819,19 @@ if (window.Music) { window.Music.init(); } + // Инициализация Lucide Icons после загрузки DOM + if (typeof lucide !== 'undefined') { + lucide.createIcons(); + // Обновляем иконки при изменении DOM + const observer = new MutationObserver(() => { + lucide.createIcons(); + }); + observer.observe(document.body, { childList: true, subtree: true }); + } }); } else { init(); + if (typeof lucide !== 'undefined') lucide.createIcons(); if (window.Music) { window.Music.init(); } diff --git a/public/index.html b/public/index.html index 9a7e1fc..b4f0677 100644 --- a/public/index.html +++ b/public/index.html @@ -11,6 +11,7 @@ + @@ -29,8 +30,8 @@

PvP до 4 игроков · Игра с ИИ · Работает через Radmin VPN

- - + +
@@ -91,7 +92,7 @@