Android build v1.1.4
This commit is contained in:
Binary file not shown.
@@ -7,8 +7,8 @@ android {
|
|||||||
applicationId "com.warren.iwanttoheal"
|
applicationId "com.warren.iwanttoheal"
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 82
|
versionCode 83
|
||||||
versionName "1.1.3"
|
versionName "1.1.4"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
aaptOptions {
|
aaptOptions {
|
||||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||||
|
|||||||
+33
@@ -787,6 +787,10 @@ textarea:focus-visible,
|
|||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dual-top-main.pvp-roguelike-dual-top {
|
||||||
|
grid-template-rows: auto minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
.dual-top-main.stadium-dual-top {
|
.dual-top-main.stadium-dual-top {
|
||||||
grid-template-rows: auto auto minmax(0, 1fr) auto;
|
grid-template-rows: auto auto minmax(0, 1fr) auto;
|
||||||
}
|
}
|
||||||
@@ -798,6 +802,12 @@ textarea:focus-visible,
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dual-top-main.pvp-roguelike-dual-top .dual-top-enemy {
|
||||||
|
align-items: center;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 84px minmax(0, 1fr) minmax(96px, 108px);
|
||||||
|
}
|
||||||
|
|
||||||
.dual-top-main .dual-top-party-grid {
|
.dual-top-main .dual-top-party-grid {
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
@@ -829,6 +839,14 @@ textarea:focus-visible,
|
|||||||
padding: 8px 10px;
|
padding: 8px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dual-top-cooldowns {
|
||||||
|
align-content: center;
|
||||||
|
display: grid;
|
||||||
|
gap: 6px;
|
||||||
|
grid-template-columns: repeat(2, 48px);
|
||||||
|
justify-content: end;
|
||||||
|
}
|
||||||
|
|
||||||
.dual-top-spell {
|
.dual-top-spell {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: #20232c;
|
background: #20232c;
|
||||||
@@ -843,6 +861,11 @@ textarea:focus-visible,
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dual-top-cooldowns .dual-top-spell {
|
||||||
|
height: 38px;
|
||||||
|
width: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
.dual-top-spell:not(:disabled) {
|
.dual-top-spell:not(:disabled) {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
@@ -858,6 +881,12 @@ textarea:focus-visible,
|
|||||||
width: 32px;
|
width: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dual-top-cooldowns .dual-top-spell .spell-icon {
|
||||||
|
font-size: 16px;
|
||||||
|
height: 26px;
|
||||||
|
width: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
.dual-top-spell > i {
|
.dual-top-spell > i {
|
||||||
background: rgba(0, 0, 0, 0.58);
|
background: rgba(0, 0, 0, 0.58);
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
@@ -875,6 +904,10 @@ textarea:focus-visible,
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dual-top-cooldowns .dual-top-spell > small {
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.dual-top-resource {
|
.dual-top-resource {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
color: #82bfff;
|
color: #82bfff;
|
||||||
|
|||||||
@@ -1339,6 +1339,9 @@ export function PvPRoguelikeScreen({
|
|||||||
opponentClassName: liveMatch?.opponentClassName ?? (cpuDifficulty ? `CPU ${cpuDifficulty}` : 'CPU'),
|
opponentClassName: liveMatch?.opponentClassName ?? (cpuDifficulty ? `CPU ${cpuDifficulty}` : 'CPU'),
|
||||||
opponentParty: cpuSide.party,
|
opponentParty: cpuSide.party,
|
||||||
opponentEnemyHealth: cpuSide.enemyHealth,
|
opponentEnemyHealth: cpuSide.enemyHealth,
|
||||||
|
opponentResource: cpuSide.resource,
|
||||||
|
opponentMaxResource: maxResource,
|
||||||
|
opponentResourceName: gameClass.resourceName,
|
||||||
opponentBuffSummary,
|
opponentBuffSummary,
|
||||||
opponentDebuffSummary,
|
opponentDebuffSummary,
|
||||||
floatingTexts: dualScreenFloatingTexts,
|
floatingTexts: dualScreenFloatingTexts,
|
||||||
@@ -1362,6 +1365,7 @@ export function PvPRoguelikeScreen({
|
|||||||
cpuDifficulty,
|
cpuDifficulty,
|
||||||
cpuSide.enemyHealth,
|
cpuSide.enemyHealth,
|
||||||
cpuSide.party,
|
cpuSide.party,
|
||||||
|
cpuSide.resource,
|
||||||
directPartyTargeting,
|
directPartyTargeting,
|
||||||
encounter.description,
|
encounter.description,
|
||||||
encounter.enemyName,
|
encounter.enemyName,
|
||||||
|
|||||||
@@ -1055,6 +1055,9 @@ export function PvpStadiumScreen({
|
|||||||
opponentClassName: liveMatch?.opponentClassName ?? (cpuDifficulty ? `CPU ${cpuDifficulty}` : 'CPU'),
|
opponentClassName: liveMatch?.opponentClassName ?? (cpuDifficulty ? `CPU ${cpuDifficulty}` : 'CPU'),
|
||||||
opponentParty: cpuSide.party,
|
opponentParty: cpuSide.party,
|
||||||
opponentEnemyHealth: 0,
|
opponentEnemyHealth: 0,
|
||||||
|
opponentResource: cpuSide.resource,
|
||||||
|
opponentMaxResource: MAX_RESOURCE,
|
||||||
|
opponentResourceName: gameClass.resourceName,
|
||||||
opponentBuffSummary,
|
opponentBuffSummary,
|
||||||
opponentDebuffSummary,
|
opponentDebuffSummary,
|
||||||
floatingTexts: dualScreenFloatingTexts,
|
floatingTexts: dualScreenFloatingTexts,
|
||||||
@@ -1083,6 +1086,7 @@ export function PvpStadiumScreen({
|
|||||||
controllerIconStyle,
|
controllerIconStyle,
|
||||||
cpuDifficulty,
|
cpuDifficulty,
|
||||||
cpuSide.party,
|
cpuSide.party,
|
||||||
|
cpuSide.resource,
|
||||||
cpuSide.survivalSeconds,
|
cpuSide.survivalSeconds,
|
||||||
directPartyTargeting,
|
directPartyTargeting,
|
||||||
dualScreenFloatingTexts,
|
dualScreenFloatingTexts,
|
||||||
|
|||||||
+56
-33
@@ -47,6 +47,9 @@ export type DualScreenCombatState = {
|
|||||||
opponentClassName?: string
|
opponentClassName?: string
|
||||||
opponentParty?: PartyMember[]
|
opponentParty?: PartyMember[]
|
||||||
opponentEnemyHealth?: number
|
opponentEnemyHealth?: number
|
||||||
|
opponentResource?: number
|
||||||
|
opponentMaxResource?: number
|
||||||
|
opponentResourceName?: string
|
||||||
opponentBuffSummary?: string
|
opponentBuffSummary?: string
|
||||||
opponentDebuffSummary?: string
|
opponentDebuffSummary?: string
|
||||||
floatingTexts: Array<{
|
floatingTexts: Array<{
|
||||||
@@ -479,6 +482,17 @@ export function DualScreenBottomDisplay() {
|
|||||||
<div className="bar enemy-health boss-bar">
|
<div className="bar enemy-health boss-bar">
|
||||||
<span style={{ width: `${Math.max(0, ((state.opponentEnemyHealth ?? 0) / state.encounterMaxHealth) * 100)}%` }} />
|
<span style={{ width: `${Math.max(0, ((state.opponentEnemyHealth ?? 0) / state.encounterMaxHealth) * 100)}%` }} />
|
||||||
</div>
|
</div>
|
||||||
|
{typeof state.opponentResource === 'number' && state.opponentMaxResource ? (
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
<p className="eyebrow">{state.opponentResourceName ?? state.resourceName}</p>
|
||||||
|
<strong>{Math.floor(state.opponentResource)} / {state.opponentMaxResource}</strong>
|
||||||
|
</div>
|
||||||
|
<div className="bar mana-bar">
|
||||||
|
<span style={{ width: `${Math.max(0, (state.opponentResource / state.opponentMaxResource) * 100)}%` }} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -626,8 +640,34 @@ export function DualScreenTopCombat({
|
|||||||
[state.floatingTexts],
|
[state.floatingTexts],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const spellButtons = state.spells.map((spell, slotIndex) => {
|
||||||
|
if (!spell) return <div className="dual-top-spell empty" key={`empty-${slotIndex}`} />
|
||||||
|
const percent = spell.remaining > 0
|
||||||
|
? Math.min(100, (spell.remaining / Math.max(1, spell.cooldown)) * 100)
|
||||||
|
: 0
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className="dual-top-spell"
|
||||||
|
disabled={
|
||||||
|
!state.playerIsAlive
|
||||||
|
|| state.resource < spell.cost
|
||||||
|
|| spell.remaining > 0
|
||||||
|
|| state.status !== 'playing'
|
||||||
|
|| state.paused
|
||||||
|
}
|
||||||
|
key={spell.id}
|
||||||
|
onClick={() => onCastSpell?.(spell)}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span className={`spell-icon spell-${spell.kind}`}>{spell.glyph}</span>
|
||||||
|
{spell.remaining > 0 && <i style={{ height: `${percent}%` }} />}
|
||||||
|
{spell.remaining > 0 && <small>{spell.remaining.toFixed(0)}</small>}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="dual-top-main">
|
<div className={`dual-top-main ${state.opponentParty ? 'pvp-roguelike-dual-top' : ''}`}>
|
||||||
<section className="dual-top-enemy">
|
<section className="dual-top-enemy">
|
||||||
<div className="enemy-portrait" aria-hidden="true">
|
<div className="enemy-portrait" aria-hidden="true">
|
||||||
{state.encounterIsBoss ? 'B' : 'M'}
|
{state.encounterIsBoss ? 'B' : 'M'}
|
||||||
@@ -642,6 +682,11 @@ export function DualScreenTopCombat({
|
|||||||
</div>
|
</div>
|
||||||
<p>{state.encounterDescription}</p>
|
<p>{state.encounterDescription}</p>
|
||||||
</div>
|
</div>
|
||||||
|
{state.opponentParty && (
|
||||||
|
<div className="dual-top-cooldowns" aria-label="Cooldowns">
|
||||||
|
{spellButtons}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className="dual-top-party">
|
<section className="dual-top-party">
|
||||||
@@ -669,39 +714,17 @@ export function DualScreenTopCombat({
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className="dual-top-spell-strip">
|
{!state.opponentParty && (
|
||||||
{state.spells.map((spell, slotIndex) => {
|
<section className="dual-top-spell-strip">
|
||||||
if (!spell) return <div className="dual-top-spell empty" key={`empty-${slotIndex}`} />
|
{spellButtons}
|
||||||
const percent = spell.remaining > 0
|
<div className="dual-top-resource">
|
||||||
? Math.min(100, (spell.remaining / Math.max(1, spell.cooldown)) * 100)
|
<strong>{state.resourceName} {Math.floor(state.resource)} / {state.maxResource}</strong>
|
||||||
: 0
|
<div className="bar mana-bar">
|
||||||
return (
|
<span style={{ width: `${(state.resource / state.maxResource) * 100}%` }} />
|
||||||
<button
|
</div>
|
||||||
className="dual-top-spell"
|
|
||||||
disabled={
|
|
||||||
!state.playerIsAlive
|
|
||||||
|| state.resource < spell.cost
|
|
||||||
|| spell.remaining > 0
|
|
||||||
|| state.status !== 'playing'
|
|
||||||
|| state.paused
|
|
||||||
}
|
|
||||||
key={spell.id}
|
|
||||||
onClick={() => onCastSpell?.(spell)}
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span className={`spell-icon spell-${spell.kind}`}>{spell.glyph}</span>
|
|
||||||
{spell.remaining > 0 && <i style={{ height: `${percent}%` }} />}
|
|
||||||
{spell.remaining > 0 && <small>{spell.remaining.toFixed(0)}</small>}
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
<div className="dual-top-resource">
|
|
||||||
<strong>{state.resourceName} {Math.floor(state.resource)} / {state.maxResource}</strong>
|
|
||||||
<div className="bar mana-bar">
|
|
||||||
<span style={{ width: `${(state.resource / state.maxResource) * 100}%` }} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</section>
|
||||||
</section>
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user