made some changes to the UI, removed leaderboards. updated gamesaves

This commit is contained in:
Warren H
2026-06-18 13:00:29 -04:00
parent 3c90998a61
commit a604569a2f
44 changed files with 2301 additions and 435 deletions
+27 -19
View File
@@ -241,7 +241,7 @@ function makeRoguelikeSegment(
encounter.maxHealth
+ encounter.damage * 18
+ encounter.tankDamage * 10
+ encounter.partyDamage * 12
+ encounter.partyDamage * 18
)
const trashPool = [...pool.filter((encounter) => !encounter.isBoss)]
.sort((left, right) => encounterThreat(left) - encounterThreat(right))
@@ -331,7 +331,7 @@ export function CombatScreen({
)
const maxResource = gameClass.maxResource + (isRoguelike ? 0 : profile.gearStats.maxResourceBonus)
const partyTemplate = useMemo(
() => (dungeon.partySize === 10 ? RAID_PARTY : INITIAL_PARTY).map((member) => ({
() => (dungeon.partySize >= 10 ? RAID_PARTY : INITIAL_PARTY).map((member) => ({
...member,
name: member.id === 'mira' ? profile.character.name : member.name,
})),
@@ -346,10 +346,10 @@ export function CombatScreen({
const [encounterIndex, setEncounterIndex] = useState(initialEncounterIndex)
const [enemyHealth, setEnemyHealth] = useState(encounters[initialEncounterIndex].maxHealth)
const [cooldowns, setCooldowns] = useState<Record<string, number>>({})
const [elapsedTicks, setElapsedTicks] = useState(0)
const [, setElapsedTicks] = useState(0)
const [status, setStatus] = useState<'playing' | 'won' | 'lost' | 'part-complete' | 'upgrade-choice'>('playing')
const [paused, setPaused] = useState(false)
const [targetGroup, setTargetGroup] = useState<0 | 1>(0)
const [targetGroup, setTargetGroup] = useState<0 | 1 | 2>(0)
const [log, setLog] = useState<CombatLogEntry[]>([
{ id: 1, text: `${dungeon.name} begins.`, tone: 'system' },
])
@@ -373,6 +373,7 @@ export function CombatScreen({
const nextFloatingTextId = useRef(1)
const partyRef = useRef(partyTemplate)
const enemyHealthRef = useRef(encounters[initialEncounterIndex].maxHealth)
const elapsedTicksRef = useRef(0)
const encounter = encounters[encounterIndex]
const currentPart = getCurrentPart(encounterIndex)
const firstEncounterIndex = (startPart - 1) * 3
@@ -471,6 +472,7 @@ export function CombatScreen({
setEncounterIndex(initialEncounterIndex)
setEnemyHealth(nextEncounters[initialEncounterIndex].maxHealth)
setCooldowns({})
elapsedTicksRef.current = 0
setElapsedTicks(0)
setStatus('playing')
setPaused(false)
@@ -670,7 +672,7 @@ export function CombatScreen({
}, [selectedId])
const selectDirectionalTarget = useCallback((action: InputAction) => {
const columns = dungeon.partySize === 10 ? 5 : 3
const columns = dungeon.partySize >= 10 ? 6 : 3
const currentIndex = partyRef.current.findIndex((member) => member.id === selectedId)
if (currentIndex < 0) {
setSelectedId(partyRef.current[0].id)
@@ -711,7 +713,7 @@ export function CombatScreen({
}, [dungeon.partySize, selectedId])
const selectDirectTarget = useCallback((slot: number) => {
const index = slot + (dungeon.partySize === 10 ? targetGroup * 5 : 0)
const index = slot + (dungeon.partySize > 6 ? targetGroup * 6 : 0)
const member = partyRef.current[index]
if (member) setSelectedId(member.id)
}, [dungeon.partySize, targetGroup])
@@ -748,6 +750,7 @@ export function CombatScreen({
setParty(recoveredParty)
setEncounterIndex((current) => current + 1)
setEnemyHealth(nextEncounter.maxHealth)
elapsedTicksRef.current = 0
setElapsedTicks(0)
setCooldowns({})
setResource((value) => clamp(value + Math.round(maxResource * 0.25), 0, maxResource))
@@ -771,11 +774,12 @@ export function CombatScreen({
return
}
if (action === 'toggleTargetGroup') {
if (dungeon.partySize !== 10) return
if (dungeon.partySize <= 6) return
setTargetGroup((current) => {
const next = current === 0 ? 1 : 0
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 nextMember = partyRef.current[(selectedIndex < 0 ? 0 : selectedIndex % 5) + next * 5]
const nextMember = partyRef.current[(selectedIndex < 0 ? 0 : selectedIndex % 6) + next * 6]
if (nextMember) setSelectedId(nextMember.id)
return next
})
@@ -798,7 +802,9 @@ export function CombatScreen({
useEffect(() => {
if (status !== 'playing' || paused) return
const timer = window.setInterval(() => {
setElapsedTicks((value) => value + 1)
const nextElapsedTicks = elapsedTicksRef.current + 1
elapsedTicksRef.current = nextElapsedTicks
setElapsedTicks(nextElapsedTicks)
setResource((value) => clamp(value + 2.4, 0, maxResource))
setCooldowns((current) =>
Object.fromEntries(
@@ -820,19 +826,19 @@ export function CombatScreen({
const primaryTarget = living[Math.floor(Math.random() * living.length)]
const mechanics = (encounter as RoguelikeEncounter).roguelikeMechanics ?? []
const useDefaultBossMechanics = encounter.isBoss && mechanics.length === 0
const bossPulse = encounter.isBoss && elapsedTicks > 0 && elapsedTicks % 7 === 0
const bossPulse = encounter.isBoss && nextElapsedTicks > 0 && nextElapsedTicks % 7 === 0
&& (useDefaultBossMechanics || mechanics.includes('party-pulse'))
const appliesDebuff = encounter.isBoss && elapsedTicks > 0 && elapsedTicks % 11 === 0
const appliesDebuff = encounter.isBoss && nextElapsedTicks > 0 && nextElapsedTicks % 11 === 0
&& (useDefaultBossMechanics || mechanics.includes('searing-mark'))
const appliesMaxHealthCut = encounter.isBoss && elapsedTicks > 0 && elapsedTicks % 13 === 0
const appliesMaxHealthCut = encounter.isBoss && nextElapsedTicks > 0 && nextElapsedTicks % 13 === 0
&& mechanics.includes('max-health-cut')
const appliesHealingReduction = encounter.isBoss && elapsedTicks > 0 && elapsedTicks % 9 === 0
const appliesHealingReduction = encounter.isBoss && nextElapsedTicks > 0 && nextElapsedTicks % 9 === 0
&& mechanics.includes('healing-reduction')
const tankBuster = encounter.isBoss && elapsedTicks > 0 && elapsedTicks % 8 === 0
const tankBuster = encounter.isBoss && nextElapsedTicks > 0 && nextElapsedTicks % 8 === 0
&& mechanics.includes('tank-buster')
const resourceDrain = encounter.isBoss && elapsedTicks > 0 && elapsedTicks % 10 === 0
const resourceDrain = encounter.isBoss && nextElapsedTicks > 0 && nextElapsedTicks % 10 === 0
&& mechanics.includes('resource-drain')
const appliesPoison = encounter.isBoss && elapsedTicks > 0 && elapsedTicks % 12 === 0
const appliesPoison = encounter.isBoss && nextElapsedTicks > 0 && nextElapsedTicks % 12 === 0
&& mechanics.includes('ramping-poison')
if (bossPulse) addLog(`${encounter.enemyName} unleashes party-wide damage.`, 'danger')
if (appliesDebuff) addLog(`${primaryTarget.name} is afflicted by Searing Mark.`, 'danger')
@@ -957,6 +963,7 @@ export function CombatScreen({
setParty(recoveredParty)
setEncounterIndex((value) => value + 1)
setEnemyHealth(nextEncounter.maxHealth)
elapsedTicksRef.current = 0
setElapsedTicks(0)
addLog(`${encounter.enemyName} defeated. ${nextEncounter.enemyName} approaches.`, 'system')
}, TICK_MS)
@@ -965,7 +972,6 @@ export function CombatScreen({
addLog,
addFloatingHeal,
difficulty.damageMultiplier,
elapsedTicks,
encounter,
encounterIndex,
encounters,
@@ -1123,7 +1129,7 @@ export function CombatScreen({
<div className="bar mana-bar"><span style={{ width: `${(resource / maxResource) * 100}%` }} /></div>
</div>
</div>
<div className={`party-grid ${dungeon.partySize === 10 ? 'raid-party-grid' : ''}`}>
<div className={`party-grid ${dungeon.partySize >= 10 ? 'raid-party-grid' : ''}`}>
{party.map((member) => (
<button
className={`party-member ${selectedId === member.id ? 'selected' : ''} ${member.health <= 0 ? 'dead' : ''}`}
@@ -1146,6 +1152,7 @@ export function CombatScreen({
<div className="bar member-health">
<span style={{ width: `${(member.health / effectiveMaxHealth(member)) * 100}%` }} />
{member.shield > 0 && <i style={{ width: `${(member.shield / effectiveMaxHealth(member)) * 100}%` }} />}
<em className="health-text">{Math.ceil(member.health)} / {effectiveMaxHealth(member)}</em>
</div>
<div className="floating-combat-texts" aria-hidden="true">
{floatingTexts
@@ -1395,6 +1402,7 @@ export function CombatScreen({
setParty(recoveredParty)
setEncounterIndex(nextIndex)
setEnemyHealth(nextEncounter.maxHealth)
elapsedTicksRef.current = 0
setElapsedTicks(0)
setStatus('playing')
addLog(`Proceeding to ${sectionName} ${currentPart + 1}. ${nextEncounter.enemyName} approaches.`, 'system')