Android build v1.0.25
This commit is contained in:
Binary file not shown.
@@ -7,8 +7,8 @@ android {
|
||||
applicationId "com.warren.iwanttoheal"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 41
|
||||
versionName "1.0.24"
|
||||
versionCode 42
|
||||
versionName "1.0.25"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
|
||||
+10
@@ -131,6 +131,13 @@ function App() {
|
||||
})
|
||||
}, [screen])
|
||||
|
||||
useEffect(() => {
|
||||
if (!authChecked || !account || !profile || screen === 'combat') return
|
||||
window.requestAnimationFrame(() => {
|
||||
focusFirstControl()
|
||||
})
|
||||
}, [account, authChecked, profile, screen])
|
||||
|
||||
useEffect(() => {
|
||||
window.localStorage.setItem(LAST_DIFFICULTY_KEY, String(selectedDifficultyId))
|
||||
}, [selectedDifficultyId])
|
||||
@@ -148,6 +155,9 @@ function App() {
|
||||
setScreen('menu')
|
||||
setError('')
|
||||
setServerMessage('')
|
||||
window.requestAnimationFrame(() => {
|
||||
focusFirstControl()
|
||||
})
|
||||
}
|
||||
|
||||
async function signOut() {
|
||||
|
||||
@@ -374,6 +374,7 @@ export function CombatScreen({
|
||||
const partyRef = useRef(partyTemplate)
|
||||
const enemyHealthRef = useRef(encounters[initialEncounterIndex].maxHealth)
|
||||
const elapsedTicksRef = useRef(0)
|
||||
const selectedIdRef = useRef(partyTemplate[0].id)
|
||||
const encounter = encounters[encounterIndex]
|
||||
const currentPart = getCurrentPart(encounterIndex)
|
||||
const firstEncounterIndex = (startPart - 1) * 3
|
||||
@@ -415,6 +416,11 @@ export function CombatScreen({
|
||||
})
|
||||
}, [paused])
|
||||
|
||||
const setSelectedTargetId = useCallback((id: string) => {
|
||||
selectedIdRef.current = id
|
||||
setSelectedId(id)
|
||||
}, [])
|
||||
|
||||
const addLog = useCallback((text: string, tone: CombatLogEntry['tone']) => {
|
||||
const entry = { id: nextLogId.current++, text, tone }
|
||||
setLog((current) => [entry, ...current].slice(0, 60))
|
||||
@@ -467,7 +473,7 @@ export function CombatScreen({
|
||||
if (roguelikeMode) setRoguelikeEncounters(nextRoguelikeEncounters)
|
||||
setRoguelikeStage(1)
|
||||
setParty(freshParty)
|
||||
setSelectedId(partyTemplate[0].id)
|
||||
setSelectedTargetId(partyTemplate[0].id)
|
||||
setResource(maxResource)
|
||||
setEncounterIndex(initialEncounterIndex)
|
||||
setEnemyHealth(nextEncounters[initialEncounterIndex].maxHealth)
|
||||
@@ -494,7 +500,7 @@ export function CombatScreen({
|
||||
runStartedAtRef.current = Date.now()
|
||||
partStartTimesRef.current = { [startPart]: runStartedAtRef.current }
|
||||
setLog([{ id: nextLogId.current++, text: 'A new run begins.', tone: 'system' }])
|
||||
}, [difficulty, initialEncounterIndex, maxResource, partyTemplate, roguelikeMode, roguelikePool, startPart, staticEncounters])
|
||||
}, [difficulty, initialEncounterIndex, maxResource, partyTemplate, roguelikeMode, roguelikePool, setSelectedTargetId, startPart, staticEncounters])
|
||||
|
||||
const castSpell = useCallback(
|
||||
(spell: Spell) => {
|
||||
@@ -502,26 +508,27 @@ export function CombatScreen({
|
||||
if (status !== 'playing' || cooldowns[spell.id] > 0 || resource < effectiveCost) return
|
||||
const healer = partyRef.current.find((member) => member.id === 'mira')
|
||||
if (!healer || healer.health <= 0) return
|
||||
const selected = partyRef.current.find((member) => member.id === selectedId)
|
||||
const targetId = selectedIdRef.current
|
||||
const selected = partyRef.current.find((member) => member.id === targetId)
|
||||
if (!selected || selected.health <= 0) return
|
||||
const extraTarget = (blockedIds: string[]) => partyRef.current
|
||||
.filter((member) => member.health > 0 && !blockedIds.includes(member.id))
|
||||
.sort((left, right) => (left.health / left.maxHealth) - (right.health / right.maxHealth))[0]
|
||||
const directTargets = new Set([selectedId])
|
||||
const directTargets = new Set([targetId])
|
||||
const hotTargets = new Set<string>()
|
||||
const shieldTargets = new Set<string>()
|
||||
if (spell.kind === 'hot') hotTargets.add(selectedId)
|
||||
if (spell.kind === 'shield') shieldTargets.add(selectedId)
|
||||
if (spell.kind === 'hot') hotTargets.add(targetId)
|
||||
if (spell.kind === 'shield') shieldTargets.add(targetId)
|
||||
if (spell.name === 'Mend' && activeSetEffects.has('mend_extra_target')) {
|
||||
const extra = extraTarget([selectedId])
|
||||
const extra = extraTarget([targetId])
|
||||
if (extra) directTargets.add(extra.id)
|
||||
}
|
||||
if (spell.name === 'Renew' && activeSetEffects.has('renew_extra_target')) {
|
||||
const extra = extraTarget([selectedId])
|
||||
const extra = extraTarget([targetId])
|
||||
if (extra) hotTargets.add(extra.id)
|
||||
}
|
||||
if (spell.name === 'Mend' && activeSetEffects.has('mend_applies_renew')) {
|
||||
hotTargets.add(selectedId)
|
||||
hotTargets.add(targetId)
|
||||
}
|
||||
const extraTargets = upgradeStackCount(roguelikeUpgrades, `slot${spell.key as SlotKey}-extra-target` as RoguelikeUpgradeId)
|
||||
for (let index = 0; index < extraTargets; index += 1) {
|
||||
@@ -599,7 +606,7 @@ export function CombatScreen({
|
||||
setParty(nextParty)
|
||||
addLog(`${spell.name} cast on ${spell.kind === 'group' ? 'the party' : selected.name}${effectiveCost === 0 ? ' for free' : ''}.`, 'heal')
|
||||
},
|
||||
[activeSetEffects, addFloatingHeal, addLog, cooldowns, freeCastReady, resource, roguelikeUpgrades, selectedId, status],
|
||||
[activeSetEffects, addFloatingHeal, addLog, cooldowns, freeCastReady, resource, roguelikeUpgrades, status],
|
||||
)
|
||||
|
||||
const finishRun = useCallback(
|
||||
@@ -664,18 +671,18 @@ export function CombatScreen({
|
||||
const selectRelativeTarget = useCallback((direction: -1 | 1) => {
|
||||
const living = partyRef.current.filter((member) => member.health > 0)
|
||||
if (living.length === 0) return
|
||||
const currentIndex = living.findIndex((member) => member.id === selectedId)
|
||||
const currentIndex = living.findIndex((member) => member.id === selectedIdRef.current)
|
||||
const nextIndex = currentIndex < 0
|
||||
? 0
|
||||
: (currentIndex + direction + living.length) % living.length
|
||||
setSelectedId(living[nextIndex].id)
|
||||
}, [selectedId])
|
||||
setSelectedTargetId(living[nextIndex].id)
|
||||
}, [setSelectedTargetId])
|
||||
|
||||
const selectDirectionalTarget = useCallback((action: InputAction) => {
|
||||
const columns = dungeon.partySize >= 10 ? 6 : 3
|
||||
const currentIndex = partyRef.current.findIndex((member) => member.id === selectedId)
|
||||
const currentIndex = partyRef.current.findIndex((member) => member.id === selectedIdRef.current)
|
||||
if (currentIndex < 0) {
|
||||
setSelectedId(partyRef.current[0].id)
|
||||
setSelectedTargetId(partyRef.current[0].id)
|
||||
return
|
||||
}
|
||||
const currentRow = Math.floor(currentIndex / columns)
|
||||
@@ -709,14 +716,14 @@ export function CombatScreen({
|
||||
: Math.abs(b.column - currentColumn)
|
||||
return aPrimary - bPrimary || aSecondary - bSecondary
|
||||
})
|
||||
if (candidates[0]) setSelectedId(candidates[0].member.id)
|
||||
}, [dungeon.partySize, selectedId])
|
||||
if (candidates[0]) setSelectedTargetId(candidates[0].member.id)
|
||||
}, [dungeon.partySize, setSelectedTargetId])
|
||||
|
||||
const selectDirectTarget = useCallback((slot: number) => {
|
||||
const index = slot + (dungeon.partySize > 6 ? targetGroup * 6 : 0)
|
||||
const member = partyRef.current[index]
|
||||
if (member) setSelectedId(member.id)
|
||||
}, [dungeon.partySize, targetGroup])
|
||||
if (member) setSelectedTargetId(member.id)
|
||||
}, [dungeon.partySize, setSelectedTargetId, targetGroup])
|
||||
|
||||
const chooseRoguelikeUpgrade = useCallback((upgrade: RoguelikeUpgrade) => {
|
||||
if (!roguelikeMode) return
|
||||
@@ -778,9 +785,9 @@ export function CombatScreen({
|
||||
setTargetGroup((current) => {
|
||||
const groupCount = Math.max(1, Math.ceil(partyRef.current.length / 6))
|
||||
const next = ((current + 1) % groupCount) as 0 | 1 | 2
|
||||
const selectedIndex = partyRef.current.findIndex((member) => member.id === selectedId)
|
||||
const selectedIndex = partyRef.current.findIndex((member) => member.id === selectedIdRef.current)
|
||||
const nextMember = partyRef.current[(selectedIndex < 0 ? 0 : selectedIndex % 6) + next * 6]
|
||||
if (nextMember) setSelectedId(nextMember.id)
|
||||
if (nextMember) setSelectedTargetId(nextMember.id)
|
||||
return next
|
||||
})
|
||||
return
|
||||
@@ -1134,7 +1141,7 @@ export function CombatScreen({
|
||||
<button
|
||||
className={`party-member ${selectedId === member.id ? 'selected' : ''} ${member.health <= 0 ? 'dead' : ''}`}
|
||||
key={member.id}
|
||||
onClick={() => setSelectedId(member.id)}
|
||||
onClick={() => setSelectedTargetId(member.id)}
|
||||
aria-pressed={selectedId === member.id}
|
||||
type="button"
|
||||
>
|
||||
@@ -1219,7 +1226,7 @@ export function CombatScreen({
|
||||
{dualScreenEnabled && (
|
||||
<DualScreenTopCombat
|
||||
state={dualScreenState}
|
||||
onSelectTarget={setSelectedId}
|
||||
onSelectTarget={setSelectedTargetId}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user