feat: dying label and Roll Recovery button in InitiativeTracker active phase
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
52f792d63b
commit
bf7db6bd4c
2 changed files with 55 additions and 8 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -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({
|
|||
</span>
|
||||
)}
|
||||
</div>
|
||||
{partyChars.map((c) => (
|
||||
{partyChars.map((c) => {
|
||||
const dyingCondition = c.conditions?.find((cond) => cond.name === "Dying");
|
||||
return (
|
||||
<div key={c.id} className={styles.combatantRow}>
|
||||
<span className={styles.dot} style={{ background: c.color }} />
|
||||
<span className={partyActive ? styles.activeName : styles.rollName}>
|
||||
{c.name}
|
||||
{c.is_dead ? "\u{1F480} " : ""}{c.name}
|
||||
</span>
|
||||
{dyingCondition && (
|
||||
<span className={styles.dyingTag}>
|
||||
{"\u{1F480}"} Dying ({dyingCondition.rounds_remaining}r)
|
||||
</span>
|
||||
)}
|
||||
{isDM && dyingCondition && !c.is_dead && (
|
||||
<button
|
||||
className={styles.recoveryBtn}
|
||||
onClick={() => onRecoveryRoll(c.id)}
|
||||
>
|
||||
Roll Recovery
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className={`${styles.section} ${!partyActive ? styles.activeSection : ""}`}>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue