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 (typeof window.Sounds !== 'undefined') window.Sounds.playCard();
socket.emit('playSpell', { handIndex: handIndex });
@ -2238,14 +2246,25 @@
const hintEl = $('steal-cards-hint');
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) {
// Обновляем колоду из актуального gameState
const targetPlayer = state.players[stealCardsMode.targetPlayerIndex];
const targetPlayer = currentState.players[stealCardsMode.targetPlayerIndex];
if (targetPlayer && targetPlayer.deck) {
stealCardsMode.targetDeck = [...targetPlayer.deck];
} else {
console.warn('Target player not found or deck is empty:', stealCardsMode.targetPlayerIndex);
}
if (stealCardsMode.targetDeck.length === 0) {
@ -2263,39 +2282,65 @@
}
deckList.innerHTML = stealCardsMode.targetDeck.map((cardId, idx) => {
const meta = cardDb[cardId];
if (!meta) return '';
const cardDbToUse = currentState?.cardDb || cardDb;
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 cost = meta.cost || 0;
const attack = meta.attack !== undefined ? meta.attack : '';
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 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-art">${art}</div>
<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}
${costDisplay}
</div>
</div>
</div>`;
}).filter(Boolean).join('');
}).join('');
$all('.steal-deck-card').forEach(card => {
card.onclick = function() {
const handleCardClick = function(e) {
e.preventDefault();
e.stopPropagation();
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);
if (selectedIdx >= 0) {
stealCardsMode.selectedIndices.splice(selectedIdx, 1);
} else if (stealCardsMode.selectedIndices.length < 2) {
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 => {
@ -2330,9 +2375,14 @@
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) => {
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;">
<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>
@ -2340,21 +2390,40 @@
}).join('');
$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 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) {
stealCardsMode.targetPlayerIndex = playerIdx;
// Получаем актуальную колоду из gameState
stealCardsMode.targetDeck = targetPlayer.deck ? [...targetPlayer.deck] : [];
showStealCardsModal(state, {
console.log('Selected target player:', playerIdx, 'Deck size:', stealCardsMode.targetDeck.length);
showStealCardsModal(currentState, {
targetPlayerIndex: playerIdx,
targetPlayerName: targetPlayer.name || `Игрок ${playerIdx + 1}`,
targetDeckSize: 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 {
margin-bottom: 1rem;
}
.steal-target-option {
pointer-events: auto !important;
cursor: pointer;
user-select: none;
-webkit-user-select: none;
}
.steal-target-option:hover {
background: rgba(0,180,255,0.2) !important;
border-color: var(--cyan) !important;
transform: scale(1.02);
}
.steal-target-option:active {
transform: scale(0.98);
}
.steal-deck-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
@ -1957,14 +1966,24 @@ html, body {
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
border: 2px solid transparent;
position: relative;
z-index: 10;
pointer-events: auto !important;
user-select: none;
-webkit-user-select: none;
}
.steal-deck-card:hover {
transform: scale(1.1);
box-shadow: 0 0 15px rgba(0,180,255,0.5);
z-index: 15;
}
.steal-deck-card.selected {
border-color: var(--cyan);
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 {
min-height: 80px;