Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
679900e7f5 | ||
|
|
ff64c6ddcc |
@@ -15,6 +15,9 @@
|
|||||||
- Controller navigation must not depend on touch, mouse, keyboard, or hidden developer-only shortcuts.
|
- Controller navigation must not depend on touch, mouse, keyboard, or hidden developer-only shortcuts.
|
||||||
- Focus state must always be visible and predictable when controller navigation is active.
|
- Focus state must always be visible and predictable when controller navigation is active.
|
||||||
- Avoid interaction patterns that trap focus, lose focus, or require precise pointer input.
|
- Avoid interaction patterns that trap focus, lose focus, or require precise pointer input.
|
||||||
|
- Controller navigation fixes must not break live combat bindings. When changing shared input routing, verify that combat-only actions still win during active combat: movement, ability casts, party targeting, pause, and overlay navigation must all work on AYN Thor controls.
|
||||||
|
- `data-game-nav-active` and other custom navigation markers may coexist with live combat HUDs. Do not treat those markers as menu mode during active combat unless a pause/dialog/result overlay is visible.
|
||||||
|
- Before considering any controller input change complete, test both states: no-overlay combat and menu/dialog navigation. No-overlay combat must include at least one successful ability cast from a controller binding and continuous analog movement on the AYN Thor control scheme.
|
||||||
|
|
||||||
## Architecture Requirements
|
## Architecture Requirements
|
||||||
|
|
||||||
@@ -34,6 +37,7 @@
|
|||||||
- IWT2 rendering can use a 2D canvas/game runtime, but renderer objects must not become the source of truth for saveable gameplay state.
|
- IWT2 rendering can use a 2D canvas/game runtime, but renderer objects must not become the source of truth for saveable gameplay state.
|
||||||
- IWT2 needs continuous movement input: left analog stick on AYN Thor and WASD on keyboard. Do not rely only on existing menu-style navigation actions for arena movement.
|
- IWT2 needs continuous movement input: left analog stick on AYN Thor and WASD on keyboard. Do not rely only on existing menu-style navigation actions for arena movement.
|
||||||
- IWT2 menus, dialogs, inventory, collection log, pause overlays, and game-select screen must still follow controller navigation requirements.
|
- IWT2 menus, dialogs, inventory, collection log, pause overlays, and game-select screen must still follow controller navigation requirements.
|
||||||
|
- IWT2 combat must preserve AYN Thor face/shoulder button ability bindings even when party frames, HUD controls, or target rails use custom controller navigation state. Menu navigation priority must never swallow ability inputs while `data-combat-active="true"` and no overlay is open.
|
||||||
- IWT2 boss mechanics and indicators must be modular. Add reusable hit-shape, damage/status, telegraph/indicator, hazard, and marker primitives under `src/modes/iwt2/sim/` or `src/modes/iwt2/render/` instead of hardcoding boss-specific rules in Phaser scenes. Boss AI may compose these primitives, but renderer code should draw sim-owned indicators generically.
|
- IWT2 boss mechanics and indicators must be modular. Add reusable hit-shape, damage/status, telegraph/indicator, hazard, and marker primitives under `src/modes/iwt2/sim/` or `src/modes/iwt2/render/` instead of hardcoding boss-specific rules in Phaser scenes. Boss AI may compose these primitives, but renderer code should draw sim-owned indicators generically.
|
||||||
- Every IWT2 boss must have a boss pet collection-log reward. Add the pet to IWT2 boss reward metadata when adding the boss, and keep boss kill pet drops at a rare 1 in 500 chance.
|
- Every IWT2 boss must have a boss pet collection-log reward. Add the pet to IWT2 boss reward metadata when adding the boss, and keep boss kill pet drops at a rare 1 in 500 chance.
|
||||||
- IWT2 boss and party movement must be built with crowding and hazard escape in mind from the first implementation. New bosses must not rely on straight-line chase or single-vector hazard avoidance if the boss can create ground effects, wall pressure, summons, or multi-boss overlap.
|
- IWT2 boss and party movement must be built with crowding and hazard escape in mind from the first implementation. New bosses must not rely on straight-line chase or single-vector hazard avoidance if the boss can create ground effects, wall pressure, summons, or multi-boss overlap.
|
||||||
|
|||||||
+31
-3
@@ -54,12 +54,18 @@ code updates to be a Git pull plus app restart.
|
|||||||
|
|
||||||
Portainer is not required. Use TrueNAS **Apps > Discover > Install via YAML**.
|
Portainer is not required. Use TrueNAS **Apps > Discover > Install via YAML**.
|
||||||
|
|
||||||
Repository:
|
Repository URL:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
https://git.whoagland.com/phenom/i-want-to-heal.git
|
https://git.whoagland.com/phenom/i-want-to-heal.git
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Local Gitea repository path on the same TrueNAS host:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/mnt/.ix-apps/app_mounts/gitea/data/git/repositories/phenom/i-want-to-heal.git
|
||||||
|
```
|
||||||
|
|
||||||
TrueNAS paths:
|
TrueNAS paths:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
@@ -67,12 +73,15 @@ TrueNAS paths:
|
|||||||
/mnt/usbssds/apps/iwanttoheal/data
|
/mnt/usbssds/apps/iwanttoheal/data
|
||||||
```
|
```
|
||||||
|
|
||||||
Create the app directory and clone the repo:
|
Create the app directory and clone the repo. When Gitea is hosted on the same
|
||||||
|
TrueNAS box, prefer the local repository path instead of HTTPS. This avoids
|
||||||
|
Git-over-HTTPS TLS failures while downloading large pack files.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo mkdir -p /mnt/usbssds/apps/iwanttoheal
|
sudo mkdir -p /mnt/usbssds/apps/iwanttoheal
|
||||||
cd /mnt/usbssds/apps/iwanttoheal
|
cd /mnt/usbssds/apps/iwanttoheal
|
||||||
sudo git clone https://git.whoagland.com/phenom/i-want-to-heal.git app
|
sudo git config --global --add safe.directory /mnt/.ix-apps/app_mounts/gitea/data/git/repositories/phenom/i-want-to-heal.git
|
||||||
|
sudo git clone /mnt/.ix-apps/app_mounts/gitea/data/git/repositories/phenom/i-want-to-heal.git app
|
||||||
```
|
```
|
||||||
|
|
||||||
Because the clone was run with `sudo`, give the normal TrueNAS user ownership:
|
Because the clone was run with `sudo`, give the normal TrueNAS user ownership:
|
||||||
@@ -101,6 +110,25 @@ cd /mnt/usbssds/apps/iwanttoheal/app
|
|||||||
git pull
|
git pull
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If setting up a different app hosted by the same Gitea instance, first find its
|
||||||
|
bare repository path:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo find /mnt -type d -name "REPO-NAME.git" -prune -print 2>/dev/null
|
||||||
|
```
|
||||||
|
|
||||||
|
Then substitute that path in the `safe.directory` and `git clone` commands:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo git config --global --add safe.directory /mnt/.ix-apps/app_mounts/gitea/data/git/repositories/OWNER/REPO-NAME.git
|
||||||
|
sudo git clone /mnt/.ix-apps/app_mounts/gitea/data/git/repositories/OWNER/REPO-NAME.git app
|
||||||
|
sudo chown -R truenas_admin:truenas_admin app
|
||||||
|
```
|
||||||
|
|
||||||
|
`safe.directory` is a Git trust exception for the Gitea-owned bare repository.
|
||||||
|
It is needed because Gitea's repository files are owned by the app/container
|
||||||
|
user, not by `truenas_admin`.
|
||||||
|
|
||||||
If Git fails with `chmod ... Operation not permitted`, do not use a media or SMB
|
If Git fails with `chmod ... Operation not permitted`, do not use a media or SMB
|
||||||
dataset for the repo. Git needs normal file locking and chmod behavior. Create or
|
dataset for the repo. Git needs normal file locking and chmod behavior. Create or
|
||||||
use a dedicated apps dataset and clone under `/mnt/usbssds/apps/...`.
|
use a dedicated apps dataset and clone under `/mnt/usbssds/apps/...`.
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
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 112
|
versionCode 114
|
||||||
versionName "1.1.31"
|
versionName "1.1.33"
|
||||||
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.
|
||||||
|
|||||||
@@ -104,6 +104,10 @@ npm run release:cli -- --release-only 1.1.26
|
|||||||
|
|
||||||
## Step 5: Update TrueNAS
|
## Step 5: Update TrueNAS
|
||||||
|
|
||||||
|
The TrueNAS app checkout should be cloned from the local Gitea bare repository
|
||||||
|
path when Gitea runs on the same TrueNAS host. After that setup, normal updates
|
||||||
|
still use `git pull`; the remote is local filesystem storage instead of HTTPS.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd /mnt/usbssds/apps/iwanttoheal/app
|
cd /mnt/usbssds/apps/iwanttoheal/app
|
||||||
git pull
|
git pull
|
||||||
|
|||||||
+1
-1
@@ -748,7 +748,7 @@ export function InputProvider({ children }: { children: ReactNode }) {
|
|||||||
'navigateLeft',
|
'navigateLeft',
|
||||||
'navigateRight',
|
'navigateRight',
|
||||||
] satisfies InputAction[]
|
] satisfies InputAction[]
|
||||||
const dedicatedNavigationActive = hasDedicatedGameNavigation()
|
const dedicatedNavigationActive = hasDedicatedGameNavigation() && (!combatActive || uiOverlay)
|
||||||
const action = dedicatedNavigationActive
|
const action = dedicatedNavigationActive
|
||||||
? uiPriority.find((candidate) => bindingsRef.current.controller[candidate] === token)
|
? uiPriority.find((candidate) => bindingsRef.current.controller[candidate] === token)
|
||||||
?? (DPAD_NAV_ACTIONS[token] && isDedicatedNavigationAction(DPAD_NAV_ACTIONS[token])
|
?? (DPAD_NAV_ACTIONS[token] && isDedicatedNavigationAction(DPAD_NAV_ACTIONS[token])
|
||||||
|
|||||||
@@ -47,9 +47,11 @@ import {
|
|||||||
type Iwt2RoguelikeVariant,
|
type Iwt2RoguelikeVariant,
|
||||||
} from './content/roguelike'
|
} from './content/roguelike'
|
||||||
import {
|
import {
|
||||||
createIwt2PveRoguelikeBossPair,
|
createIwt2WeightedRoguelikeBossPair,
|
||||||
createUniformIwt2RoguelikeBossPair,
|
createUniformIwt2RoguelikeBossPair,
|
||||||
IWT2_PVE_ROGUELIKE_WEIGHTED_BOSS_PROGRESSION_ENABLED,
|
IWT2_PVE_ROGUELIKE_WEIGHTED_BOSS_PROGRESSION_ENABLED,
|
||||||
|
IWT2_PVP_ROGUELIKE_WEIGHTED_BOSS_PROGRESSION_ENABLED,
|
||||||
|
IWT2_PVP_STADIUM_WEIGHTED_BOSS_PROGRESSION_ENABLED,
|
||||||
} from './content/roguelikeBossProgression'
|
} from './content/roguelikeBossProgression'
|
||||||
|
|
||||||
type Iwt2Screen =
|
type Iwt2Screen =
|
||||||
@@ -527,7 +529,7 @@ function createRoguelikeRun(
|
|||||||
contentType: Iwt2RoguelikeContentType,
|
contentType: Iwt2RoguelikeContentType,
|
||||||
): Iwt2RoguelikeRunState {
|
): Iwt2RoguelikeRunState {
|
||||||
return {
|
return {
|
||||||
bossIds: createRoguelikeBossPair(variant, 1),
|
bossIds: createRoguelikeBossPair(variant, contentType, 1),
|
||||||
buffs: [],
|
buffs: [],
|
||||||
contentType,
|
contentType,
|
||||||
debuffs: [],
|
debuffs: [],
|
||||||
@@ -595,15 +597,25 @@ function applyRoguelikeChoice(
|
|||||||
return {
|
return {
|
||||||
...run,
|
...run,
|
||||||
...nextBase,
|
...nextBase,
|
||||||
bossIds: createRoguelikeBossPair(run.variant, run.stage + 1),
|
bossIds: createRoguelikeBossPair(run.variant, run.contentType, run.stage + 1),
|
||||||
...buildRoguelikeChoices(save, run.variant),
|
...buildRoguelikeChoices(save, run.variant),
|
||||||
stage: run.stage + 1,
|
stage: run.stage + 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createRoguelikeBossPair(variant: Iwt2RoguelikeVariant, stage: number): Iwt2BossId[] {
|
function createRoguelikeBossPair(
|
||||||
if (variant === 'pve' && IWT2_PVE_ROGUELIKE_WEIGHTED_BOSS_PROGRESSION_ENABLED) {
|
variant: Iwt2RoguelikeVariant,
|
||||||
return createIwt2PveRoguelikeBossPair(stage)
|
contentType: Iwt2RoguelikeContentType,
|
||||||
|
stage: number,
|
||||||
|
): Iwt2BossId[] {
|
||||||
|
const weightedProgressionEnabled = variant === 'pve'
|
||||||
|
? IWT2_PVE_ROGUELIKE_WEIGHTED_BOSS_PROGRESSION_ENABLED
|
||||||
|
: contentType === 'stadium'
|
||||||
|
? IWT2_PVP_STADIUM_WEIGHTED_BOSS_PROGRESSION_ENABLED
|
||||||
|
: IWT2_PVP_ROGUELIKE_WEIGHTED_BOSS_PROGRESSION_ENABLED
|
||||||
|
|
||||||
|
if (weightedProgressionEnabled) {
|
||||||
|
return createIwt2WeightedRoguelikeBossPair(stage)
|
||||||
}
|
}
|
||||||
return createUniformIwt2RoguelikeBossPair()
|
return createUniformIwt2RoguelikeBossPair()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { IWT2_PARTY_ORDER } from './classes'
|
||||||
|
import {
|
||||||
|
IWT2_GEAR_SLOTS,
|
||||||
|
type Iwt2GearLevel,
|
||||||
|
type Iwt2GearProgress,
|
||||||
|
} from './gear'
|
||||||
|
|
||||||
|
export type Iwt2PvpGearNormalizationConfig = {
|
||||||
|
enabled: boolean
|
||||||
|
gearLevel: Iwt2GearLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
export const IWT2_PVP_GEAR_NORMALIZATION: Iwt2PvpGearNormalizationConfig = {
|
||||||
|
enabled: true,
|
||||||
|
gearLevel: 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createIwt2PvpNormalizedGearProgress(
|
||||||
|
config = IWT2_PVP_GEAR_NORMALIZATION,
|
||||||
|
): Iwt2GearProgress | undefined {
|
||||||
|
if (!config.enabled) return undefined
|
||||||
|
|
||||||
|
return Object.fromEntries(
|
||||||
|
IWT2_PARTY_ORDER.map((classId) => [
|
||||||
|
classId,
|
||||||
|
{
|
||||||
|
slots: Object.fromEntries(
|
||||||
|
IWT2_GEAR_SLOTS.map((slotId) => [slotId, { level: config.gearLevel }]),
|
||||||
|
),
|
||||||
|
infusionAbilityId: null,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
) as Iwt2GearProgress
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import { IWT2_BOSS_METADATA, type Iwt2BossId } from './bosses'
|
import { IWT2_BOSS_METADATA, type Iwt2BossId } from './bosses'
|
||||||
|
|
||||||
export const IWT2_PVE_ROGUELIKE_WEIGHTED_BOSS_PROGRESSION_ENABLED = true
|
export const IWT2_PVE_ROGUELIKE_WEIGHTED_BOSS_PROGRESSION_ENABLED = true
|
||||||
|
export const IWT2_PVP_ROGUELIKE_WEIGHTED_BOSS_PROGRESSION_ENABLED = true
|
||||||
|
export const IWT2_PVP_STADIUM_WEIGHTED_BOSS_PROGRESSION_ENABLED = true
|
||||||
|
|
||||||
type Iwt2RoguelikeBossTier = 'early' | 'mid' | 'late'
|
type Iwt2RoguelikeBossTier = 'early' | 'mid' | 'late'
|
||||||
|
|
||||||
@@ -43,6 +45,13 @@ const IWT2_ROGUELIKE_BOSS_TIER_BY_ID: Record<Iwt2BossId, Iwt2RoguelikeBossTier>
|
|||||||
export function createIwt2PveRoguelikeBossPair(
|
export function createIwt2PveRoguelikeBossPair(
|
||||||
stage: number,
|
stage: number,
|
||||||
random: () => number = Math.random,
|
random: () => number = Math.random,
|
||||||
|
): Iwt2BossId[] {
|
||||||
|
return createIwt2WeightedRoguelikeBossPair(stage, random)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createIwt2WeightedRoguelikeBossPair(
|
||||||
|
stage: number,
|
||||||
|
random: () => number = Math.random,
|
||||||
): Iwt2BossId[] {
|
): Iwt2BossId[] {
|
||||||
const choices: Iwt2BossId[] = []
|
const choices: Iwt2BossId[] = []
|
||||||
const maxThreat = maxThreatForStage(stage)
|
const maxThreat = maxThreatForStage(stage)
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import {
|
|||||||
IWT2_BARKSKIN_HOT_BONUS_BUFF_ID,
|
IWT2_BARKSKIN_HOT_BONUS_BUFF_ID,
|
||||||
IWT2_SUN_WARD_DAMAGE_REDUCTION_BUFF_ID,
|
IWT2_SUN_WARD_DAMAGE_REDUCTION_BUFF_ID,
|
||||||
} from '../content/roguelike'
|
} from '../content/roguelike'
|
||||||
|
import { createIwt2PvpNormalizedGearProgress } from '../content/pvpGearNormalization'
|
||||||
|
|
||||||
type ArenaStatus = 'playing' | 'paused' | 'victory' | 'defeat'
|
type ArenaStatus = 'playing' | 'paused' | 'victory' | 'defeat'
|
||||||
type OverlayAction = 'primary' | 'requeue' | 'menu'
|
type OverlayAction = 'primary' | 'requeue' | 'menu'
|
||||||
@@ -92,7 +93,12 @@ type BossArenaScreenProps = {
|
|||||||
export function BossArenaScreen({ bossId, bossIds, difficulty, modeLabel, save, onBack, onMainMenu, onPvpRequeue, onSaveUpdated, roguelikeRun }: BossArenaScreenProps) {
|
export function BossArenaScreen({ bossId, bossIds, difficulty, modeLabel, save, onBack, onMainMenu, onPvpRequeue, onSaveUpdated, roguelikeRun }: BossArenaScreenProps) {
|
||||||
const bossMetadata = IWT2_BOSS_METADATA[bossId]
|
const bossMetadata = IWT2_BOSS_METADATA[bossId]
|
||||||
const pvpRoguelike = roguelikeRun?.variant === 'pvp'
|
const pvpRoguelike = roguelikeRun?.variant === 'pvp'
|
||||||
const pveGearActive = roguelikeRun?.variant !== 'pvp'
|
const pvpNormalizedGearProgress = useMemo(() => createIwt2PvpNormalizedGearProgress(), [])
|
||||||
|
const activeGearProgress = pvpRoguelike
|
||||||
|
? pvpNormalizedGearProgress
|
||||||
|
: roguelikeRun?.variant !== 'pvp'
|
||||||
|
? save.gearProgress
|
||||||
|
: undefined
|
||||||
const bossHealthScale = roguelikeRun ? roguelikeBossHealthScale(roguelikeRun.stage) : 1
|
const bossHealthScale = roguelikeRun ? roguelikeBossHealthScale(roguelikeRun.stage) : 1
|
||||||
const difficultyHealthScale = difficulty?.healthMultiplier ?? 1
|
const difficultyHealthScale = difficulty?.healthMultiplier ?? 1
|
||||||
const difficultyDamageScale = difficulty?.damageMultiplier ?? 1
|
const difficultyDamageScale = difficulty?.damageMultiplier ?? 1
|
||||||
@@ -115,17 +121,19 @@ export function BossArenaScreen({ bossId, bossIds, difficulty, modeLabel, save,
|
|||||||
combinedDamageScale,
|
combinedDamageScale,
|
||||||
roguelikeBuffs,
|
roguelikeBuffs,
|
||||||
createPressureState(roguelikeStage, roguelikeContentType),
|
createPressureState(roguelikeStage, roguelikeContentType),
|
||||||
pveGearActive ? save.gearProgress : undefined,
|
activeGearProgress,
|
||||||
arenaBounds,
|
arenaBounds,
|
||||||
))
|
))
|
||||||
const [opponentArenaState, setOpponentArenaState] = useState<Iwt2ArenaState | null>(() => (
|
const [opponentArenaState, setOpponentArenaState] = useState<Iwt2ArenaState | null>(() => (
|
||||||
pvpRoguelike
|
pvpRoguelike
|
||||||
? createInitialIwt2ArenaState(
|
? createArenaState(
|
||||||
bossId,
|
bossId,
|
||||||
bossIds,
|
bossIds,
|
||||||
combinedBossHealthScale,
|
combinedBossHealthScale,
|
||||||
combinedDamageScale,
|
combinedDamageScale,
|
||||||
|
EMPTY_ROGUELIKE_BUFFS,
|
||||||
createPressureState(roguelikeStage, roguelikeContentType),
|
createPressureState(roguelikeStage, roguelikeContentType),
|
||||||
|
activeGearProgress,
|
||||||
arenaBounds,
|
arenaBounds,
|
||||||
)
|
)
|
||||||
: null
|
: null
|
||||||
@@ -189,16 +197,18 @@ export function BossArenaScreen({ bossId, bossIds, difficulty, modeLabel, save,
|
|||||||
combinedDamageScale,
|
combinedDamageScale,
|
||||||
roguelikeBuffs,
|
roguelikeBuffs,
|
||||||
pressureState,
|
pressureState,
|
||||||
pveGearActive ? save.gearProgress : undefined,
|
activeGearProgress,
|
||||||
arenaBounds,
|
arenaBounds,
|
||||||
)
|
)
|
||||||
const nextOpponentState = pvpRoguelike
|
const nextOpponentState = pvpRoguelike
|
||||||
? createInitialIwt2ArenaState(
|
? createArenaState(
|
||||||
bossId,
|
bossId,
|
||||||
bossIds,
|
bossIds,
|
||||||
combinedBossHealthScale,
|
combinedBossHealthScale,
|
||||||
combinedDamageScale,
|
combinedDamageScale,
|
||||||
|
EMPTY_ROGUELIKE_BUFFS,
|
||||||
pressureState,
|
pressureState,
|
||||||
|
activeGearProgress,
|
||||||
arenaBounds,
|
arenaBounds,
|
||||||
)
|
)
|
||||||
: null
|
: null
|
||||||
@@ -214,7 +224,7 @@ export function BossArenaScreen({ bossId, bossIds, difficulty, modeLabel, save,
|
|||||||
setPetAwards([])
|
setPetAwards([])
|
||||||
setSelectedOverlayAction('primary')
|
setSelectedOverlayAction('primary')
|
||||||
setStatus('playing')
|
setStatus('playing')
|
||||||
}, [arenaBounds, bossId, bossIds, combinedBossHealthScale, combinedDamageScale, pveGearActive, pvpRoguelike, roguelikeBuffs, roguelikeContentType, roguelikeStage, save.gearProgress])
|
}, [activeGearProgress, arenaBounds, bossId, bossIds, combinedBossHealthScale, combinedDamageScale, pvpRoguelike, roguelikeBuffs, roguelikeContentType, roguelikeStage])
|
||||||
|
|
||||||
const showOverlay = useCallback((nextStatus: Exclude<ArenaStatus, 'playing'>) => {
|
const showOverlay = useCallback((nextStatus: Exclude<ArenaStatus, 'playing'>) => {
|
||||||
setSelectedOverlayAction('primary')
|
setSelectedOverlayAction('primary')
|
||||||
@@ -231,10 +241,10 @@ export function BossArenaScreen({ bossId, bossIds, difficulty, modeLabel, save,
|
|||||||
() => {
|
() => {
|
||||||
const baseAbilities = abilitiesForHealer(
|
const baseAbilities = abilitiesForHealer(
|
||||||
save.character.healerStyle,
|
save.character.healerStyle,
|
||||||
pveGearActive ? save.gearProgress.healer.infusionAbilityId : null,
|
activeGearProgress?.healer.infusionAbilityId ?? null,
|
||||||
)
|
)
|
||||||
const gearAbilities = pveGearActive
|
const gearAbilities = activeGearProgress
|
||||||
? applyIwt2PveGearToHealerAbilities(baseAbilities, save.gearProgress)
|
? applyIwt2PveGearToHealerAbilities(baseAbilities, activeGearProgress)
|
||||||
: baseAbilities
|
: baseAbilities
|
||||||
return applyRoguelikeModifiers(
|
return applyRoguelikeModifiers(
|
||||||
gearAbilities,
|
gearAbilities,
|
||||||
@@ -242,7 +252,7 @@ export function BossArenaScreen({ bossId, bossIds, difficulty, modeLabel, save,
|
|||||||
roguelikeRun?.debuffs ?? [],
|
roguelikeRun?.debuffs ?? [],
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
[pveGearActive, roguelikeRun?.buffs, roguelikeRun?.debuffs, save.character.healerStyle, save.gearProgress],
|
[activeGearProgress, roguelikeRun?.buffs, roguelikeRun?.debuffs, save.character.healerStyle],
|
||||||
)
|
)
|
||||||
|
|
||||||
const castAbility = useCallback((ability: Iwt2HealerAbility) => {
|
const castAbility = useCallback((ability: Iwt2HealerAbility) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user