Android build v1.0.60 stadium updated
This commit is contained in:
@@ -453,6 +453,7 @@ export function PvpStadiumScreen({
|
||||
const { enabled: dualScreenEnabled } = useDualScreen()
|
||||
const opponentLabel = liveMatch ? liveMatch.opponentName : `CPU ${cpuDifficulty ?? 1}`
|
||||
const playerAlive = playerSide.party.some((member) => member.health > 0)
|
||||
const partyColumns = 3
|
||||
|
||||
const setSelectedTargetId = useCallback((id: string) => {
|
||||
selectedIdRef.current = id
|
||||
@@ -841,6 +842,55 @@ export function PvpStadiumScreen({
|
||||
if (succeeded) addLog(`${spell.name} cast on ${playerRef.current.party.find((member) => member.id === targetId)?.name ?? 'target'}.`, 'heal')
|
||||
}, [addLog, applySpell, playerAlive, status])
|
||||
|
||||
const selectRelativeTarget = useCallback((direction: -1 | 1) => {
|
||||
const living = playerRef.current.party.filter((member) => member.health > 0)
|
||||
if (living.length === 0) return
|
||||
const currentIndex = living.findIndex((member) => member.id === selectedIdRef.current)
|
||||
const nextIndex = currentIndex < 0
|
||||
? 0
|
||||
: (currentIndex + direction + living.length) % living.length
|
||||
setSelectedTargetId(living[nextIndex].id)
|
||||
}, [setSelectedTargetId])
|
||||
|
||||
const selectDirectionalTarget = useCallback((action: InputAction) => {
|
||||
const currentIndex = playerRef.current.party.findIndex((member) => member.id === selectedIdRef.current)
|
||||
if (currentIndex < 0) {
|
||||
const firstLiving = playerRef.current.party.find((member) => member.health > 0)
|
||||
if (firstLiving) setSelectedTargetId(firstLiving.id)
|
||||
return
|
||||
}
|
||||
const currentRow = Math.floor(currentIndex / partyColumns)
|
||||
const currentColumn = currentIndex % partyColumns
|
||||
const candidates = playerRef.current.party
|
||||
.map((member, index) => ({
|
||||
member,
|
||||
index,
|
||||
row: Math.floor(index / partyColumns),
|
||||
column: index % partyColumns,
|
||||
}))
|
||||
.filter(({ member, index, row, column }) => {
|
||||
if (member.health <= 0 || index === currentIndex) return false
|
||||
if (action === 'navigateLeft') return row === currentRow && column < currentColumn
|
||||
if (action === 'navigateRight') return row === currentRow && column > currentColumn
|
||||
if (action === 'navigateUp') return row < currentRow
|
||||
return row > currentRow
|
||||
})
|
||||
.sort((a, b) => {
|
||||
const horizontal = action === 'navigateLeft' || action === 'navigateRight'
|
||||
const aPrimary = horizontal ? Math.abs(a.column - currentColumn) : Math.abs(a.row - currentRow)
|
||||
const bPrimary = horizontal ? Math.abs(b.column - currentColumn) : Math.abs(b.row - currentRow)
|
||||
const aSecondary = horizontal ? 0 : Math.abs(a.column - currentColumn)
|
||||
const bSecondary = horizontal ? 0 : Math.abs(b.column - currentColumn)
|
||||
return aPrimary - bPrimary || aSecondary - bSecondary
|
||||
})
|
||||
if (candidates[0]) setSelectedTargetId(candidates[0].member.id)
|
||||
}, [partyColumns, setSelectedTargetId])
|
||||
|
||||
const selectDirectTarget = useCallback((slot: number) => {
|
||||
const member = playerRef.current.party[slot]
|
||||
if (member?.health > 0) setSelectedTargetId(member.id)
|
||||
}, [setSelectedTargetId])
|
||||
|
||||
const cpuTakeTurn = useCallback(() => {
|
||||
if (!cpuDifficulty || status !== 'playing') return
|
||||
const behavior = CPU_BEHAVIOR[cpuDifficulty]
|
||||
@@ -1032,6 +1082,18 @@ export function PvpStadiumScreen({
|
||||
setShopReady(false)
|
||||
setShopPoints(0)
|
||||
addLog(`Round ${nextRound} starts. HP and mana restored.`, 'system')
|
||||
if (liveMatchRef.current) {
|
||||
publishPvpMatchState<StadiumSideState>(liveMatchRef.current.id, {
|
||||
state: nextPlayer,
|
||||
status: 'playing',
|
||||
stage: nextRound,
|
||||
encounterIndex: nextRound,
|
||||
encountersCleared: roundWins.player,
|
||||
enemyHealth: 0,
|
||||
alive: true,
|
||||
elapsedTicks: 0,
|
||||
}).catch(() => undefined)
|
||||
}
|
||||
beginRoundCountdown()
|
||||
}, [addLog, beginRoundCountdown, cpuPartyTemplate, partyTemplate, roundIndex, roundWins.opponent, roundWins.player, setSelectedTargetId])
|
||||
|
||||
@@ -1086,7 +1148,7 @@ export function PvpStadiumScreen({
|
||||
.then((snapshot) => {
|
||||
if (stopped) return
|
||||
const opponentState = snapshot.states[liveMatch.opponentSide]
|
||||
if (opponentState) {
|
||||
if (opponentState && opponentState.roundIndex >= roundIndex) {
|
||||
cpuRef.current = opponentState
|
||||
setCpuSide(opponentState)
|
||||
}
|
||||
@@ -1094,6 +1156,7 @@ export function PvpStadiumScreen({
|
||||
if (opponentStatus === 'won' && status !== 'won' && status !== 'lost') setStatus('lost')
|
||||
if (opponentStatus === 'lost' && status !== 'won' && status !== 'lost') setStatus('won')
|
||||
if (!opponentState) return
|
||||
if (opponentState.roundIndex < roundIndex) return
|
||||
if (status === 'playing' && opponentState.roundIndex === roundIndex && opponentState.roundStatus === 'shop' && opponentState.lastRoundOutcome) {
|
||||
const key = `${roundIndex}-${opponentState.lastRoundOutcome}`
|
||||
if (loggedOpponentRoundRef.current === key) return
|
||||
@@ -1102,7 +1165,14 @@ export function PvpStadiumScreen({
|
||||
else if (opponentState.lastRoundOutcome === 'win') finishRound('loss')
|
||||
else finishRound('tie')
|
||||
}
|
||||
if (status === 'shop' && shopReady && opponentState.roundIndex === roundIndex && opponentState.shopReady) {
|
||||
if (
|
||||
status === 'shop'
|
||||
&& shopReady
|
||||
&& (
|
||||
(opponentState.roundIndex === roundIndex && opponentState.shopReady)
|
||||
|| opponentState.roundIndex > roundIndex
|
||||
)
|
||||
) {
|
||||
startNextRound()
|
||||
}
|
||||
})
|
||||
@@ -1178,15 +1248,31 @@ export function PvpStadiumScreen({
|
||||
window.requestAnimationFrame(() => focusFirstControl())
|
||||
}, [status])
|
||||
|
||||
useEffect(() => {
|
||||
if (!paused) return
|
||||
window.requestAnimationFrame(() => focusFirstControl())
|
||||
}, [paused])
|
||||
|
||||
useGameAction((action) => {
|
||||
if (action === 'pause') {
|
||||
if (action === 'pause' || action === 'back') {
|
||||
if (status === 'playing') setPaused((value) => !value)
|
||||
return
|
||||
}
|
||||
if (paused || status !== 'playing') return
|
||||
if (action.startsWith('navigate')) {
|
||||
selectDirectionalTarget(action)
|
||||
return
|
||||
}
|
||||
if (action === 'previousTarget') {
|
||||
selectRelativeTarget(-1)
|
||||
return
|
||||
}
|
||||
if (action === 'nextTarget') {
|
||||
selectRelativeTarget(1)
|
||||
return
|
||||
}
|
||||
if (action.startsWith('targetParty')) {
|
||||
const index = Number(action.slice('targetParty'.length)) - 1
|
||||
const member = playerRef.current.party[index]
|
||||
if (member?.health > 0) setSelectedTargetId(member.id)
|
||||
selectDirectTarget(Number(action.slice('targetParty'.length)) - 1)
|
||||
return
|
||||
}
|
||||
if (action.startsWith('ability')) {
|
||||
|
||||
Reference in New Issue
Block a user