diff --git a/client/src/components/InitiativeTracker.module.css b/client/src/components/InitiativeTracker.module.css index 512d919..352d3aa 100644 --- a/client/src/components/InitiativeTracker.module.css +++ b/client/src/components/InitiativeTracker.module.css @@ -302,3 +302,27 @@ border-color: rgba(var(--gold-rgb), 0.5); color: var(--gold); } + +.dyingTag { + font-size: 0.72rem; + color: var(--danger); + font-weight: 600; + margin-left: auto; + white-space: nowrap; +} + +.recoveryBtn { + font-size: 0.7rem; + padding: 0.15rem 0.4rem; + background: transparent; + border: 1px solid var(--danger); + color: var(--danger); + border-radius: 3px; + cursor: pointer; + white-space: nowrap; + flex-shrink: 0; +} + +.recoveryBtn:hover { + background: rgba(var(--danger-rgb), 0.12); +} diff --git a/client/src/components/InitiativeTracker.tsx b/client/src/components/InitiativeTracker.tsx index 4f847ad..b67999c 100644 --- a/client/src/components/InitiativeTracker.tsx +++ b/client/src/components/InitiativeTracker.tsx @@ -56,6 +56,10 @@ export default function InitiativeTracker({ socket.emit("initiative:end", { campaignId, combatId: combat.id }); } + function emitRecoveryRoll(characterId: number) { + socket.emit("death:recovery-roll", { campaignId, characterId }); + } + function emitUpdateEnemyHp(enemyId: string, hp_current: number) { socket.emit("initiative:update-enemy", { campaignId, @@ -119,6 +123,7 @@ export default function InitiativeTracker({ onAddEnemy={emitAddEnemy} onNext={emitNext} onEnd={emitEnd} + onRecoveryRoll={emitRecoveryRoll} /> )} @@ -232,6 +237,7 @@ interface ActivePhaseProps { onAddEnemy: () => void; onNext: () => void; onEnd: () => void; + onRecoveryRoll: (characterId: number) => void; } function ActivePhase({ @@ -249,6 +255,7 @@ function ActivePhase({ onAddEnemy, onNext, onEnd, + onRecoveryRoll, }: ActivePhaseProps) { const partyActive = combat.current_side === "party"; @@ -263,14 +270,30 @@ function ActivePhase({ )} - {partyChars.map((c) => ( -