Fix Grabej

This commit is contained in:
2026-01-27 20:28:18 +03:00
parent e8181493bd
commit 09acbecdf1
2 changed files with 104 additions and 16 deletions

View File

@ -1187,6 +1187,14 @@
} }
} }
// Если это Грабеж, но spellTarget не enemy_player, все равно активируем режим выбора цели
if (meta.spellEffect === 'steal_cards' && !meta.spellTarget) {
spellMode = { active: true, handIndex: handIndex, cardId: wrap.dataset.cardId, spellTarget: 'enemy_player' };
$('spell-mode')?.classList.remove('hidden');
renderGame(state);
return;
}
if (!needTarget) { if (!needTarget) {
if (typeof window.Sounds !== 'undefined') window.Sounds.playCard(); if (typeof window.Sounds !== 'undefined') window.Sounds.playCard();
socket.emit('playSpell', { handIndex: handIndex }); socket.emit('playSpell', { handIndex: handIndex });
@ -2238,14 +2246,25 @@
const hintEl = $('steal-cards-hint'); const hintEl = $('steal-cards-hint');
const targetSelect = $('steal-target-select'); const targetSelect = $('steal-target-select');
if (!deckList || !selectedEl || !confirmBtn) return; if (!deckList || !selectedEl || !confirmBtn) {
console.error('Steal cards modal elements not found');
return;
}
const currentState = gameState || state;
if (!currentState || !currentState.players) {
console.error('Invalid game state for steal cards modal');
return;
}
// Если противник уже выбран, показываем его колоду // Если противник уже выбран, показываем его колоду
if (stealCardsMode.targetPlayerIndex !== null) { if (stealCardsMode.targetPlayerIndex !== null) {
// Обновляем колоду из актуального gameState // Обновляем колоду из актуального gameState
const targetPlayer = state.players[stealCardsMode.targetPlayerIndex]; const targetPlayer = currentState.players[stealCardsMode.targetPlayerIndex];
if (targetPlayer && targetPlayer.deck) { if (targetPlayer && targetPlayer.deck) {
stealCardsMode.targetDeck = [...targetPlayer.deck]; stealCardsMode.targetDeck = [...targetPlayer.deck];
} else {
console.warn('Target player not found or deck is empty:', stealCardsMode.targetPlayerIndex);
} }
if (stealCardsMode.targetDeck.length === 0) { if (stealCardsMode.targetDeck.length === 0) {
@ -2263,39 +2282,65 @@
} }
deckList.innerHTML = stealCardsMode.targetDeck.map((cardId, idx) => { deckList.innerHTML = stealCardsMode.targetDeck.map((cardId, idx) => {
const meta = cardDb[cardId]; const cardDbToUse = currentState?.cardDb || cardDb;
if (!meta) return ''; const meta = cardDbToUse[cardId];
if (!meta) {
console.warn('Card not found in cardDb:', cardId, 'Available keys:', Object.keys(cardDbToUse).slice(0, 10));
return `<div class="card-wrap steal-deck-card" data-card-id="${cardId}" data-deck-index="${idx}" style="width: 100px; height: 140px; cursor: pointer; border: 2px solid red; position: relative; z-index: 10;">
<div style="padding: 0.5rem; text-align: center; font-size: 0.7rem; color: #ff6b6b;">Карта ${cardId}</div>
</div>`;
}
const isSelected = stealCardsMode.selectedIndices.includes(idx); const isSelected = stealCardsMode.selectedIndices.includes(idx);
const cost = meta.cost || 0; const cost = meta.cost || 0;
const attack = meta.attack !== undefined ? meta.attack : ''; const attack = meta.attack !== undefined ? meta.attack : '';
const health = meta.health !== undefined ? meta.health : ''; const health = meta.health !== undefined ? meta.health : '';
const stats = meta.type === 'minion' ? `<div class="card-stats"><span class="atk">${attack}</span><span class="hp">${health}</span></div>` : ''; const stats = meta.type === 'minion' ? `<div class="card-stats"><span class="atk">${attack}</span><span class="hp">${health}</span></div>` : '';
const costDisplay = `<div class="card-cost-wrap"><span class="card-cost">${cost}</span></div>`; const costDisplay = `<div class="card-cost-wrap"><span class="card-cost">${cost}</span></div>`;
const art = getCardArt ? getCardArt(meta) : '✦'; const art = typeof getCardArt === 'function' ? getCardArt(meta) : '✦';
return `<div class="card-wrap steal-deck-card ${isSelected ? 'selected' : ''}" data-card-id="${cardId}" data-deck-index="${idx}" style="width: 100px; height: 140px; cursor: pointer;"> return `<div class="card-wrap steal-deck-card ${isSelected ? 'selected' : ''}" data-card-id="${cardId}" data-deck-index="${idx}" style="width: 100px; height: 140px; cursor: pointer; position: relative; z-index: 10;">
<div class="card faction-${meta.faction || 'neutral'}"> <div class="card faction-${meta.faction || 'neutral'}">
<div class="card-art">${art}</div> <div class="card-art">${art}</div>
<div class="card-info"> <div class="card-info">
<div class="card-name" style="font-size: 0.7rem;">${escapeHtml(meta.name)}</div> <div class="card-name" style="font-size: 0.7rem;">${escapeHtml(meta.name || cardId)}</div>
${stats} ${stats}
${costDisplay} ${costDisplay}
</div> </div>
</div> </div>
</div>`; </div>`;
}).filter(Boolean).join(''); }).join('');
$all('.steal-deck-card').forEach(card => { $all('.steal-deck-card').forEach(card => {
card.onclick = function() { const handleCardClick = function(e) {
e.preventDefault();
e.stopPropagation();
const idx = parseInt(card.dataset.deckIndex, 10); const idx = parseInt(card.dataset.deckIndex, 10);
if (isNaN(idx)) {
console.warn('Invalid deck index:', card.dataset.deckIndex);
return;
}
const selectedIdx = stealCardsMode.selectedIndices.indexOf(idx); const selectedIdx = stealCardsMode.selectedIndices.indexOf(idx);
if (selectedIdx >= 0) { if (selectedIdx >= 0) {
stealCardsMode.selectedIndices.splice(selectedIdx, 1); stealCardsMode.selectedIndices.splice(selectedIdx, 1);
} else if (stealCardsMode.selectedIndices.length < 2) { } else if (stealCardsMode.selectedIndices.length < 2) {
stealCardsMode.selectedIndices.push(idx); stealCardsMode.selectedIndices.push(idx);
} }
showStealCardsModal(state, data); const currentState = gameState || state;
showStealCardsModal(currentState, data || {
targetPlayerIndex: stealCardsMode.targetPlayerIndex,
targetPlayerName: currentState?.players?.[stealCardsMode.targetPlayerIndex]?.name || `Игрок ${stealCardsMode.targetPlayerIndex + 1}`,
targetDeckSize: stealCardsMode.targetDeck.length,
maxCards: Math.min(2, stealCardsMode.targetDeck.length)
});
}; };
card.onclick = handleCardClick;
card.style.pointerEvents = 'auto';
if (isTouchDevice()) {
card.ontouchstart = function(e) {
e.preventDefault();
handleCardClick(e);
};
}
}); });
selectedEl.innerHTML = stealCardsMode.selectedIndices.length ? stealCardsMode.selectedIndices.map(idx => { selectedEl.innerHTML = stealCardsMode.selectedIndices.length ? stealCardsMode.selectedIndices.map(idx => {
@ -2330,9 +2375,14 @@
hintEl.textContent = 'Выберите противника для грабежа'; hintEl.textContent = 'Выберите противника для грабежа';
} }
const enemies = state.players.filter((p, i) => i !== state.yourIndex && p.health > 0 && p.deck && p.deck.length > 0); const enemies = currentState.players.filter((p, i) => i !== currentState.yourIndex && p.health > 0 && p.deck && p.deck.length > 0);
if (enemies.length === 0) {
if (hintEl) hintEl.textContent = 'Нет доступных противников для грабежа';
targetSelect.innerHTML = '';
return;
}
targetSelect.innerHTML = enemies.map((enemy, idx) => { targetSelect.innerHTML = enemies.map((enemy, idx) => {
const enemyIdx = state.players.indexOf(enemy); const enemyIdx = currentState.players.indexOf(enemy);
return `<div class="steal-target-option" data-player-index="${enemyIdx}" style="padding: 1rem; margin: 0.5rem 0; background: rgba(0,0,0,0.3); border: 2px solid rgba(0,180,255,0.3); border-radius: 8px; cursor: pointer; transition: all 0.2s;"> return `<div class="steal-target-option" data-player-index="${enemyIdx}" style="padding: 1rem; margin: 0.5rem 0; background: rgba(0,0,0,0.3); border: 2px solid rgba(0,180,255,0.3); border-radius: 8px; cursor: pointer; transition: all 0.2s;">
<div style="font-weight: 700; color: var(--cyan);">${escapeHtml(enemy.name || `Игрок ${enemyIdx + 1}`)}</div> <div style="font-weight: 700; color: var(--cyan);">${escapeHtml(enemy.name || `Игрок ${enemyIdx + 1}`)}</div>
<div style="font-size: 0.85rem; color: #94a3b8; margin-top: 0.25rem;">Колода: ${enemy.deck.length} карт</div> <div style="font-size: 0.85rem; color: #94a3b8; margin-top: 0.25rem;">Колода: ${enemy.deck.length} карт</div>
@ -2340,21 +2390,40 @@
}).join(''); }).join('');
$all('.steal-target-option').forEach(option => { $all('.steal-target-option').forEach(option => {
option.onclick = function() { const handleOptionClick = function(e) {
e.preventDefault();
e.stopPropagation();
const playerIdx = parseInt(option.dataset.playerIndex, 10); const playerIdx = parseInt(option.dataset.playerIndex, 10);
const targetPlayer = state.players[playerIdx]; if (isNaN(playerIdx)) return;
const currentState = gameState || state;
if (!currentState || !currentState.players) {
console.error('Invalid state when selecting target player');
return;
}
const targetPlayer = currentState.players[playerIdx];
if (targetPlayer && targetPlayer.deck && targetPlayer.deck.length > 0) { if (targetPlayer && targetPlayer.deck && targetPlayer.deck.length > 0) {
stealCardsMode.targetPlayerIndex = playerIdx; stealCardsMode.targetPlayerIndex = playerIdx;
// Получаем актуальную колоду из gameState
stealCardsMode.targetDeck = targetPlayer.deck ? [...targetPlayer.deck] : []; stealCardsMode.targetDeck = targetPlayer.deck ? [...targetPlayer.deck] : [];
showStealCardsModal(state, { console.log('Selected target player:', playerIdx, 'Deck size:', stealCardsMode.targetDeck.length);
showStealCardsModal(currentState, {
targetPlayerIndex: playerIdx, targetPlayerIndex: playerIdx,
targetPlayerName: targetPlayer.name || `Игрок ${playerIdx + 1}`, targetPlayerName: targetPlayer.name || `Игрок ${playerIdx + 1}`,
targetDeckSize: targetPlayer.deck.length, targetDeckSize: targetPlayer.deck.length,
maxCards: Math.min(2, targetPlayer.deck.length) maxCards: Math.min(2, targetPlayer.deck.length)
}); });
} else {
console.warn('Target player has no deck or is invalid:', playerIdx, targetPlayer);
} }
}; };
option.onclick = handleOptionClick;
option.style.pointerEvents = 'auto';
option.style.cursor = 'pointer';
if (isTouchDevice()) {
option.ontouchstart = function(e) {
e.preventDefault();
handleOptionClick(e);
};
}
}); });
} }

View File

@ -1937,11 +1937,20 @@ html, body {
.steal-target-select { .steal-target-select {
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.steal-target-option {
pointer-events: auto !important;
cursor: pointer;
user-select: none;
-webkit-user-select: none;
}
.steal-target-option:hover { .steal-target-option:hover {
background: rgba(0,180,255,0.2) !important; background: rgba(0,180,255,0.2) !important;
border-color: var(--cyan) !important; border-color: var(--cyan) !important;
transform: scale(1.02); transform: scale(1.02);
} }
.steal-target-option:active {
transform: scale(0.98);
}
.steal-deck-list { .steal-deck-list {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
@ -1957,14 +1966,24 @@ html, body {
cursor: pointer; cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s; transition: transform 0.2s, box-shadow 0.2s;
border: 2px solid transparent; border: 2px solid transparent;
position: relative;
z-index: 10;
pointer-events: auto !important;
user-select: none;
-webkit-user-select: none;
} }
.steal-deck-card:hover { .steal-deck-card:hover {
transform: scale(1.1); transform: scale(1.1);
box-shadow: 0 0 15px rgba(0,180,255,0.5); box-shadow: 0 0 15px rgba(0,180,255,0.5);
z-index: 15;
} }
.steal-deck-card.selected { .steal-deck-card.selected {
border-color: var(--cyan); border-color: var(--cyan);
box-shadow: 0 0 20px rgba(0,180,255,0.7); box-shadow: 0 0 20px rgba(0,180,255,0.7);
transform: scale(1.05);
}
.steal-deck-card:active {
transform: scale(0.95);
} }
.steal-selected { .steal-selected {
min-height: 80px; min-height: 80px;