diff --git a/IWantToHeal-Thor-v1.1.31.apk b/IWantToHeal-Thor-v1.1.31.apk new file mode 100644 index 0000000..ca6b18c Binary files /dev/null and b/IWantToHeal-Thor-v1.1.31.apk differ diff --git a/android/app/build.gradle b/android/app/build.gradle index d6224a2..faf8b7a 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "com.warren.iwanttoheal" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 111 - versionName "1.1.30" + versionCode 112 + versionName "1.1.31" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. diff --git a/screenshots/iwt2-party-frames-compact-hp-bars-thor-960x540.png b/screenshots/iwt2-party-frames-compact-hp-bars-thor-960x540.png new file mode 100644 index 0000000..73aa8d2 Binary files /dev/null and b/screenshots/iwt2-party-frames-compact-hp-bars-thor-960x540.png differ diff --git a/screenshots/iwt2-party-frames-left-expanded-thor-960x540.png b/screenshots/iwt2-party-frames-left-expanded-thor-960x540.png new file mode 100644 index 0000000..0ff3ae9 Binary files /dev/null and b/screenshots/iwt2-party-frames-left-expanded-thor-960x540.png differ diff --git a/screenshots/iwt2-party-frames-left-thor-960x540.png b/screenshots/iwt2-party-frames-left-thor-960x540.png new file mode 100644 index 0000000..60b0119 Binary files /dev/null and b/screenshots/iwt2-party-frames-left-thor-960x540.png differ diff --git a/src/App.css b/src/App.css index 6858253..4234b8b 100644 --- a/src/App.css +++ b/src/App.css @@ -212,6 +212,8 @@ } .iwt2-arena-layout { + display: grid; + grid-template-columns: 172px minmax(0, 1fr); height: 100vh; overflow: hidden; padding: 0; @@ -221,6 +223,7 @@ .iwt2-arena-stage { background: #090c10; border: 0; + grid-column: 2; height: 100%; min-height: 0; overflow: hidden; @@ -317,6 +320,22 @@ top: 0; } +.iwt2-bar em { + color: #fff7df; + font-size: 0.56rem; + font-style: normal; + font-weight: 800; + left: 0; + line-height: 1; + pointer-events: none; + position: absolute; + right: 0; + text-align: center; + text-shadow: 0 1px 0 #050608; + top: 50%; + transform: translateY(-50%); +} + .iwt2-bar.boss span { background: #dc5162; } @@ -337,17 +356,18 @@ .iwt2-party-list { background: rgba(15, 19, 26, 0.88); border: 0; - left: 28px; - max-height: calc(100% - 112px); + bottom: 0; + left: 0; + max-height: none; outline: 0; padding: 6px; - position: absolute; - top: 28px; + position: fixed; + top: 0; width: 172px; z-index: 4; display: grid; gap: 8px; - align-content: start; + align-content: center; overflow: auto; } @@ -1099,7 +1119,8 @@ .iwt2-gear-class, .iwt2-gear-slot, .iwt2-infusion-row, -.iwt2-gear-upgrade-button { +.iwt2-gear-upgrade-button, +.iwt2-gear-back { background: #151922; border: 2px solid #08090d; color: var(--ink); @@ -1177,7 +1198,8 @@ .iwt2-gear-class.game-selected, .iwt2-gear-slot.game-selected, .iwt2-infusion-row.game-selected, -.iwt2-gear-upgrade-button.game-selected { +.iwt2-gear-upgrade-button.game-selected, +.iwt2-gear-back.game-selected { outline-color: #e5b95f; } @@ -1187,6 +1209,12 @@ text-align: center; } +.iwt2-gear-back { + min-height: 36px; + padding: 8px 10px; + text-align: center; +} + .iwt2-gear-upgrade-button:disabled, .iwt2-infusion-row:disabled { color: var(--muted); @@ -1401,6 +1429,10 @@ } @media (max-width: 1000px) and (max-height: 620px) { + .iwt2-arena-layout { + grid-template-columns: 154px minmax(0, 1fr); + } + .game-shell.iwt2-shell { padding: 6px 0; width: min(100%, calc(100% - 20px)); @@ -1640,6 +1672,11 @@ padding: 7px 9px; } + .iwt2-gear-back { + min-height: 30px; + padding: 5px 8px; + } + .iwt2-gear-detail { gap: 6px; padding: 7px; @@ -1735,20 +1772,22 @@ } .iwt2-party-list { - gap: 5px; - left: 10px; - max-height: calc(100% - 84px); + align-content: center; + gap: 7px; + bottom: 0; + left: 0; + max-height: none; overflow: hidden; padding: 4px; - top: 10px; + top: 0; width: 154px; } .iwt2-party-row { gap: 5px; grid-template-columns: 22px minmax(0, 1fr); - height: 62px; - min-height: 62px; + height: 70px; + min-height: 70px; padding: 4px; } @@ -1782,8 +1821,12 @@ } .iwt2-party-row .iwt2-bar { - height: 7px; - margin-top: 2px; + height: 12px; + margin-top: 3px; + } + + .iwt2-party-row .iwt2-bar.mana { + height: 8px; } .iwt2-party-effects { @@ -1803,6 +1846,7 @@ .iwt2-ability-bar { bottom: 8px; + display: none; gap: 8px; grid-template-columns: repeat(6, 36px); max-width: 256px; diff --git a/src/input.tsx b/src/input.tsx index 5d3b7c7..f605ba3 100644 --- a/src/input.tsx +++ b/src/input.tsx @@ -435,6 +435,10 @@ function hasDedicatedGameNavigation() { ).some(isVisible) } +function isDedicatedNavigationAction(action: InputAction) { + return action.startsWith('navigate') || action === 'confirm' || action === 'back' +} + function dispatchGameAction(action: InputAction, device: InputDevice) { window.dispatchEvent(new CustomEvent(GAME_ACTION_EVENT, { detail: { action, device }, @@ -621,7 +625,12 @@ export function InputProvider({ children }: { children: ReactNode }) { setLastDevice(device) document.documentElement.dataset.inputDevice = device - if (controllerUiInput && dedicatedNavAction && hasDedicatedGameNavigation()) { + if ( + device === 'controller' + && dedicatedNavAction + && !keyboardInputRef.current + && hasDedicatedGameNavigation() + ) { if (document.activeElement instanceof HTMLElement) document.activeElement.blur() dispatchGameAction(action, device) return @@ -709,6 +718,7 @@ export function InputProvider({ children }: { children: ReactNode }) { 'navigateRight', 'confirm', 'back', + 'pause', ] satisfies InputAction[] const directTargetActions = [ 'targetParty1', @@ -738,7 +748,13 @@ export function InputProvider({ children }: { children: ReactNode }) { 'navigateLeft', 'navigateRight', ] satisfies InputAction[] - const action = DPAD_NAV_ACTIONS[token] && (!combatActive || uiOverlay) + const dedicatedNavigationActive = hasDedicatedGameNavigation() + const action = dedicatedNavigationActive + ? uiPriority.find((candidate) => bindingsRef.current.controller[candidate] === token) + ?? (DPAD_NAV_ACTIONS[token] && isDedicatedNavigationAction(DPAD_NAV_ACTIONS[token]) + ? DPAD_NAV_ACTIONS[token] + : undefined) + : DPAD_NAV_ACTIONS[token] && (!combatActive || uiOverlay) ? DPAD_NAV_ACTIONS[token] : uiOverlay ? uiPriority.find((candidate) => bindingsRef.current.controller[candidate] === token) diff --git a/src/modes/iwt2/components/ArenaBars.tsx b/src/modes/iwt2/components/ArenaBars.tsx index cff62bc..bcfe5c2 100644 --- a/src/modes/iwt2/components/ArenaBars.tsx +++ b/src/modes/iwt2/components/ArenaBars.tsx @@ -1,11 +1,13 @@ export function ArenaBar({ className = '', current, + label, max, shield = 0, }: { className?: string current: number + label?: string max: number shield?: number }) { @@ -15,6 +17,7 @@ export function ArenaBar({