Android build v1.0.54

This commit is contained in:
Warren H
2026-06-21 20:22:12 -04:00
parent 421540c52b
commit 787e2bbae9
4 changed files with 144 additions and 85 deletions
+46 -58
View File
@@ -1618,8 +1618,15 @@ export function PvPRoguelikeScreen({
<div>
<p className="eyebrow">You</p>
<h2>{profile.character.name}</h2>
<small>{encounter.enemyName} | Stage {stage}{encounter.isBoss ? ' Boss' : ''}</small>
</div>
<div className="resource-row pvp-resource-row">
<div className="pvp-side-bars">
<div className="pvp-clear-wrap">
<span>Your clear {Math.max(0, Math.floor(playerSide.enemyHealth))} / {encounter.maxHealth}</span>
<div className="bar enemy-health boss-bar">
<span style={{ width: `${(playerSide.enemyHealth / encounter.maxHealth) * 100}%` }} />
</div>
</div>
<div className="pvp-resource-wrap">
<span>{gameClass.resourceName} {Math.floor(playerSide.resource)} / {maxResource}</span>
{speedMultiplier === 2 && <strong className="speed-badge">2x speed</strong>}
@@ -1643,6 +1650,7 @@ export function PvPRoguelikeScreen({
<div className="bar member-health">
<span style={{ width: `${(member.health / effectiveMaxHealth(member)) * 100}%` }} />
{member.shield > 0 && <i style={{ width: `${(member.shield / effectiveMaxHealth(member)) * 100}%` }} />}
<em className="health-text">{Math.floor(member.health)} / {effectiveMaxHealth(member)}</em>
</div>
<div className="floating-combat-texts" aria-hidden="true">
{floatingTexts
@@ -1665,69 +1673,20 @@ export function PvPRoguelikeScreen({
</p>
</section>
<section className="combat-panel pvp-middle-panel">
<div className="encounter-header">
<div>
<p className="eyebrow">Encounter {encounterIndex + 1}</p>
<h2>{encounter.enemyName}</h2>
<small>Stage {stage}{encounter.isBoss ? ' Boss' : ''}</small>
</div>
</div>
<div className="pvp-enemy-race">
<div>
<strong>Your clear</strong>
<div className="bar enemy-health boss-bar">
<span style={{ width: `${(playerSide.enemyHealth / encounter.maxHealth) * 100}%` }} />
</div>
<small>{Math.max(0, Math.floor(playerSide.enemyHealth))} / {encounter.maxHealth}</small>
</div>
<div>
<strong>{liveMatch ? `${liveMatch.opponentName} clear` : 'CPU clear'}</strong>
<div className="bar enemy-health boss-bar">
<span style={{ width: `${(cpuSide.enemyHealth / encounter.maxHealth) * 100}%` }} />
</div>
<small>{Math.max(0, Math.floor(cpuSide.enemyHealth))} / {encounter.maxHealth}</small>
</div>
</div>
<div className="spell-bar six-slots vertical-spell-bar pvp-vertical-spell-bar">
{starterSpells.map((spell) => {
const remaining = playerSide.cooldowns[spell.id] ?? 0
const cost = spellResourceCost(spell, playerSide.buffs, playerSide.debuffs, playerSide.freeCastReady)
return (
<button
className="spell"
disabled={status !== 'playing' || playerDone || !playerAlive || remaining > 0 || playerSide.resource < cost}
key={`middle-${spell.id}`}
onClick={() => castPlayerSpell(spell)}
type="button"
>
<kbd>
<ControllerBindingLabel
binding={bindings[lastDevice][`ability${Number(spell.key)}` as InputAction]}
compact
iconStyle={controllerIconStyle}
/>
</kbd>
<span className={`spell-icon spell-${spell.kind}`}>{spell.glyph}</span>
<strong>{spell.name}</strong>
<small>{cost} {gameClass.resourceName}</small>
{remaining > 0 && <i>{remaining.toFixed(1)}</i>}
</button>
)
})}
</div>
<p className="roguelike-upgrade-list">
{liveMatch ? `${liveMatch.opponentName} (${liveMatch.opponentClassName})` : `CPU ${cpuDifficulty}`} | Encounters cleared: {encountersCleared}
</p>
</section>
<section className="combat-panel pvp-side">
<div className="encounter-header">
<div>
<p className="eyebrow">Opponent</p>
<h2>{opponentLabel}</h2>
<small>{liveMatch ? liveMatch.opponentClassName : `CPU ${cpuDifficulty}`} | Encounters cleared: {encountersCleared}</small>
</div>
<div className="resource-row pvp-resource-row">
<div className="pvp-side-bars">
<div className="pvp-clear-wrap">
<span>{liveMatch ? `${liveMatch.opponentName} clear` : 'CPU clear'} {Math.max(0, Math.floor(cpuSide.enemyHealth))} / {encounter.maxHealth}</span>
<div className="bar enemy-health boss-bar">
<span style={{ width: `${(cpuSide.enemyHealth / encounter.maxHealth) * 100}%` }} />
</div>
</div>
<div className="pvp-resource-wrap">
<span>{gameClass.resourceName} {Math.floor(cpuSide.resource)} / {maxResource}</span>
<div className="bar mana-bar"><span style={{ width: `${(cpuSide.resource / maxResource) * 100}%` }} /></div>
@@ -1745,6 +1704,7 @@ export function PvPRoguelikeScreen({
<div className="bar member-health">
<span style={{ width: `${(member.health / effectiveMaxHealth(member)) * 100}%` }} />
{member.shield > 0 && <i style={{ width: `${(member.shield / effectiveMaxHealth(member)) * 100}%` }} />}
<em className="health-text">{Math.floor(member.health)} / {effectiveMaxHealth(member)}</em>
</div>
<div className="floating-combat-texts" aria-hidden="true">
{floatingTexts
@@ -1766,6 +1726,34 @@ export function PvPRoguelikeScreen({
Buffs: {cpuSide.buffs.length > 0 ? summarizeStacks(cpuSide.buffs, selfBuffChoicesCatalog) : 'none'} | Debuffs: {cpuSide.debuffs.length > 0 ? summarizeStacks(cpuSide.debuffs, opponentDebuffChoicesCatalog) : 'none'}
</p>
</section>
<section className="pvp-bottom-spell-bar" aria-label="Player abilities">
{starterSpells.map((spell) => {
const remaining = playerSide.cooldowns[spell.id] ?? 0
const cost = spellResourceCost(spell, playerSide.buffs, playerSide.debuffs, playerSide.freeCastReady)
return (
<button
className="spell"
disabled={status !== 'playing' || playerDone || !playerAlive || remaining > 0 || playerSide.resource < cost}
key={`bottom-${spell.id}`}
onClick={() => castPlayerSpell(spell)}
type="button"
>
<kbd>
<ControllerBindingLabel
binding={bindings[lastDevice][`ability${Number(spell.key)}` as InputAction]}
compact
iconStyle={controllerIconStyle}
/>
</kbd>
<span className={`spell-icon spell-${spell.kind}`}>{spell.glyph}</span>
<strong>{spell.name}</strong>
<small>{cost} {gameClass.resourceName}</small>
{remaining > 0 && <i>{remaining.toFixed(1)}</i>}
</button>
)
})}
</section>
</div>
)}