dok/sockets/combat.js
2026-04-14 10:32:01 +01:00

85 lines
2.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* sockets/combat.js Server-seitige Kampfphasen-Logik für 1v1
*
* PRO KARTE: erst bewegen, dann sofort angreifen → dann nächste Karte.
* Avatar-Angriff wenn Range über das Spielfeld hinausreicht.
*/
'use strict';
function runCombatPhase(boardState, leftSlot, activeSlot) {
const events = [];
const isActiveLeft = activeSlot === leftSlot;
const dir = isActiveLeft ? 1 : -1;
const opponentSlot = activeSlot === 'player1' ? 'player2' : 'player1';
const myCards = [];
for (let slotIndex = 1; slotIndex <= 11; slotIndex++) {
for (const row of ['row1', 'row2']) {
const slotId = `${row}-slot-${slotIndex}`;
if (boardState[slotId]?.owner === activeSlot) myCards.push(slotId);
}
}
myCards.sort((a, b) => {
const ia = parseInt(a.split('-slot-')[1], 10);
const ib = parseInt(b.split('-slot-')[1], 10);
return isActiveLeft ? ib - ia : ia - ib;
});
for (const startSlotId of myCards) {
const entry = boardState[startSlotId];
if (!entry) continue;
const { card } = entry;
const row = startSlotId.split('-slot-')[0];
const race = card.race ?? 0;
const atk = card.attack ?? 0;
const range = card.range ?? 0;
let currentPos = parseInt(startSlotId.split('-slot-')[1], 10);
let currentSlotId = startSlotId;
/* ── BEWEGEN ── */
for (let step = 0; step < race; step++) {
const nextPos = currentPos + dir;
if (nextPos < 1 || nextPos > 11) break;
const nextSlotId = `${row}-slot-${nextPos}`;
if (boardState[nextSlotId]) break;
delete boardState[currentSlotId];
boardState[nextSlotId] = entry;
events.push({ type: 'move', from: currentSlotId, to: nextSlotId, owner: activeSlot });
currentSlotId = nextSlotId;
currentPos = nextPos;
}
/* ── ANGREIFEN ── */
for (let r = 1; r <= range; r++) {
const targetPos = currentPos + dir * r;
/* Avatar-Angriff: Range geht über das Spielfeld */
if (targetPos < 1 || targetPos > 11) {
events.push({ type: 'avatar_attack', from: currentSlotId, target: opponentSlot, damage: atk });
break;
}
const targetSlotId = `${row}-slot-${targetPos}`;
const target = boardState[targetSlotId];
if (!target) continue;
if (target.owner === activeSlot) continue;
target.card = { ...target.card, defends: (target.card.defends ?? 0) - atk };
events.push({ type: 'attack', from: currentSlotId, to: targetSlotId, damage: atk, remainingDef: target.card.defends });
if (target.card.defends <= 0) {
delete boardState[targetSlotId];
events.push({ type: 'die', slotId: targetSlotId });
}
break;
}
}
return events;
}
module.exports = { runCombatPhase };