Android build v1.1.27

This commit is contained in:
Warren H
2026-07-06 11:46:53 -04:00
parent de2f86e101
commit d70941f43e
24 changed files with 598 additions and 46 deletions
@@ -54,6 +54,7 @@ import {
iwt2GearUpgradeCosts,
iwt2InfusionCosts,
isIwt2InfusionUnlocked,
type Iwt2GearStatId,
type Iwt2GearSlotId,
} from '../content/gear'
import {
@@ -2021,6 +2022,9 @@ export function Iwt2GearUpgradeScreen({
const classProgress = save.gearProgress[selectedClassId]
const selectedSlot = classProgress.slots[selectedSlotId]
const selectedRecipe = IWT2_GEAR_SLOT_RECIPES[selectedClassId][selectedSlotId]
const selectedBonus = gearBonusSummary(selectedRecipe.statId, selectedSlot.level, selectedClassId)
const nextLevel = Math.min(5, selectedSlot.level + 1)
const nextBonus = gearBonusSummary(selectedRecipe.statId, nextLevel, selectedClassId)
const selectedClassName = gearClassDisplayName(selectedClassId, save)
const upgradeCosts = iwt2GearUpgradeCosts(selectedClassId, selectedSlotId, selectedSlot.level)
const canUpgrade = selectedSlot.level < 5 && canAffordIwt2Costs(save, upgradeCosts)
@@ -2186,6 +2190,16 @@ export function Iwt2GearUpgradeScreen({
<strong>{IWT2_GEAR_SLOT_LABELS[selectedSlotId]} +{selectedSlot.level}</strong>
<small>{IWT2_GEAR_STAT_LABELS[selectedRecipe.statId]} from {bossName(selectedRecipe.primaryBossId)} and {bossName(selectedRecipe.secondaryBossId)} coins.</small>
</p>
<div className="iwt2-gear-bonus-grid">
<span>
<strong>Current bonus</strong>
<small>{selectedBonus.text}</small>
</span>
<span>
<strong>{selectedSlot.level >= 5 ? 'Max rank' : `Upgrade preview +${selectedSlot.level} -> +${nextLevel}`}</strong>
<small>{selectedSlot.level >= 5 ? infusionAnchorText(classProgress.slots[selectedSlotId].level) : `${selectedBonus.label}: ${selectedBonus.value} -> ${nextBonus.value}`}</small>
</span>
</div>
<div className="iwt2-gear-cost-list">
{upgradeCosts.length === 0 ? (
<span>Max rank reached.</span>
@@ -2245,6 +2259,38 @@ function gearClassSubtitle(classId: Iwt2PlayerClassId, save: Iwt2Save): string {
return role === 'damage' ? 'Damage' : 'Tank'
}
function gearBonusSummary(
statId: Iwt2GearStatId,
level: number,
classId: Iwt2PlayerClassId,
): { label: string, text: string, value: string } {
const bonus = Math.max(0, level)
if (statId === 'maxHealth') return gearBonus('Max health', `+${bonus * 4}%`)
if (statId === 'moveSpeed') return gearBonus('Move speed', `+${formatPercent(bonus * 2.5)}%`)
if (statId === 'damage') return gearBonus('Attack damage', `+${bonus * 4}%`)
if (statId === 'attackCooldown') {
const label = classId === 'healer' ? 'Ability cooldown' : 'Attack cooldown'
return gearBonus(label, `-${bonus * 3}%`)
}
if (statId === 'projectileSpeed') return gearBonus('Projectile speed', `+${bonus * 3}%`)
if (statId === 'hazardDamageTaken') return gearBonus('Hazard damage taken', `-${bonus * 3}%`)
if (statId === 'stunResist') return gearBonus('Stun/knockdown duration', `-${bonus * 8}%`)
if (statId === 'healingPower') return gearBonus('Ability healing', `+${bonus * 4}%`)
return gearBonus('Bonus', '+0%')
}
function gearBonus(label: string, value: string): { label: string, text: string, value: string } {
return { label, text: `${label} ${value}`, value }
}
function infusionAnchorText(level: number): string {
return level >= 5 ? 'Infusion anchor available.' : 'No further bonus.'
}
function formatPercent(value: number): string {
return Number.isInteger(value) ? String(value) : value.toFixed(1)
}
function clampToEnabled(actions: Iwt2NavAction[], index: number) {
if (actions.length === 0) return 0
const bounded = Math.min(Math.max(0, index), actions.length - 1)