diff --git a/IWantToHeal-Thor-v1.0.31.apk b/IWantToHeal-Thor-v1.0.31.apk new file mode 100644 index 0000000..571d70f Binary files /dev/null and b/IWantToHeal-Thor-v1.0.31.apk differ diff --git a/android/app/build.gradle b/android/app/build.gradle index 641fbc5..383b9c5 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 48 - versionName "1.0.30" + versionCode 49 + versionName "1.0.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/db/seed.sql b/db/seed.sql index a1505a2..e7a7387 100644 --- a/db/seed.sql +++ b/db/seed.sql @@ -134,22 +134,22 @@ INSERT OR IGNORE INTO spells VALUES (1, 1, 'mend', 'Mend', 'direct_heal', 5, 0.5, 30, 1, '+', 'A fast, efficient single-target heal.'), (2, 1, 'renew', 'Renew', 'heal_over_time', 7, 0.5, 12, 1, '~', 'Heals now and continues healing over time.'), - (3, 1, 'radiance', 'Radiance', 'party_heal', 12, 8, 18, 1, '*', 'Restores health to every living party member.'), + (3, 1, 'radiance', 'Radiance', 'party_heal', 12, 8, 18, 1, '*', 'Restores health to up to 4 injured party members.'), (4, 1, 'sun-ward', 'Sun Ward', 'absorb', 8, 7, 36, 1, 'O', 'Places a damage-absorbing shield on your target.'), (5, 1, 'purify', 'Purify', 'cleanse', 5, 5, 10, 1, 'x', 'Removes a harmful effect and restores health.'), - (6, 1, 'dawn-burst', 'Dawn Burst', 'party_heal', 16, 12, 28, 5, 'D', 'A brilliant wave of healing for the entire party.'), + (6, 1, 'dawn-burst', 'Dawn Burst', 'party_heal', 16, 12, 28, 5, 'D', 'A brilliant wave of healing for up to 4 injured allies.'), (7, 1, 'guardian-light', 'Guardian Light', 'absorb', 13, 14, 55, 10, 'G', 'A powerful ward reserved for moments of extreme danger.'), (8, 1, 'second-sun', 'Second Sun', 'direct_heal', 20, 20, 85, 15, 'S', 'Calls down a delayed surge of restorative light.'), - (9, 1, 'daybreak', 'Daybreak', 'party_heal', 23, 30, 48, 20, 'A', 'Floods the party with the full strength of dawn.'), + (9, 1, 'daybreak', 'Daybreak', 'party_heal', 23, 30, 48, 20, 'A', 'Floods up to 4 injured allies with the full strength of dawn.'), (20, 2, 'verdant-touch', 'Verdant Touch', 'direct_heal', 5, 0.5, 28, 1, '+', 'A quick pulse of living energy.'), (21, 2, 'seed-of-life', 'Seed of Life', 'heal_over_time', 7, 0.5, 11, 1, 's', 'Plants a restorative seed that blooms over time.'), - (22, 2, 'wild-bloom', 'Wild Bloom', 'party_heal', 12, 8, 17, 1, '*', 'Restorative growth spreads through the party.'), + (22, 2, 'wild-bloom', 'Wild Bloom', 'party_heal', 12, 8, 17, 1, '*', 'Restorative growth spreads to up to 4 injured allies.'), (23, 2, 'barkskin', 'Barkskin', 'absorb', 8, 7, 34, 1, 'B', 'Wraps an ally in protective living bark.'), (24, 2, 'purging-sap', 'Purging Sap', 'cleanse', 5, 5, 10, 1, 'p', 'Draws a harmful effect out through enchanted sap.'), (25, 2, 'ancient-grove', 'Ancient Grove', 'party_heal', 17, 12, 31, 5, 'T', 'Briefly summons the shelter of an ancient grove.'), (30, 3, 'etched-mend', 'Etched Mend', 'direct_heal', 5, 0.5, 29, 1, '+', 'Completes a simple rune of restoration.'), (31, 3, 'echo-rune', 'Echo Rune', 'heal_over_time', 7, 0.5, 12, 1, 'e', 'Repeats a restorative rune over several moments.'), - (32, 3, 'concordance', 'Concordance', 'party_heal', 12, 8, 18, 1, '*', 'Links the party through a shared healing pattern.'), + (32, 3, 'concordance', 'Concordance', 'party_heal', 12, 8, 18, 1, '*', 'Links up to 4 injured allies through a shared healing pattern.'), (33, 3, 'aegis-script', 'Aegis Script', 'absorb', 8, 7, 35, 1, 'O', 'Writes a temporary barrier around an ally.'), (34, 3, 'unravel', 'Unravel', 'cleanse', 5, 5, 10, 1, 'u', 'Unravels a hostile magical pattern.'), (35, 3, 'grand-design', 'Grand Design', 'party_heal', 16, 12, 30, 5, 'R', 'Activates a prepared network of restorative runes.'); diff --git a/src/App.css b/src/App.css index a0fd585..91be524 100644 --- a/src/App.css +++ b/src/App.css @@ -7567,6 +7567,7 @@ h2 { flex: 1; gap: 5px; grid-template-columns: repeat(5, minmax(0, 1fr)); + grid-template-rows: repeat(2, minmax(52px, 1fr)); margin-top: 5px; max-height: none; min-height: 0; @@ -7605,10 +7606,6 @@ h2 { font-size: 8px; } - .workshop-shell .ability-library > button:nth-child(n+6) { - display: none; - } - .workshop-shell .save-row .primary-button { font-size: 8px; min-height: 28px; @@ -7682,11 +7679,8 @@ h2 { } .workshop-shell .ability-library { - grid-template-columns: 1fr; - } - - .workshop-shell .ability-library > button:nth-child(n+6) { - display: none; + grid-template-columns: repeat(5, minmax(0, 1fr)); + grid-template-rows: repeat(2, minmax(52px, 1fr)); } .workshop-bottom-grid { @@ -7814,6 +7808,7 @@ h2 { flex: 1; gap: 5px; grid-template-columns: repeat(5, minmax(0, 1fr)); + grid-template-rows: repeat(2, minmax(52px, 1fr)); margin-top: 5px; max-height: none; min-height: 0; @@ -7843,9 +7838,6 @@ h2 { line-height: 1; } - .workshop-shell .ability-library > button:nth-child(n+6) { - display: none; - } } @media (max-width: 700px) and (max-height: 620px) { diff --git a/src/App.tsx b/src/App.tsx index 5f411bd..cfcf6f0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -283,6 +283,19 @@ function App() { const raid = raidOptions.find((candidate) => candidate.id === selectedRaidId) ?? raidOptions[0] const activityOptions = screen === 'raids' ? raidOptions : dungeonOptions + const startPveRoguelike = () => { + const baseDungeon = dungeonOptions[0] + const baseRaid = raidOptions[0] + if (roguelikeKind === 'raid') { + setCombatContentId(-2) + setSelectedDifficultyId(baseRaid?.difficulties[0]?.id ?? 101) + } else { + setCombatContentId(-1) + setSelectedDifficultyId(baseDungeon?.difficulties[0]?.id ?? 1) + } + setSelectedPart(1) + setScreen('combat') + } const tierOptions = activityOptions .flatMap((option) => option.difficulties) .filter((difficulty, index, all) => ( @@ -425,84 +438,90 @@ function App() { {roguelikeVariant === 'pve' && ( <> -
Upgrade Timing
-Upgrade Labels
-Run Type
+Upgrade Timing
+Upgrade Labels
+{encounter.isBoss ? `Roguelike Stage ${roguelikeStage} Complete` @@ -1359,13 +1375,18 @@ export function CombatScreen({
Pick one upgrade before the next fight.
-
diff --git a/src/components/PvpRoguelikeScreen.tsx b/src/components/PvpRoguelikeScreen.tsx
index 85c8e3b..b1827df 100644
--- a/src/components/PvpRoguelikeScreen.tsx
+++ b/src/components/PvpRoguelikeScreen.tsx
@@ -1,5 +1,15 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
-import { INITIAL_PARTY, RAID_PARTY, type CombatLogEntry, type PartyMember, type Spell } from '../game'
+import {
+ INITIAL_PARTY,
+ RAID_PARTY,
+ DEFAULT_GROUP_HEAL_TARGETS,
+ groupHealTargets,
+ partyDamageOutput,
+ tankPressureTargets,
+ type CombatLogEntry,
+ type PartyMember,
+ type Spell,
+} from '../game'
import { completeRoguelike, type DungeonReward } from '../profile'
import type { Ability, CharacterProfile, DungeonEncounter } from '../profile'
import type { GameMode } from '../gameRepository'
@@ -78,6 +88,17 @@ type FloatingCombatText = {
value: number
}
+type PvpRunSummary = {
+ bossesKilled: number
+ experienceGained: number
+ previousLevel: number | null
+ newLevel: number | null
+ levelsGained: number
+ talentPointsGained: number
+ unlockedAbilities: DungeonReward['unlockedAbilities']
+ loot: Array