Android build v1.1.38
This commit is contained in:
@@ -22,11 +22,7 @@ import {
|
||||
Iwt2RoguelikeUpgradeScreen,
|
||||
Iwt2SettingsScreen,
|
||||
} from './screens/Iwt2ShellScreens'
|
||||
import {
|
||||
loadIwt2Save,
|
||||
writeIwt2Save,
|
||||
type Iwt2Save,
|
||||
} from './save/iwt2Repository'
|
||||
import { writeIwt2Save, type Iwt2Save } from './save/iwt2Repository'
|
||||
import { IWT2_BOSS_METADATA, type Iwt2BossId } from './content/bosses'
|
||||
import { iwt2BossCoinRewardFor } from './content/bossRewards'
|
||||
import {
|
||||
@@ -153,15 +149,17 @@ const MENU_ITEMS: Array<{
|
||||
]
|
||||
|
||||
export function IWantToHeal2App({
|
||||
initialSave,
|
||||
onlineBackupsAvailable,
|
||||
onBackToGameSelect,
|
||||
onExitToSaveSelect,
|
||||
}: {
|
||||
initialSave: Iwt2Save
|
||||
onlineBackupsAvailable: boolean
|
||||
onBackToGameSelect: () => void
|
||||
onExitToSaveSelect: () => void
|
||||
}) {
|
||||
const { enabled: dualScreenEnabled } = useDualScreen()
|
||||
const [screen, setScreen] = useState<Iwt2Screen>('menu')
|
||||
const [save, setSave] = useState<Iwt2Save>(loadIwt2Save)
|
||||
const [save, setSave] = useState<Iwt2Save>(initialSave)
|
||||
const [selectedIndex, setSelectedIndex] = useState(0)
|
||||
const [selectedBossId, setSelectedBossId] = useState<Iwt2BossId>('bulldrome')
|
||||
const [arenaModeLabel, setArenaModeLabel] = useState('Dungeon')
|
||||
@@ -205,7 +203,7 @@ export function IWantToHeal2App({
|
||||
useGameAction((action, device) => {
|
||||
if (screen !== 'menu' || device !== 'controller') return
|
||||
if (action === 'back') {
|
||||
onBackToGameSelect()
|
||||
onExitToSaveSelect()
|
||||
return
|
||||
}
|
||||
if (action === 'confirm') {
|
||||
@@ -288,7 +286,7 @@ export function IWantToHeal2App({
|
||||
if (screen === 'roguelike-upgrade' && roguelikeRun) {
|
||||
return (
|
||||
<main className="game-shell iwt2-shell">
|
||||
<Iwt2Header save={save} onBackToGameSelect={onBackToGameSelect} />
|
||||
<Iwt2Header save={save} onExitToSaveSelect={onExitToSaveSelect} />
|
||||
<Iwt2RoguelikeUpgradeScreen
|
||||
activeBuffSummary={summarizeIwt2Buffs(save, roguelikeRun.buffs)}
|
||||
activeDebuffSummary={summarizeIwt2Debuffs(save, roguelikeRun.debuffs)}
|
||||
@@ -312,7 +310,7 @@ export function IWantToHeal2App({
|
||||
if (screen === 'dungeons') {
|
||||
return (
|
||||
<main className="game-shell iwt2-shell">
|
||||
<Iwt2Header save={save} onBackToGameSelect={onBackToGameSelect} />
|
||||
<Iwt2Header save={save} onExitToSaveSelect={onExitToSaveSelect} />
|
||||
<Iwt2DungeonsScreen
|
||||
difficultySlug={selectedDungeonDifficultySlug}
|
||||
save={save}
|
||||
@@ -333,7 +331,7 @@ export function IWantToHeal2App({
|
||||
if (screen === 'roguelike') {
|
||||
return (
|
||||
<main className="game-shell iwt2-shell">
|
||||
<Iwt2Header save={save} onBackToGameSelect={onBackToGameSelect} />
|
||||
<Iwt2Header save={save} onExitToSaveSelect={onExitToSaveSelect} />
|
||||
<Iwt2RoguelikeScreen
|
||||
contentType={roguelikeContentType}
|
||||
variant={roguelikeVariant}
|
||||
@@ -363,7 +361,7 @@ export function IWantToHeal2App({
|
||||
if (screen === 'raids') {
|
||||
return (
|
||||
<main className="game-shell iwt2-shell">
|
||||
<Iwt2Header save={save} onBackToGameSelect={onBackToGameSelect} />
|
||||
<Iwt2Header save={save} onExitToSaveSelect={onExitToSaveSelect} />
|
||||
<Iwt2ModeScreen
|
||||
difficultySlug={selectedRaidDifficultySlug}
|
||||
mode="Raids"
|
||||
@@ -397,7 +395,7 @@ export function IWantToHeal2App({
|
||||
save={save}
|
||||
title="Gear Upgrade"
|
||||
onBack={() => setScreen('menu')}
|
||||
onBackToGameSelect={onBackToGameSelect}
|
||||
onExitToSaveSelect={onExitToSaveSelect}
|
||||
/>
|
||||
<Iwt2GearUpgradeScreen
|
||||
save={save}
|
||||
@@ -411,7 +409,7 @@ export function IWantToHeal2App({
|
||||
if (screen === 'customize-character') {
|
||||
return (
|
||||
<main className="game-shell iwt2-shell">
|
||||
<Iwt2Header save={save} onBackToGameSelect={onBackToGameSelect} />
|
||||
<Iwt2Header save={save} onExitToSaveSelect={onExitToSaveSelect} />
|
||||
<Iwt2CustomizeCharacterScreen
|
||||
save={save}
|
||||
onBack={() => setScreen('menu')}
|
||||
@@ -424,7 +422,7 @@ export function IWantToHeal2App({
|
||||
if (screen === 'cloud-save') {
|
||||
return (
|
||||
<main className="game-shell iwt2-shell">
|
||||
<Iwt2Header save={save} onBackToGameSelect={onBackToGameSelect} />
|
||||
<Iwt2Header save={save} onExitToSaveSelect={onExitToSaveSelect} />
|
||||
<Iwt2CloudSaveScreen
|
||||
save={save}
|
||||
onlineBackupsAvailable={onlineBackupsAvailable}
|
||||
@@ -438,7 +436,7 @@ export function IWantToHeal2App({
|
||||
if (screen === 'settings') {
|
||||
return (
|
||||
<main className="game-shell iwt2-shell">
|
||||
<Iwt2Header save={save} onBackToGameSelect={onBackToGameSelect} />
|
||||
<Iwt2Header save={save} onExitToSaveSelect={onExitToSaveSelect} />
|
||||
<Iwt2SettingsScreen onBack={() => setScreen('menu')} />
|
||||
</main>
|
||||
)
|
||||
@@ -446,7 +444,7 @@ export function IWantToHeal2App({
|
||||
|
||||
return (
|
||||
<main className="game-shell iwt2-shell">
|
||||
<Iwt2Header save={save} onBackToGameSelect={onBackToGameSelect} />
|
||||
<Iwt2Header save={save} onExitToSaveSelect={onExitToSaveSelect} />
|
||||
|
||||
{screen === 'menu' && (
|
||||
<section className="iwt2-menu-screen" data-game-nav-active="true">
|
||||
@@ -692,19 +690,19 @@ function isExtraTargetBuff(choice: Iwt2RoguelikeChoice<Iwt2RoguelikeSelfBuffId>)
|
||||
|
||||
function Iwt2Header({
|
||||
onBack,
|
||||
onBackToGameSelect,
|
||||
onExitToSaveSelect,
|
||||
save,
|
||||
title,
|
||||
}: {
|
||||
onBack?: () => void
|
||||
onBackToGameSelect: () => void
|
||||
onExitToSaveSelect: () => void
|
||||
save: Iwt2Save
|
||||
title?: string
|
||||
}) {
|
||||
return (
|
||||
<header className="topbar app-header">
|
||||
<button className="brand-button" onClick={onBackToGameSelect} type="button">
|
||||
<strong>Games</strong>
|
||||
<button className="brand-button" onClick={onExitToSaveSelect} type="button">
|
||||
<strong>Saves</strong>
|
||||
</button>
|
||||
{title && <strong className="iwt2-header-title">{title}</strong>}
|
||||
<div className="character-summary">
|
||||
|
||||
@@ -130,7 +130,11 @@ function normalizeSave(value: unknown): Iwt2Save {
|
||||
if (candidate.version !== 1 && candidate.version !== 2) return createDefaultIwt2Save()
|
||||
return {
|
||||
version: 2,
|
||||
updatedAt: typeof candidate.updatedAt === 'number' ? candidate.updatedAt : Date.now(),
|
||||
updatedAt: typeof candidate.updatedAt === 'number'
|
||||
&& Number.isFinite(candidate.updatedAt)
|
||||
&& candidate.updatedAt > 0
|
||||
? candidate.updatedAt
|
||||
: Date.now(),
|
||||
character: {
|
||||
name: candidate.character?.name || 'Healer',
|
||||
level: Math.max(1, Math.floor(candidate.character?.level ?? 1)),
|
||||
@@ -150,10 +154,16 @@ function normalizeSave(value: unknown): Iwt2Save {
|
||||
}
|
||||
|
||||
export function loadIwt2Save(): Iwt2Save {
|
||||
return loadExistingIwt2Save() ?? createDefaultIwt2Save()
|
||||
}
|
||||
|
||||
export function loadExistingIwt2Save(): Iwt2Save | null {
|
||||
const serialized = window.localStorage.getItem(IWT2_SAVE_KEY)
|
||||
if (!serialized) return null
|
||||
try {
|
||||
return normalizeSave(JSON.parse(window.localStorage.getItem(IWT2_SAVE_KEY) ?? 'null'))
|
||||
return normalizeSave(JSON.parse(serialized))
|
||||
} catch {
|
||||
return createDefaultIwt2Save()
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,10 +186,11 @@ export async function writeIwt2OnlineSave(save: Iwt2Save): Promise<Iwt2OnlineSav
|
||||
}
|
||||
|
||||
export function writeIwt2Save(save: Iwt2Save) {
|
||||
window.localStorage.setItem(IWT2_SAVE_KEY, JSON.stringify({
|
||||
...save,
|
||||
updatedAt: Date.now(),
|
||||
}))
|
||||
replaceIwt2Save(save)
|
||||
}
|
||||
|
||||
export function replaceIwt2Save(save: Iwt2Save) {
|
||||
window.localStorage.setItem(IWT2_SAVE_KEY, JSON.stringify(normalizeSave(save)))
|
||||
}
|
||||
|
||||
export function recordIwt2BossKill(
|
||||
|
||||
Reference in New Issue
Block a user