{# ══════════════════════════════════════════════════════════════════════ MACROS partagées entre match.html.twig et _match_body.html.twig ══════════════════════════════════════════════════════════════════════ #} {% macro renderCamp(pState, pid, cardMap, elementsMap, matchId, activePid, matchStatus, typeBudget) %} {% import _self as helpers %} {% set isActive = (pid == activePid) and (matchStatus != 'finished') %} {% set typeBudget = typeBudget ?? {} %}
{# ── Colonne latérale gauche : zone énergétique verticale ── #}
Énergie · {{ (pState.energyZone ?? [])|length }} {# Résumé du budget par type (précalculé côté controller pour éviter le renumérotage des clés entières par array_merge dans Twig). #} {% if typeBudget|length > 0 %}
{% for tid, avail in typeBudget %} {% set elLabel = tid == 0 ? 'Sans type' : (elementsMap[tid].name ?? '#' ~ tid) %}
{% if tid == 0 %} ✻ {% elseif elementsMap[tid] is defined and elementsMap[tid].iconUrl %} {% endif %} {{ avail }}
{% endfor %}
{% endif %}
{% if (pState.energyZone ?? [])|length == 0 %} Vide {% else %} {% for e in pState.energyZone %} {% set card = cardMap[e.cardId] ?? null %} {% set energyIdx = loop.index0 %}
{{ e.cardValue }}
{% for eid in e.elementalTypes ?? [] %} {% if elementsMap[eid] is defined and elementsMap[eid].iconUrl %} {% endif %} {% endfor %}
{{ card ? card.name : '?' }} {% if isActive and not e.engaged %}
{% elseif e.engaged %} Engagée {% endif %}
{% endfor %} {% endif %}
{# ── Colonne principale : monstres, sorts, boucliers ── #}
{# Rangée 1 : 4 monstres + 1 héros central #}
{% set mZone = pState.monsterZone ?? [null, null, null, null] %} {% for i in [0, 1] %} {{ helpers.renderZoneSlot(mZone[i] ?? null, 'monster', 'Monstre', i, cardMap, elementsMap) }} {% endfor %} {{ helpers.renderZoneSlot(pState.heroZone ?? null, 'hero', 'Héros', 4, cardMap, elementsMap) }} {% for i in [2, 3] %} {{ helpers.renderZoneSlot(mZone[i] ?? null, 'monster', 'Monstre', i, cardMap, elementsMap) }} {% endfor %}
{# Rangée 2 : 2 sorts + 1 terrain + 2 bottes #}
{% set sZone = pState.spellZone ?? [null, null] %} {% set tZone = pState.trapZone ?? [null, null] %} {{ helpers.renderZoneSlot(sZone[0] ?? null, 'spell', 'Sort', 0, cardMap, elementsMap) }} {{ helpers.renderZoneSlot(sZone[1] ?? null, 'spell', 'Sort', 1, cardMap, elementsMap) }} {{ helpers.renderZoneSlot(pState.terrainZone ?? null, 'terrain', 'Terrain', 0, cardMap, elementsMap) }} {{ helpers.renderZoneSlot(tZone[0] ?? null, 'trap', 'Botte secrète', 0, cardMap, elementsMap) }} {{ helpers.renderZoneSlot(tZone[1] ?? null, 'trap', 'Botte secrète', 1, cardMap, elementsMap) }}
{# Rangée 3 : 5 boucliers #}
{% set shields = pState.shields ?? [] %} {% for s in shields %} {{ helpers.renderShieldSlot(s, loop.index0, cardMap, elementsMap) }} {% endfor %} {% set brokenCount = 5 - shields|length %} {% if brokenCount > 0 %} {% for _ in range(1, brokenCount) %}
Brisé
{% endfor %} {% endif %}
{# ── Colonne latérale droite : Deck + Cimetière ── #}
{# Deck : dos de carte + compteur #}
{% if (pState.deck ?? [])|length > 0 %} {{ helpers.renderCardBack() }} {% else %} Vide {% endif %}
{{ (pState.deck ?? [])|length }} Deck
{# Cimetière : dernière carte envoyée face visible + compteur ; cliquable pour ouvrir la grille complète #} {% set graveyard = pState.graveyard ?? [] %}
0 %} data-graveyard-owner="{{ pid }}" data-graveyard-cardids="{{ graveyard|join(',') }}" title="Cliquer pour ouvrir le cimetière" {% endif %}>
{% if graveyard|length > 0 %} {% set lastCardId = graveyard|last %} {% set lastCard = cardMap[lastCardId] ?? null %} {% if lastCard %}
{{ lastCard.summonCost }}
{% for eid in lastCard.elementalTypes ?? [] %} {% if elementsMap[eid] is defined and elementsMap[eid].iconUrl %} {% endif %} {% endfor %}
{{ lastCard.name }}
{% endif %} {% else %} Vide {% endif %}
{{ graveyard|length }} Cimetière
{% endmacro %} {% macro renderZoneSlot(slot, kind, label, slotIndex, cardMap, elementsMap) %} {% import _self as helpers %} {% if slot is null %}
{{ label }}
{% else %}
{# Bottes secrètes non-déclenchées : face cachée #} {% if kind == 'trap' and not (slot.triggered ?? false) %} {{ helpers.renderCardBack() }} {% else %} {% set card = cardMap[slot.cardId] ?? null %} {{ helpers.renderCardInSlot(card, slot, kind, slotIndex, elementsMap) }} {% endif %}
{% endif %} {% endmacro %} {% macro renderShieldSlot(shield, slotIndex, cardMap, elementsMap) %} {% import _self as helpers %} {% if shield.broken %}
Brisé
{% else %}
{{ helpers.renderCardBack() }}
{% endif %} {% endmacro %} {% macro renderCardBack() %}
{% endmacro %} {% macro renderCardInSlot(card, slot, kind, slotIndex, elementsMap) %} {% set engaged = slot.engaged ?? false %} {% if card is null %}
Carte #{{ slot.cardId ?? '?' }}
{% else %}
{{ card.summonCost }}
{% for eid in card.elementalTypes ?? [] %} {% if elementsMap[eid] is defined and elementsMap[eid].iconUrl %} {% endif %} {% endfor %}
{{ card.name }}
{% if slot.currentPv is defined %}
PV {{ slot.currentPv }} EG {{ slot.currentEg }}
{% endif %}
{% endif %} {% endmacro %} {% macro renderCard(card, elementsMap, handIndex) %} {% if card is null %}
?
{% else %}
{{ card.summonCost }}
{% for eid in card.elementalTypes ?? [] %} {% if elementsMap[eid] is defined and elementsMap[eid].iconUrl %} {% endif %} {% endfor %}
{{ card.name }}
PV {{ card.stats.pvMax }} EG {{ card.stats.egMax }}
{% endif %} {% endmacro %}