current_context - xopherdeep/do-it-for-the-xp GitHub Wiki
Last Updated: 2026-10-29
Focus Area: CI/CD Autobump Workflow Orchestration on Push to Main
What was done:
-
Autobump Workflow Restored (
.github/workflows/autobump.yml):- Created dedicated
Autobumpworkflow triggering on push tomainandmasterbranches, plus manualworkflow_dispatch. - Computes the
YY.M.D-MINSversion viaHalloftheGods/.github/.github/workflows/calculate-version.yml@main. - Bumps
package.json, commitschore: auto-bump version to ${VERSION} [skip ci], creates tagv${VERSION}, and pushes commit and tag viaHalloftheGods/.github/.github/workflows/wp-plugin-update.yml@main.
- Created dedicated
-
Downstream Workflow Trigger Synchronization:
- Updated
deploy-pages.ymlto trigger viaworkflow_runafterAutobumpcompletes successfully. - Updated
build-mobile.ymlto trigger viaworkflow_runafterAutobumpcompletes successfully. - Both build workflows now check out the bumped ref (
ref: ${{ github.event.workflow_run.head_branch || github.ref }}) and readversiondirectly frompackage.json. - Removed desynchronized ad-hoc version calculation and redundant tag pushes from build workflows.
- Preserved manual
workflow_dispatchtriggers for all workflows.
- Updated
-
Test Triggers (
.github/workflows/tests.yml):- Added
mainbranch to push trigger list alongsidemaster.
- Added
What was done:
-
Native Voxel Figurine Widget (
VoxelHeroWidget.java, Slot 12):- Created dedicated 2x2 / 2x3 home screen diorama widget showcasing the player's custom 3D voxel character.
- Designed
widget_voxel_hero.xmlwith RPG window styling, floating level badge, class title, streak status, andwidget_pedestal_base.xmldiorama stage. - Created
widget_voxel_hero_preview.xmlfor launcher preview selector on Android 12+. - Bound one-tap deep link (
com.forthexp.doit://my-portal).
-
3D Voxel Avatar Integration for Companion Widget (
HeroCompanionWidget.java, Slot 9):- Updated
widget_hero_companion.xmlto two-column horizontal layout pairing the hero's 3D voxel character (@+id/widget_companion_voxel) beside the speech bubble quote. - Bound cached voxel bitmap with fallback to hero icon.
- Updated
-
Native Snapshot Decoding & Caching Pipeline (
WidgetImageHelper.java,XpWidgetPlugin.java):- Created
WidgetImageHelper.javato decode base64 PNG data URLs into internal storage (voxel_<heroId>.png). - Implemented safe downsampling during
decodeFileto prevent Binder IPCTransactionTooLargeException. - Updated
XpWidgetPlugin.syncWidgetDatato automatically cache incomingavatarImagesnapshots across all family heroes and registeredVoxelHeroWidget.classin provider broadcasts.
- Created
-
Frontend Data Extraction & In-App Preview Customizer (
widgetCatalog.ts,widgetDataExtractor.ts,XpWidgetConfigModal.vue):- Added
avatarImage?: stringtoWidgetHeroPayloadand extracted fromuser?.avatarImage. - Added
Voxel Figurinesegment button, diorama mockup, and updated companion mockup inXpWidgetConfigModal.vueadhering to Hex Color Ratchet rules (RGB tokens only).
- Added
-
RemoteViews Whitelist Compliance Fix (
widget_voxel_hero.xml,widget_voxel_hero_preview.xml):- Replaced
<View>pedestal tags with<FrameLayout>, resolving the Android launcherInflateException: Class not allowed to be inflated android.view.Viewand eliminating the "Couldn't load widget" homescreen crash.
- Replaced
-
Testing & Deployment:
- Verified unit tests:
widgetLinks.spec.ts,widgetDataExtractor.spec.ts, andwidgetSyncTrigger.spec.ts(48/48 passing). - Built debug APK with
./gradlew assembleDebug(BUILD SUCCESSFUL). - Deployed wirelessly to Pixel 9a over ADB with
Success.
- Verified unit tests:
What was done:
-
Native RPG Box Window Drawables (
android/app/src/main/res/drawable/):- Created native drawables mirroring the app's
.rpg-boxgame styles with high-fidelity gradients, bevels, and border layers:-
widget_window_finalfantasy.xml: SNES blue gradient with bevel border. -
widget_window_chronotrigger.xml: Slate window with warm gold border. -
widget_window_dragonquest.xml: Classic cobalt blue with double white border. -
widget_window_secretofmana.xml: Deep forest green with parchment border. -
widget_window_virtualboy.xml: Pitch black with high-contrast red border. -
widget_window_zelda.xml: Dark night teal with polished gold frame. -
widget_window_mariorpg.xml: Espresso frame with studded gold border. -
widget_window_phantasystar.xml: Deep cyber navy with cyan steel trim.
-
- Created native drawables mirroring the app's
-
Native Java Theme Helper & Plugin Ingestion (
WidgetThemeHelper.java,XpWidgetPlugin.java):- Added
KEY_GAME_STYLEinWidgetThemeHelperand mapped all RPG styles to their respective window drawables. - Preserved per-widget override while falling back to the globally synced game style.
- Ingested
gameStyleinXpWidgetPlugin.syncWidgetDataand saved toSharedPreferences.
- Added
-
TypeScript Sync Pipeline & Reactive Trigger (
widgetCatalog.ts,widgetDataExtractor.ts,widgetSyncTrigger.ts,useHeroThemeSync.ts):- Added
gameStyleproperty toWidgetSyncPayloadinterface. - Updated
buildWidgetSyncPayloadto accept and serializegameStyle. - Updated
syncAllWidgets()inwidgetSyncTrigger.tsto read active RPG style fromuseGameStore().theme.rpg. - Added reactive trigger in
useHeroThemeSync.tsto invokequeueWidgetSync()on theme changes.
- Added
-
Testing & Verification:
- Added unit tests for
gameStyleserialization and store extraction inwidgetDataExtractor.spec.tsandwidgetSyncTrigger.spec.ts. - Full widget test suite passed (47/47 passing).
- Built APK with
./gradlew assembleDebugand deployed wirelessly to Pixel 9a over ADB.
- Added unit tests for
What was done:
-
Menu Corner Button Removal (
src/views/LogIn/LogIn.vue,src/views/LogIn/_LogIn.scss):- Removed floating top-left
ion-menu-toggle(.menu-corner) from start/login screen to keep splash screen art clear. - Cleaned up
.menu-cornerand legacy.menu-toggleCSS rules from_LogIn.scss.
- Removed floating top-left
-
Title Screen Settings Link (
src/views/LogIn/LogIn.vue,src/views/LogIn/LogIn.ts,src/views/LogIn/_LogIn.scss):- Unhid settings action and converted it to retro text link button (
.settings-link) directly beneath "Press Start". - Replaced the inline modal with direct navigation to the existing settings home page (
/xp-settings). - Removed legacy
InputSettings,modalController, and.settings-modalstyling from the start screen. - Styled
.settings-linkwith "Press Start 2P" font, gear icon with hover rotation, and synchronizedfadeInUpanimation.
- Unhid settings action and converted it to retro text link button (
-
Public Settings Route & Navigation (
src/router/SideMenu/settings.routes.ts,src/app/SideMenu/XpSettings/components/XpSettingsHome/XpSettingsHome.vue):- Added
meta: { requiresAuth: false }to/xp-settingsand child routes so users without an active profile session can configure settings. - Added
<xp-back-button default-href="/log-in">to the Settings toolbar to allow returning directly to the title screen.
- Added
What was done:
-
Domain Invariant Enforcement (
src/lib/services/gp/wallet.ts,src/lib/utils/User/stats.ts):- Floored
nextWalletUpgrade()atDEFAULT_WALLET_LIMIT(500 GP) so the base tier is never queried as an upgrade offer, resolving soft-locks on legacy profiles. - Ensured
Statsconstructor floorsstats.gp.limitatDEFAULT_WALLET_LIMIT.
- Floored
-
Storage Self-Healing Ingestion (
src/lib/databases/ProfileDb.ts,src/lib/store/stores/user/resources.ts):- Added
hasOutdatedWalletLimit()andnormalizeProfileWallet()inProfileDb. - Updated
ProfileDb.getAll()to auto-migrate legacy profiles withlimit < DEFAULT_WALLET_LIMITand persist fixes to storage. - Added safety floor in
applyGpChange()to update outdated limits on live point adjustments.
- Added
-
Testing:
- Added regression test cases in
Wallet.spec.ts,WalletShops.spec.ts, andProfileDbPins.spec.ts.
- Added regression test cases in
What was done:
-
Native Android AppWidgetProviders (11 Total Suite):
- Expanded widget suite from 5 to 11 with 6 new providers:
-
NextQuestWidget(Slot 6): Urgent next quest countdown, reward tags, and one-tap deep link. -
LevelGaugeWidget(Slot 7): Level progress bar, XP percentage, and remaining XP to level up. -
PartyRosterWidget(Slot 8): Multi-hero status board showing HP/MP bars for up to 4 heroes. -
HeroCompanionWidget(Slot 9): Hero pixel companion, class, dynamic status quote, and portal link. -
BountyApprovalsWidget(Slot 10): Pending approvals count and overdue chores counter for Game Masters. -
SpellbookWidget(Slot 11): Action Points (AP) gauge and tactical quick-cast ability dock.
-
- Updated
BaseXpWidgetProvider.javarequest code bit-packing(appWidgetId << 8) | ((providerSlot() & 0x1F) << 3) | (target & 0x7)to safely support up to 32 distinct widget providers. - Updated
WidgetPayload.javawithallHeroes()andfirstPendingQuest()helper accessors. - Registered all 11 providers in
XpWidgetPlugin.javaandAndroidManifest.xml.
- Expanded widget suite from 5 to 11 with 6 new providers:
-
Home Screen Launcher Previews (Android 12+ / API 31+):
- Added
android:previewLayoutto all 11 widget provider XML definitions (res/xml/widget_*_info.xml). - Created
widget_quest_board_preview.xmlproviding an authentic populated preview with sample quest items in the launcher widget selector.
- Added
-
Deep Links & In-App Preview Customizer:
- Extended
widgetLinks.tswith routing forcom.forthexp.doit://abilitiesandcom.forthexp.doit://approvals. - Expanded
XpWidgetConfigModal.vuewith segment selectors, interactive mockups, and theme tokens for all 11 widgets in full compliance with Hex Color Ratchet rules (RGB tokens only).
- Extended
-
Verification:
- Clean Android compilation:
./gradlew compileDebugSourcesBUILD SUCCESSFUL. - Unit tests:
widgetLinks.spec.ts(26/26 passing),HexLiteralRatchet.spec.ts(15/15 passing).
- Clean Android compilation:
What was done:
-
In-App DLC Downloader Service (
src/lib/services/dlc/assetDlcService.ts):- Implemented singleton service managing manifest verification, progress tracking, and bulk asset download.
- Caches remote assets into HTML5
CacheStorage(xp-dlc-v1) under Capacitor's native origin. - Stores synced DLC version in
@capacitor/preferencesto prevent redundant downloads.
-
Service Worker Asset Interception (
public/alerts-sw.js):- Extended Service Worker with fetch handler for
/img/and/media/paths. - Intercepts requests, matches cached assets first, tries local APK, and falls back to remote CDN endpoints (R2 -> WordPress -> Cloudflare Pages) while asynchronously caching responses.
- Extended Service Worker with fetch handler for
-
DLC Modal UI Component (
src/components/molecules/Modals/XpDlcModal.vue):- Created retro RPG-styled modal offering "Download All" or "Stream Later".
- Displays download progress percentage and file progress meter using theme tokens.
-
App Bootstrap Integration (
src/app/App.vue,src/app/App.ts,src/main.ts):- Registered Service Worker for native Capacitor environments.
- Triggered DLC readiness checks on startup for native platforms.
-
Asset Packaging & Cloudflare R2 Upload (
scripts/upload-dlc-r2.mjs,package.json):- Built high-speed concurrent HTTP uploader leveraging Cloudflare R2 REST API.
- Successfully uploaded all 888 items (manifest,
assets-bundle.zip, and extracted assets) to remote R2 bucketxp-bgmunder/dlc/.
-
General Settings Manual DLC Trigger (
GeneralSettings.vue):- Added "Game Asset Pack" card to General Settings (
/settings/general). - Displays download/ready badge and summary text, with one-tap access to open
XpDlcModalfor manual downloading or cache refreshing.
- Added "Game Asset Pack" card to General Settings (
-
CI/CD Mobile Build Fixes (
.github/workflows/build-mobile.yml):- Fixed Android SDK license acceptance to use runner pre-installed SDK.
- Removed redundant chemx verification gate to prevent build blocking.
-
Native Beast Sprites Bundling (
.mobileignore,dist/):- Bundled 214 beast sprites (~11 MB) directly in the mobile APK/IPA to ensure instant local loading without broken image icons in Bestiary, Quests, or Battle screens.
- Preserved 60% total asset reduction (52.85 MB APK payload down from 133 MB) by keeping heavy audio (65 MB) and dungeon tiles (14 MB) in the downloadable DLC.
-
Merge Conflict Resolution (
feat/kid-creations):- Resolved conflict between Makers settings from
feat/kid-creationsand Party overhaul modes frommaster. - Verified unit tests for
PartySettings.spec.ts(both Makers and Party Modes) andXpDashboard.spec.ts(all 25 tests passing).
- Resolved conflict between Makers settings from
What was done:
-
Hex Colour Ratchet Compliance (
XpPowerCard.vue,_XpNotifications.scss,XpWidgetConfigModal.vue,XpFamilyCloudCard.vue,XpRebalancePrompt.vue):- Eliminated all raw hex colour literals in style blocks across recent UI additions, replacing them with standard RGB values, Ionic variables, and
--gs-*/--xp-app-*theme tokens. - Resolved the ratchet violation in
HexLiteralRatchet.spec.tspreventing CI failures on PR #168 and full test runs.
- Eliminated all raw hex colour literals in style blocks across recent UI additions, replacing them with standard RGB values, Ionic variables, and
-
Baseline Ratchet Lockdown (
tests/unit/hexLiteralBaseline.json):- Lowered baseline total from 1541 to 1536.
- Dropped
_MyAbilities.scssand_XpNotifications.scssfrom baseline after sweeping all remaining hex literals to zero.
-
Verification:
-
tests/unit/HexLiteralRatchet.spec.ts(15/15 passing cleanly).
-
What was done:
-
Phone App Skin Registration (
useAppSkin.ts):- Added
notifications: "#f05a5b"toXP_APP_ACCENTSfor consistent retro/modern app branding.
- Added
-
Powers Page & Rich Spell Card Grid (
XpPowerCard.vue,MyAbilities.vue,_MyAbilities.scss,powerRow.ts,MyAbilities.ts):- Enhanced
XpPowerCard.vueinto a rich spell card component with themed visual emblem tiles, icon glow effects, lock/cooldown badges, running timer indicator, high-visibility AP meters with percentage readouts, MP tags, frequency tags, and dedicated tactile Cast buttons. - Replaced flat list rows in
MyAbilities.vuewith responsive.powers-gridlayout (1 column on mobile, 2+ columns on tablet/desktop). - Wired
timerLeftOfand power state data directly into card bindings. - Preserved backwards compatibility for
BattlePowersSheet.vueandXpPowerCard.spec.ts.
- Enhanced
-
Notifications Feed Overhaul (
XpNotifications.vue,XpNotifications.ts,_XpNotifications.scss):- Converted
XpNotifications.vuefrom raw Ionic markup to the unified Phone App Kit (xp-app,xp-app-header,xp-app-section,xp-app-row,xp-app-chip,xp-app-empty). - Grouped notifications into clean sections ("New" vs "Earlier" or "Recent").
- Added color-coded duotone icons per notification kind, unread indicator dot, category tag chips, and relative timestamps.
- Added quick trailing row actions (Mark Read checkmark and Delete trash).
- Implemented bottom bar with filter pills ("All" vs "Unread" with count badge) and bulk actions ("Mark Read" and "Clear").
- Converted
-
Living Documentation (
docs/App/My-Portal/My Notifications.md):- Updated feed and management documentation reflecting Phone App Kit integration.
What was done:
-
.mobileignoreConfiguration (.mobileignore):- Established universal mobile exclusion rules for heavy assets (audio
media/**, dungeon tilesimg/[*,*].*.webp, world mapsimg/world-map.*.webp, beast spritesimg/[0-9][0-9][0-9].*.webp, and redundant Webpack Font Awesome SVGsimg/fa-*.svg). - Leaves
dist/completely intact so web builds and Cloudflare Pages deploy 100% of all assets without disruption.
- Established universal mobile exclusion rules for heavy assets (audio
-
Mobile DLC Packaging & Pruning Pipeline (
scripts/package-mobile-assets.mjs):- Created zero-dependency Node CLI script supporting
--pack-only,--prune-only, and--dry-run. - Extracts excluded assets into
dist-dlc/assets/, generatesmanifest.jsonwith SHA-256 hashes and file sizes, and compresses intodist-dlc/assets-bundle.zip. - Prunes excluded assets from native project targets (
android/app/src/main/assets/public/andios/App/App/public/), reducing native mobile asset payloads from ~132 MB down to ~40 MB (~70% reduction).
- Created zero-dependency Node CLI script supporting
-
NPM Build Integration (
package.json):- Added
assets:pack,assets:prune,assets:analyze,cap:sync:mobile, andbuild:mobilescripts.
- Added
-
Continuous Integration Workflow (
.github/workflows/build-mobile.yml):- Created GitHub Actions workflow triggered on push to
masterandworkflow_dispatch. - Sets up Node 22, pnpm, JDK 17, and Android SDK.
- Stamps build version, builds web bundle, packages DLC assets, prunes native assets, and compiles Android debug and release APKs.
- Publishes lean APKs,
assets-bundle.zip, andmanifest.jsonas release artifacts and GitHub Releases.
- Created GitHub Actions workflow triggered on push to
What was done:
-
Non-Destructive Backup Merge UI (
useBackupRestore.ts):- Updated
confirmRestoreto present a 3-way dialog when profiles already exist: "Cancel", "Merge with current data" (mode: "merge"), and "Replace everything" (mode: "replace"). - Wired
modeparameter throughrunRestoreintobackupService.restoreBackup(backup, { mode }). - Customized completion alert to display "Merge complete" or "Restore complete" based on execution mode.
- Updated
-
Pre-Link Safety Backup Prompt (
AccountSettings.vue):- Intercepted account linking when local profiles exist to prompt "Back up before linking?".
- Provides one-tap "Back up & Link" that downloads an export before redirecting to WordPress authorization.
-
Cloud Family Conflict Resolution (
XpFamilyConflictModal.vue&XpFamilyPhones.vue):- Created
XpFamilyConflictModal.vueto inspect and resolveother-familyaccount mismatches. - Compares cloud family ID and registered heroes against local device heroes.
- Allows Game Masters to adopt the cloud family ID (
adoptFamily), disconnect/unlink, or download a local backup. - Wired active "Resolve" buttons into
AccountSettings.vueandXpFamilyPhones.vuebanners.
- Created
-
Cloud Account & Sync Inspector Card (
XpFamilyCloudCard.vue&FamilySettings.vue):- Implemented
XpFamilyCloudCard.vuein Family Settings displaying cloud connection status, home/family device badges, and local vs. remote hero sync statuses. - Embedded
<xp-family-cloud-card>inFamilySettings.vuefor Game Masters.
- Implemented
-
Living Documentation (
docs/XP-Settings.md):- Comprehensive documentation added for Family Settings, Cloud Sync Inspector, Conflict Resolution, and Merge vs Replace restores.
What was done:
-
Select Profile Page Container Alignment (
SwitchProfile.vue):- Added
xp-settings-pageclass andcontent-class="ion-padding"to<xp-rpg-page>to align with standard settings page layout and padding. - Added
:class="{ 'full-row': users.length === 1 }"on mobile card grid column to center single-profile cards. - Replaced oversized desktop card class
max-w-4xlwith standardsettings-card max-w-2xlmatching settings pages. - Cleaned redundant
py-4utility padding from desktop list items and labels.
- Added
-
Grid Spacing & Shadow Geometry (
_SwitchProfile.scss):- Accounted for Earthbound RPG box 16px outer box-shadow border (
eb-box). - Replaced column padding (
8px !important) with 48px grid gap (gap: 48px,padding: 16px 16px 96px 16px), yielding a uniform 16px visible gap between cards and screen edges. - Set
margin: 16px auto; width: calc(100% - 32px); max-width: 520px;on.eb-windowand.empty-windowfor uniform 16px margins insideion-padding. - Standardized desktop
.profile-itempadding to 16px horizontal and 10px vertical.
- Accounted for Earthbound RPG box 16px outer box-shadow border (
-
Profile Card Padding Standardization (
XpProfileCard.vue):- Enforced
margin: 0 !important; width: 100% !important;so cards conform cleanly to grid columns. - Standardized
ion-card-header(padding: 1rem 0.75rem 0.5rem) andion-card-content(padding: 0 0.75rem 0.75rem). - Removed root padding bloat on
&.is-large, delegating structured padding to header and content (1.5rem 1rem 0.5rem/0 1rem 1rem).
- Enforced
What was done:
-
Pegasus Feather Crystal Splash Art:
- Selected design: Hand holding the radiant Pegasus crystal shard in the center with golden celestial spiral aura.
- 16-bit retro fantasy RPG title typography ("Do it for the XP!") centered at the top.
- Gold pixel ribbon banner: "Family Owned & Operated / Made by family, for families".
- Full pairs created for both Dark (midnight cosmos) and Light (daylight azure) themes.
-
Asset Deployment & Multi-Resolution Support:
- Master source files deployed to
assets/splash-dark.pngandassets/splash.png. - Generated 26 full-bleed Android drawable density/orientation sets across
ldpi,mdpi,hdpi,xhdpi,xxhdpi, andxxxhdpi(day and night). - Resolved aspect ratio pillarboxing via center-crop scaling for edge-to-edge rendering on all screen sizes (including custom 600x1024 tablets).
- Built and verified live on devices (
G8S1L905128401PMandb1929aa0).
- Master source files deployed to
What was done:
-
Native Android Widget Infrastructure:
- Implemented
BaseXpWidgetProvider.javaandWidgetThemeHelper.javasupporting 5 retro RPG themes: Onett Blue (earthbound), Retro Monochrome (gameboy), Molten Ruby (lava), Hometown Royal (gold), and Obsidian Deep (dungeon). - Added XML drawables for retro double-line borders (
widget_window_*.xml), stat progress bars (widget_progress_hp.xml,widget_progress_mp.xml), and badge chips (widget_badge_bg.xml).
- Implemented
-
5 Gamified Android Home Screen Widgets:
-
HeroCardWidget.java(2x2 / 4x2): Displays Hero nickname, Level, Job Class, animated-style HP/MP bars, GP purse, and streak count. Tapping launches directly into the hero portal. -
StreakAltarWidget.java(1x1 / 2x1): Displays streak flame counter, active XP multiplier (1.0x to 1.5x), and launch shortcut to Party. -
GoldVaultWidget.java(2x1 / 2x2): Retro Hometown Bank kiosk showing Wallet GP and Savings balance with one-tap ATM launcher. -
QuickDockWidget.java(4x1): Four quick-action shortcuts: + Task (com.forthexp.doit://action/add-task), Chores (com.forthexp.doit://chores), Dungeon (com.forthexp.doit://dungeon), and Party (com.forthexp.doit://party). -
QuestBoardWidget.java&QuestWidgetRemoteViewsService.java(4x2): Scrollable RemoteViews collection widget displaying today's pending chores, due times, and rewards (+XP / +GP) with deep link taps to individual quests (com.forthexp.doit://quest/:id).
-
-
Capacitor Native Bridge (
XpWidgetPlugin.java):- Registered
@CapacitorPlugin(name = "XpWidget")inMainActivity.java. - Implemented
syncWidgetData,reloadAllWidgets, andsaveWidgetConfigupdating SharedPreferences and notifyingAppWidgetManager. - Registered all 5 widget receivers and remote views service in
AndroidManifest.xmlwith deep link schemecom.forthexp.doit.
- Registered
-
Web & Store State Layer:
- Created
widgetCatalog.ts: Theme configurations and sync payload interfaces. - Created
widgetDataExtractor.ts: Pure converters extracting hero stats, quest list items, streak bonuses, and bank balances. - Created
widgetSync.ts: Capacitor plugin wrapper with browser fallback. - Created
widgetSyncTrigger.tsand wired automatic widget sync onuserStoreprofile persistence flush (persistence.ts).
- Created
-
In-App Widget Preview & Customization (
XpWidgetConfigModal.vue):- Interactive live preview modal with retro widget themes, real-time hero stats rendering, and manual sync action.
- Integrated into Theme Settings (
ThemeSettings.vue) under "Home Screen -> Android Widgets".
-
Verification:
- Unit tests:
tests/unit/widgetDataExtractor.spec.ts(5/5 passing). - TypeScript type check:
npm run typecheck(0 errors).
- Unit tests:
What was done:
-
Party Invites Hub (
XpShareApp.vueat/tell-a-friend):- Replaced legacy mock referral placeholder with active Family & Party Invites Hub.
- Added "Invite Your Family" section with "Add Hero on this Device" (opens
AddProfile.vuemodal) and "Link a Hero's Phone (QR Code)" (opensXpHeroPhonesModal.vue). - Added direct link to Town Hall if unlinked, plus link to Family Settings.
- Added "Invite Friends & Allies" section with real share sheet (
@capacitor/share) and "Copy Invite Link" action.
-
Party Tab Action Wiring (
PartyRosterTab.vue+MyParty.ts/MyParty.vue):- Added prominent "+ Add Hero / Invite Family" action button to the Party Roster.
- Added per-hero phone linking quick action button (
<i class="fad fa-mobile-alt"></i>) in the roster. - Wired Action Sheet dialog to create new profiles or generate pairing QR codes / codes for heroes on demand.
-
Family Settings Onboarding (
XpFamilyPhones.vue):- Added graceful unlinked card when multiplayer flag is on but Town Hall is not yet connected (
data-cy="family-phones-connect"). - Added direct button to navigate to Town Hall to complete multiplayer setup.
- Updated unit tests in
XpFamilyPhones.spec.ts(22/22 passing).
- Added graceful unlinked card when multiplayer flag is on but Town Hall is not yet connected (
-
Verification:
-
chemx test tests/unit/XpFamilyPhones.spec.ts tests/unit/partyStats.spec.ts(49/49 passing). -
chemx typecheckclean. -
chemx checkclean (0 hazards across all modified components).
-
What was done:
- Source: screenshots in
tools/For the xp/(S'moresUp chores, boss fights, reward shelf). -
StarterWorld.ts: 3 new categories (
cat-family,cat-health,cat-bosses) and new quests mapped to library beasts where one fits. - rewardPresets.ts: 12 new GP shop rewards (boba, pizza night, game nights, spa, Lego, bike and more).
- AbilityPresets.ts: 3 new real-life AP powers (Car DJ, App Extension Time, YES Day).
-
StarterWorld.spec.ts: timed-quest assertion relaxed to
toMatchObject(16 passed). - Not yet covered: remaining shelf items (consoles, gems), streak quests, dog and sibling chores.
What was done:
- Enabled multiplayer in production builds via
.env.production(VUE_APP_MULTIPLAYER=true). -
Party Tab Honesty Pass (#1334):
- Replaced mock/random online dots and activities in
MyParty.vue. - Decomposed 735-line component into
MyParty.vue,MyParty.ts,_MyParty.scss, and subcomponents undersrc/app/Console/MyPortal/party/. - Implemented real daily streak counting consecutive days with approved quest logs in
partyStats.ts(27/27 unit tests passing). - Wired latest 20 approved quest logs into activity feed (
partyStats.ts). - Added Cypress test in
tests/e2e/specs/party.spec.js.
- Replaced mock/random online dots and activities in
- MP12 (#1305): Verified family store sending, cards diffing, and single-flight flush (66/66 unit tests passing).
-
MP13 (#1306): Finished
XpFamilyPhones.vuecard in Settings with comprehensive unit tests for age pickers, error banners, and home transfer (22/22 unit tests passing). -
MP14 (#1307): Implemented
deviceLink.ts,HeroDeviceDb.ts, and kid-mode store state and actions (94/94 unit tests passing). -
MP15 (#1308): Implemented
XpHeroPhonesModal.vuewith live QR code generation (qrcode),ABCD-EFGHformatted code, 10-minute expiry countdown, and device list (6/6 unit tests passing). -
MP16 (#1309): Implemented
/linkclaiming flow inLinkPhone.vue, ML Kit barcode camera scanner, and profile chooser empty state hero button (6/6 unit tests passing). -
MP17 (#1310): Implemented Kid Mode router guards (
heroPhone.guard.ts), GM lockout ingm.guard.ts, and/hero-phoneview with 3D voxel model and unlinked recovery (133/133 unit tests passing across guard and view specs). -
MP18 (#1311): Implemented server reward deduplication with
eventInbox.ts,"party"receipts inQuestLogDb, and auto-download triggers infamily.ts(89/89 unit tests passing). - Review #1331: Completed deep review of MP12 and MP18, confirming all 6 critical event stream and reward invariants hold.
-
MP19 (#1312): Created comprehensive Cypress end-to-end spec in
tests/e2e/specs/family.spec.jsand fixtures intests/e2e/fixtures/family/. - All tasks committed and marked done on ChemX. MP20 (#1313) queued for full rehearsal.
What was done:
- Created dedicated thief encounter domain logic in thiefEncounter.ts:
- Constants:
THIEF_BEAST_ID = "beast-thief",THIEF_ENCOUNTER_RATE = 0.20,THIEF_POTION_STEAL_RATE = 0.40. - Thief enemy factory
createThiefEnemy()configured with no tasks, standard beast stats, avatar 189, raccoon emoji. - Identification helper
isPotionOrEther()recognizing potion, ether, elixir, and registered potion catalog items. - Safe theft calculation
calculateStolenGp()stealing 10% to 25% of wallet GP (min 5, max 50 GP), safely bounded by available wallet. - Orchestrator
stealFromHero()deducting GP and optionally consuming one potion or ether from inventory.
- Constants:
- Integrated Thief encounter into battle routing and guard systems:
- Extended
BattleContextandPendingAmbushwithencounter?: stringin battleContext.ts and battle.ts. - Updated battle.guard.ts with
isThiefRoll()triggering random thief encounters (query?encounter=thief), preserving parameters across background alerts and return callbacks.
- Extended
- Integrated Thief encounter into battle pipeline and stage presentation:
- Updated encounterLoader.ts to detect
encounter === "thief"orbeastIds.includes("beast-thief")and return a thief encounter (thief: true). - Updated BattleEnemyStage.vue to hide the chores panel for thief enemies (
v-if="enemy && !enemy.isThief"), preventing "0 tasks left" displays. - Implemented
startThiefEncounter()in BattleField.ts displaying surprise leap dialogue, applying hit feedback and sound on stolen loot, reporting GP and potion losses or empty pockets, and executing fadeout escape automatically.
- Updated encounterLoader.ts to detect
- Documentation:
- Updated Random Encounters.md with details on the Thief Beast encounter and theft rates.
- Verification & Quality:
- Added unit test suite ThiefEncounter.spec.ts covering theft calculation, item detection, userStore integration, and edge cases (12/12 passing).
- Updated encounterLoader.spec.ts (34/34 passing).
What was done:
- Retired the placeholder center room FAB (
ion-fab id="room-action") in TempleGrounds.vue. - Implemented modular 3D voxel room model organism XpDungeonRoomModel.vue:
- Interactive 3D WebGL landmark canvas with Three.js renderer integration via useDungeonRoomScene.ts.
- Drag-to-rotate interactivity for 3D exploration.
- Chest lure animation (
@keyframes chest-bob), golden treasure aura (drop-shadow), and hover elevation. - Earthbound-style title badges with action cues via
<xp-landmark-badge>(e.g. "Treasure Chest", "Tap to open!"). - Accessible keyboard control (
role="button",tabindex="0", Enter/Space) and SFX triggers.
- Built comprehensive 3D voxel geometries in dungeonRoomShapes.ts:
- Unopened treasure chest with iron brackets, curved lid, golden ribs, lock plate, and scattered coins.
- Open empty chest with tilted lid and hollow interior.
- Boss/Master chest variant with crimson body, gilded dragon trim, and inset ruby.
- Custom voxel models for all dungeon room types: Key, Healing Spring, Mana Spring, Campfire, Puzzle Stela, Teleport Circle, Merchant Stall, Save Monument, Pegasus Egg Altar, Secret Alcove, Stairs Up/Down, Temple Entrance, Exit Gate, Spike Trap, Dark Chasm, Dusty Chamber, and Cleared Victory Trophy.
- Updated TempleGrounds.ts and _TempleGrounds.scss to center the room voxel model and support cleared room markers.
- Verification & Quality:
- Unit tests added: dungeonRoomVoxel.spec.ts (25 passed, 25 total).
- TypeScript type check clean (0 errors).
- Chemical X lint/check clean (0 violations).
What was done:
- Scaled up attack typography and icons in XpBattleTaskMenu.vue:
- Chore attack item text (
.battle-task-item): raised font size from1.25remto1.5remwithline-height: 1.25for improved mobile readability. - Claw attack icons (
.task-icon): enlarged from1.3rem/width: 1.6remto1.5rem/width: 1.8rem. - Sheet title and subtitle: raised title from
1.4remto1.55rem(icon1.35rem) and subtitle from0.95remto1.05rem. - Confirmation question and action buttons: increased
.confirm-questionto1.15remand.rpg-buttonto1.35rem.
- Chore attack item text (
- Verification & Quality:
- Unit tests: XpBattleTaskMenu.spec.ts (18 passed, 18 total).
What was done:
- Implemented GP bribery mechanic for fleeing combat:
- Added pure calculation helpers in bribeMath.ts:
- Base bribe:
Math.max(5, Math.round(attack * 1.5))scaled by beast attack. - Wealth surcharge: 5% of total wealth (
wallet + savings). - Grudge scaling: 50% increase per grudge mark (
1 + marks * 0.5). - Low bribe tier: 50% discount (
Math.floor(fullCost * 0.5)).
- Base bribe:
- Extended escape types in types.ts:
- Added
bribed,bribeTier, andbribeCosttoEscapeReport. - Added
"bribe-full"and"bribe-low"toBattleAction.
- Added
- Added Earthbound-style flavor dialog lines in dialogLines.ts.
- Updated engine in BattleService.ts:
- Added
getBribeQuotesandhandleBribe. - Handled wallet GP deduction via
userStore.updateUserGP.
- Added
- Updated battle outcome logic in useBattleOutcome.ts:
- Skipped grudge mark penalties when hero escapes with a full bribe.
- Updated UI radial menu and action triggers:
- BattleField.ts: Added bribe menu actions to run confirmation cluster, wired reactive GP tracking.
- XpBattleRadialMenu.vue: Added gold full bribe and secondary low bribe buttons.
- Added pure calculation helpers in bribeMath.ts:
- Verification & Quality:
- Unit tests added: BattleBribe.spec.ts (10 passed).
- Test suites updated: BattleOutcomeDefeat.spec.ts, XpBattleRadialMenu.spec.ts, BattleField.spec.ts.
What was done:
- Added Lego Monster beast portrait asset:
- Generated and keyed out 480x480 RGBA WebP sprite saved at 294.webp.
- Bumped
TOTAL_BEAST_AVATARSto 294 in BestiaryService.ts. - Bumped
nAvatarsto 294 in AvatarSelect.vue. - Added
lego-monster: 294mapping in beast_numbers.json.
- Seeded Lego Monster beast and quest in StarterWorld.ts:
- Defined
STARTER_LEGO_BEASTwith idbeast-lego-monster, 4-step chore checklist, earth element, avatar 294, and battle backgrounds. - Included
STARTER_LEGO_BEASTinSTARTER_BEASTS. - Added quest seed
quest-lego("Dismantle the Lego Monster") undercat-chamber("The Hero's Chamber") scheduled daily in the evening.
- Defined
- Added vocabulary support:
- Added
legoandlegossynonyms to librarySuggest.ts.
- Added
- Verification & Quality:
- Unit tests updated and passing: StarterWorld.spec.ts, beastLibrary.spec.ts, BestiaryService.spec.ts, librarySuggest.spec.ts.
- TypeScript type check clean (
npm run typecheck, 0 errors).
What was done:
- Implemented accelerating pulsation animation for the battle attack timer bar in BattleEnemyStage.vue:
- Added dynamic
--pulse-durationcalculation scaling smoothly from a steady 1.6s rhythm at full clock (100%) down to an urgent 0.3s heartbeat at zero or critical state. - Bound
--pulse-durationCSS variable to.attack-timercontainer for seamless child inheritance. - Added continuous pulsating glow to
.attack-timer-filland synchronized outer border glow to.attack-timer-bar. - Updated
@keyframes timer-pulseand added@keyframes timer-bar-pulsewith rhythmic brightness and glow intensity. - Ensured reduced motion preferences cleanly disable animations across the timer bar, fill, and labels.
- Added dynamic
- Verification & Quality:
- Unit tests updated and passing: BattleEnemyStage.spec.ts (58 passed).
- Existing suite passing: BattleField.spec.ts (17 passed).
What was done:
- Removed sprite animation from ATM prompts in bankPrompts.ts:
- Removed
sprite: 'atm'fromatmMenuPromptto prevent the sunburst rays and pixel sprite from covering the retro CRT ATM display. - Updated
amountAskto omit sprite animations and apply'atm'accent when invoked with'ATM'as the speaker.
- Removed
- Updated ATM errand caller in ATMModal.vue:
- Set speaker explicitly to
'ATM'inamountAskcalls so amount stepper dialogs do not show spinning coin rays over the kiosk.
- Set speaker explicitly to
- Styled subtle backdrop for ATM prompts in XpRevealPrompt.vue:
- Bound
accent-${options.accent}to prompt root. - Added
.rp.accent-atm .rp__backdropwithrgba(10, 2, 10, 0.25)to keep the CRT scanlines and account statements fully readable.
- Bound
- Verification & Quality:
- Unit tests updated and passing: BankPrompts.spec.ts (16 passed).
- Existing suite passing: XpRevealPrompt.spec.ts (27 passed).
- TypeScript type check clean (
npm run typecheck, 0 errors).
What was done:
- Implemented
hotelRegistry.ts(hotelRegistry.ts):- Defined
HotelMetadatainterface and registered thematic lodgings across all 10 worlds:- Hometown: Grand Hotel (Hotel Concierge)
- Plains: Windward Inn (Innkeeper Zephyr)
- Islands: Coral Cove Resort (Concierge Marina)
- Forest: Canopy Lodge (Lodge Keeper Bramble)
- Mountains: Highland Peak Inn (Host Boulder)
- Desert: Mirage Oasis Hotel (Hostess Dunestar)
- Swamps: Foggy Bayou Inn (Night Porter Moss)
- Ice: Frostpeak Lodge (Lodge Host Ymir)
- Clouds: Stratus Palace Hotel (Steward Nimbus)
- Moon: Lunar Orbital Suites (Steward Astra)
- Exported
getHotelByWorld,getHotelMetadata, andgetAllHotels. - Added
hotelIdtoWorldMetadataand all entries in worldRegistry.ts.
- Defined
- Parameterized hotel routing and parent resolution:
- Updated hotel route in hometown.routes.ts to
/hotel/:userId?/:world?. - Updated
parentOf.ts(parentOf.ts): regional hotel routes now resolve their parent back to the origin regional world, ensuring Back and "Leave Hotel" return players directly to where they entered.
- Updated hotel route in hometown.routes.ts to
- Updated XpBuildingModel.vue:
- Added
isHoteldetection supporting bothhoteland*-hotelidentifiers. - Automatically builds 3D hotel voxel model for all hotels.
- Resolves badge title from
getHotelByWorld(activeWorld)and badge sublabel to"Pay to rest". - Routes to
/hotel/:userId/:worldpassing the active world parameter.
- Added
- Refactored HotelHub.vue and HotelHub.ts:
- Dynamic hotel title bound to
hotelTitle. - Cleaned up obsolete WordPress item grid and legacy test alert configuration.
- Dynamic clerk speaker name and hotel greeting with
{hotel}support in npc.ts and hometownPrompts.ts. - Preserved full night rest cycle: GP deduction, full HP and MP restoration,
restoreAllaudio, and receipt notice.
- Dynamic hotel title bound to
- Mounted draggable hotel landmarks across all 9 regional world views:
- WorldPlains.vue (x: 48, y: 26)
- WorldForest.vue (x: 46, y: 28)
- WorldIslands.vue (x: 68, y: 38)
- WorldSwamps.vue (x: 68, y: 36)
- WorldMountains.vue (x: 28, y: 38)
- WorldDesert.vue (x: 28, y: 38)
- WorldClouds.vue (x: 68, y: 32)
- WorldIce.vue (x: 24, y: 38)
- WorldMoon.vue (x: 28, y: 34)
- Verification & Quality:
- Unit tests: HotelRegistry.spec.ts (8 passed), Lodging.spec.ts (21 passed), HometownPrompts.spec.ts (27 passed), parentOf.spec.ts (31 passed), DraggableSpot.spec.ts (16 passed), PegasusWorldModel.spec.ts (9 passed).
- TypeScript type check passed cleanly (
npm run typecheck, 0 errors).
What was done:
- Created TempleFloor.vue providing procedural CSS floor tiles for rooms without pre-rendered WebP background art:
- House theme varieties for The Old House:
- Hardwood timber planks (
temple-floor--wood) for living room, front hall, bedrooms, dining room, and office. - Checkered ceramic tile floor (
temple-floor--tile) with grout for kitchen, pantry, and bathrooms. - Weathered outdoor wood decking (
temple-floor--deck) for front porch, back deck, and yard. - Concrete/slate stone slabs (
temple-floor--slab) for garage, basement, and storage.
- Hardwood timber planks (
- Elemental dungeon flagstone pavers (
temple-floor--dungeon) for custom and generated temples colored by element (fire, ice, water, earth, light, shadow, moon, storm, wind). - Perimeter vignette and radial torch lighting (
temple-floor__shade) creating depth where walls meet floors. - Thematic room emblems: boss mystic circle, entrance welcome mat, and sanctuary glowing circles.
- House theme varieties for The Old House:
- Wired TempleGrounds.vue and TempleGrounds.ts:
- Renders
<temple-floor>on walkable rooms when no pre-rendered image asset exists. - Updated walls for The Old House to use warm cedar/brass styling (
&--homein TempleWalls.vue).
- Renders
- Enhanced custom and moving temple element/metadata resolution:
- Updated
metadataForAsyncin templeRegistry.ts to query TempleDb for non-shipped temples. - Updated
templeElementForin RoomBeast.ts to respect record elements for custom temples and The Old House. - Guarded
getBgImagein useTempleLayout.ts against missing temple asset folders.
- Updated
- Verification & Quality:
- Unit tests created: TempleFloor.spec.ts (8 passed).
- Existing suite passed: RoomBeast.spec.ts (29 passed), movingTempleReset.spec.ts, templeAudit.spec.ts (57 passed).
What was done:
- Redesigned empty profile notice in SwitchProfile.vue:
- Replaced naked low-contrast floating text (
empty-state) with authentic Earthbound CRT window (eb-window empty-window). - Added signature multi-layer retro pixel borders, solid
#280828backdrop blocking the animated checkerboard background, and dual-layer header ("CHOOSE A PROFILE", "FILE SELECT"). - Added framed duotone hero icon (
fad fa-users-slash), bold retro title ("No Adventurers Yet!"), and crisp high-contrast description in"StatusPlz"monospace. - Mounted interactive "Start New Game" file slot CTA directly inside the window body (
eb-file-slot eb-new-slot), providing an immediate creation pathway on both desktop and mobile. - Wrapped populated profile views in
<template v-else>: eliminates layout duplication on desktop where the empty text previously sat above the separate desktop card. - Conditioned view-toggle left FAB on
users.length > 0to keep mobile chrome clean when no profiles exist.
- Replaced naked low-contrast floating text (
- Menu Architecture Clarification:
- Documented dual-menu responsive divergence: navigation sidebar (
SideMenu.vue) auto-collapses off-canvas viaion-split-panebehind top-left hamburger on mobile, while profile list card (SwitchProfile.vue) was previously isolated behind Tailwindhidden md:block.
- Documented dual-menu responsive divergence: navigation sidebar (
- Verification & Quality:
- TypeScript typecheck passed cleanly (
npm run typecheck, 0 errors). - Unit tests passed: familyPrompts.spec.ts (29 passed).
- TypeScript typecheck passed cleanly (
What was done:
- Redesigned ATM screen and modal artwork in ATMModal.vue:
- Replaced generic white card and floating FontAwesome icon with a retro CRT ATM kiosk enclosure.
- Added marquee header banner with glowing green LEDs, status indicator pulse, and Hometown National Bank branding.
- Implemented phosphor CRT display with deep green scanlines, curved surface glare, and terminal header ("TERMINAL #402", "ACCOUNT STATEMENT").
- Formatted cash and savings readouts in glowing monospace phosphor typography (
"StatusPlz") with color-coded status glow (gold wallet, green savings, red hospital debt). - Added lower machine bay featuring tactile screen-side function keys, card reader with green insertion slot, cash dispenser slit, and metallic 12-key numeric pad.
- Created dedicated retro ATM pixel sprite in revealSprites.ts:
- Defined
atmsprite (44x40) with chassis body, glowing green CRT monitor, function keys, card slot, and key bay. - Added
'atm'toRevealSpriteNamein revealPrompt.ts. - Updated
atmMenuPromptin bankPrompts.ts to displaysprite: 'atm'instead of generic coins.
- Defined
- Verification & Quality:
- Unit tests passed: XpRevealPrompt.spec.ts (27 passed), StarterWorld.spec.ts (16 passed), PurchaseService.spec.ts (42 passed).
What was done:
- Added basic in-game consumable items to catalogue presets in rewardPresets.ts:
- Defined
BASIC_CONSUMABLE_PRESETS: Health Potion (50 GP), Mana Potion (75 GP), Ether (100 GP), and Elixir (200 GP). - Added
consumableFromPresetmapping them toAccessorywithAccessoryType.Virtualandtags: ["consumable", "preset"]. - Updated
ALL_REWARD_PRESETSandpresetsNotInto include consumables in the Compendium catalogue.
- Defined
- Stocked shops across the starter world in StarterWorld.ts:
- Hometown Market carries the complete catalogue (all basic consumables + real-life rewards).
- Regional shops stock Health Potion and Mana Potion alongside their rotating accessories.
- Updated purchase service & flow in PurchaseService.ts:
- Implemented
isConsumableItem: recognizes in-game consumables, potions, ethers, and elixirs. - Added capacity validation: verifies
canCarry(hero, item)before purchase; throwsPurchaseError("bag-full")if inventory and storage are full without deducting GP. - Added immediate fulfillment: purchases of in-game consumables add the item directly to
user.inventoryviauserStore.addInventoryItem(userId, consumableRawItem)and log status as"fulfilled"(skipping physical GM handover queues).
- Implemented
- Enhanced shop UI and dialogue copy:
- Added
shop.buy.consumableReceiptandshop.buy.bagFullin npc.ts. - Added
consumablePurchaseReceiptand bag-full prompt handling in shopPrompts.ts. - Wired consumable receipt and bag-full feedback in AccessoryShop.ts.
- Added
- Verification & Quality:
- Unit tests: PurchaseService.spec.ts (42 passed), StarterWorld.spec.ts (16 passed), BattlePotions.spec.ts (24 passed), and BattleItems.spec.ts (23 passed).
What was done:
- Restored rain to swamp weather preset in presets.ts:
- Updated
weatherPresets.swamplayers to includefx.rainalongsidefx.fogandfx.fireflies. - Updated ambient audio loop to
"rain".
- Updated
- Verification:
- Unit tests: WeatherFX.spec.ts and WeatherCanvas.spec.ts (33 passed, 33 total).
What was done:
- Redesigned 3D hotel voxel model in buildingShapes.ts:
- Upgraded from muted brown/green inn styling to a vibrant, multi-tiered grand red hotel.
- Added charcoal/red carpet entryway foundation.
- Multi-tier crimson, ruby, and scarlet facade blocks (
#b71c1c,#c62828,#d32f2f,#e53935). - Flashy marquee canopy with neon yellow/gold borders (
#ffd700,#ffea00,#ff1744). - Gold balconies and railings with glowing suite windows (
#ffff8d). - Rooftop neon "HOTEL" marquee sign board with white glowing letter styling.
- Crowned rooftop beacon spire with gold orb and crimson beacon light.
- Verification & Quality:
- Unit tests: buildingVoxel.spec.ts (38 passed, 38 total).
What was done:
- Brought full-screen fanfare reveal to Beast Log Quest Wizard on quest summoning:
- In
XpQuestWizardModal.vue: embedded<xp-hero-fanfare>overlay triggered on quest creation. - Dynamically populates fanfare props (
name,subtitle,portrait,title="A new quest joins the log!",actionText="Accept quest"). - Added adventure BGM (
nowLetsGo) playing alongside the level-up stinger burst. - Dismisses cleanly on backdrop click or "Accept quest" button press, emitting
savedandclose.
- In
- Enhanced
XpHeroFanfare.vueand confetti engine for bigger, richer visual impact:- Generalized
XpHeroFanfare.vueprops (name,subtitle,title,actionText,sound) with defaults preserving existing hero creation flow. - Expanded sparkle particle count from 14 to 24 with increased reach (up to 205px) and varied sizes.
- Enlarged rotating ray wheel from 640px to 800px and burst flash from 110px to 160px (
_XpHeroFanfare.scss). - Added 3-wave confetti burst cascade (80 first wave, 45 second wave, 30 third wave per edge) and raised total chip cap to 480 in
confetti.tsandXpConfettiBurst.vue.
- Generalized
- Verification & Quality:
- Unit tests:
QuestFanfare.spec.ts(2 passed),HeroFanfareConfetti.spec.ts(10 passed).
- Unit tests:
What was done:
- Fixed bloated vertical height and duplicate continue markers across RPG dialogs:
- In
XpTypingText.vue: replaced right-floatedfad fa-caret-down fa-2x float-right mt-3marker with inline.typing-more-marker(▼, color#ffd84a, font-size0.85em, subtle bounce animation). Eliminates layout distortion and vertical clearance blowup. - In
XpNpcDialog.vue: refined styling with compact padding (10px 14px 12px,min-height: 48px), max-width 520px, subtle backdrop blur (rgba(10, 2, 10, 0.45),backdrop-filter: blur(2px)), safe-area bottom inset padding, and crisp header divider. - In
GoldBank.vue: hid clerk FAB button while conversation is active (v-show="!isTalking"). - In
HospitalHub.vue,HotelHub.vue,XpAboutAp.vue,XpAboutGp.vue, andXpAboutXp.vue: removed duplicate.dialog-indicatorelements and hid trigger FABs while dialogs are open. CorrectedhasMoreTextprop binding inHospitalHub.vue.
- In
- Verification & Quality:
- Unit tests: AccessoryShopComponents.spec.ts (12 passed, 12 total).
What was done:
- Allowed open "anytime" chores (quests without an explicit clock due time) to trigger quest ambush encounters:
- Updated questAmbush.ts
pickQuestAmbush: anytime quests qualify for encounters alongside overdue quests. Overdue quests retain priority and trigger first. - Updated OS notification copy in
ambushAlertCopyto state${quest} is waiting. Come back and fight!instead of asserting overdue. - Updated questRoomPicker.ts: renamed
neverAmbushesproperty toisAnytime, updatedANYTIME_AMBUSH_NOTEnote text to"no due time: ambushes any time"with backwards-compatibleNEVER_AMBUSHES_NOTEalias. - Updated documentation in Quest-Rooms-Spec.md (Section 5.9).
- Updated questAmbush.ts
- Verification & Quality:
- Unit tests: questAmbush.spec.ts, BattleGuard.spec.ts, QuestRoomPicker.spec.ts, and BattleOutcomePassives.spec.ts all pass green.
- Verified approval-required quests properly hold pending claims and delay rewards during battle victories.
What was done:
- Battle dialog box padding and room (_BattleField.scss):
- Adjusted box padding to
14px 20px 16px(was5px 0 0) withmin-height: 96px. - Added 22px right padding to
.dialog-contentand raisedmax-heightto 260px to avoid text overlap with the▼more indicator. - Set
.battle-zone--actionsfrom fixedheight: 176pxtomin-height: 176pxto accommodate multi-line growth.
- Adjusted box padding to
- Forced auto-scroll on dialog growth (BattleDialogBox.vue):
- Added template ref on
.dialog-content. - Implemented
scrollToBottomtriggered viaMutationObserveron child/text mutations and post-flush watchers ontextandaccumulatedLines.length. - Level-up message lines and typing text stay automatically scrolled to the latest entry without manual scrollbar dragging.
- Added template ref on
- Verification: 14 of 14 unit tests in
BattleField.spec.tspassing green.
What was done:
- Updated counter label in BattleEnemyStage.vue from
${left.value} ${left.value === 1 ? "chore" : "chores"} leftto${left.value} ${left.value === 1 ? "task" : "tasks"} left. - Updated test suites to reflect the "tasks left" terminology:
- BattleEnemyStage.spec.ts
- BattleField.spec.ts
- battle.spec.js
- moving-pack.spec.js
- quest-grudge.spec.js
- quest-rooms.spec.js
- Verification: 71 of 71 unit tests passed green across
BattleEnemyStage.spec.tsandBattleField.spec.ts.
What was done:
- Migrated legacy top segment tabs to unified bottom navigation dock across all in-game sub-apps:
- Created reusable
XpAppBottomNav.vueorganism andAppNavTabinterface (appBottomNav.ts):- Replicates visual styling and haptics of
XpBottomNav(backdrop-filter: blur(16px),rgba(16, 12, 28, 0.75), gold active highlight#ffd700, notification badges,play$fx("select")audio feedback). - Globally registered
<xp-app-bottom-nav>insrc/main.ts.
- Replicates visual styling and haptics of
- Migrated 7 in-game sub-apps:
-
Goods (
XpInventorySheet.vue,MyInventory.vue): Bottom dock withAll,Potions,Keys,Materials,Toolstabs featuring reactive item count badges. Removed redundant legacy footer chevrons. -
Spells (
MyAbilities.vue,MyAbilities.ts): Bottom dock withAll,Privileges,Spells,Unlocked,Lockedtabs (POWER_TABS). Moved searchbar to header. -
Quests (
MyQuests.vue,MyQuests.ts): Bottom dock withBoardandListtabs (including activetodoCountbadge). Moved searchbar to header. -
Workbench (
MyCrafts.vue,MyCrafts.ts): Bottom dock withAll,Furniture,Accessories,Weapons,Keytabs (WORKBENCH_TABS). Compact page switcher in footer above dock; searchbar in header. -
Storage (
MyStorage.vue,MyStorage.ts): Bottom dock withAll,HP,MP,Misc,Keytabs (STORAGE_TABS). Compact page switcher in footer above dock; searchbar in header. -
Kitchen (
MyFoods.vue,MyFoods.ts): Bottom dock withAll,Favorites,Meals,Snacks,Desserts,Pantrytabs (FOOD_TABS). Searchbar in header. Fixed template toolbar closure. -
Calendar (
MyCalendar.vue,_MyCalendar.scss): Bottom dock withAll,Morn,Noon,Eve,Nighttabs (calendarTabs). Compact day navigation buttons in footer above dock; searchbar in header.
-
Goods (
- Created reusable
- Verification and Quality:
- Unit tests:
XpAppBottomNav.spec.ts(5/5),QuestSchedule.spec.ts(65/65),XpInventoryModal.spec.ts(5/5),QuestList.spec.ts(23/23). - TypeScript typecheck passed with zero errors (
pnpm run typecheck).
- Unit tests:
What was done:
- Standardized retro RPG font families and discrete font size scale across the battle screen:
- Battle dialogue:
"Apple Kid", "StatusPlz", monospaceat1.55rem(_BattleField.scss). - Battle and radial prompts: Harmonized to
"StatusPlz", monospaceat1.15remwith 1px letter spacing (_BattleField.scss,XpBattleRadialMenu.vue). - Action pills and menu buttons: Standardized to
"Apple Kid", "StatusPlz", sans-serifat1.15rem-1.25rem(XpBattleRadialMenu.vue,BattleSheet.vue,XpBattleTaskMenu.vue). - Enemy stage typography:
- Enemy nameplate: Updated to
"StatusPlz", monospaceat1.2remwith uppercase styling (BattleEnemyStage.vue). - Chores remaining counter: Standardized to
"StatusPlz", monospaceat1.15rem(BattleEnemyStage.vue). - Attack countdown timer: Unified caption to
"StatusPlz", monospaceat0.85remand timer digits to"StatusPlz", monospaceat1.25remwith tabular numbers (BattleEnemyStage.vue).
- Enemy nameplate: Updated to
- Hero status card typography:
- Hero name: Standardized to
"StatusPlz", monospaceat1.05rem(BattleHeroCard.vue). - Hero level: Raised from
0.72remto0.85remin"StatusPlz", monospace(BattleHeroCard.vue). - Hero initial: Unified to
0.85rem(BattleHeroCard.vue). - HP / MP stat captions: Standardized to
0.85remin"Fourside", "StatusPlz", monospace(BattleHeroCard.vue). - Defending badge: Unified to
0.85remin"StatusPlz", monospace(BattleHeroCard.vue).
- Hero name: Standardized to
- Battle modal sheets and inventory:
- Sheet titles: Standardized to
"Apple Kid", "StatusPlz", sans-serifat1.4rem(BattleSheet.vue,XpBattleTaskMenu.vue). - Sheet subtitles: Unified to
"StatusPlz", monospaceat0.95rem(BattleSheet.vue,BattlePotionSheet.vue,XpBattleTaskMenu.vue). - Item and power titles: Harmonized to
"Apple Kid", "StatusPlz", sans-serifat1.25rem(BattlePotionSheet.vue,BattlePowersSheet.vue,XpBattleTaskMenu.vue). - Descriptions and effects: Unified to
"StatusPlz", monospaceat0.85rem(BattlePotionSheet.vue,BattlePowersSheet.vue). - Goods sheet and modal: Standardized segment tabs (
0.85rem), tab badge counts (0.7rem), goods names (1.05rem), goods blurbs (0.85rem), MP costs (0.85rem), refusal reasons (0.85rem), quantities (0.95rem), and modal title (1.15rem) in"StatusPlz", monospace(XpInventorySheet.vue,XpInventoryModal.vue).
- Sheet titles: Standardized to
- Victory card: Harmonized subtitle (
1.15rem), quest line (1.15rem), work line (1.15rem), held badge (0.95rem), and footer prompt (1.15rem) (BattleVictoryCard.vue).
- Battle dialogue:
- Test suite verification:
- 146 of 146 battle unit tests passed (
BattleField.spec.ts,BattleEnemyStage.spec.ts,BattleHeroCard.spec.ts,BattleVictoryCard.spec.ts,XpBattleRadialMenu.spec.ts,XpInventoryModal.spec.ts). - 50 of 50 battle consumable unit tests passed (
BattleItems.spec.ts,BattlePotions.spec.ts). - Total 196 of 196 tests passing green.
- 146 of 146 battle unit tests passed (
What was done:
- Implemented iOS-style organize mode for landmark positioning and rotation decoupling:
- Long-press (500ms) on any landmark triggers Organize Mode across all spots.
- Active organize mode adds retro wobble animation (
ios-wobble-1,ios-wobble-2,ios-wobble-3) to all landmarks. - In Organize Mode: dragging translates landmark across screen smoothly; canvas pointer events are intercepted to suppress 3D voxel rotation.
- In Placed Mode: dragging directly rotates 3D voxel model in place without moving icon on screen; taps activate modals and navigation.
- Extracted domain state to
spotState.ts(isOrganizeMode,activeOrganizeSpotId,snapMode,snapCoordinate,enableOrganizeMode,disableOrganizeMode,cycleSnapMode). - Added floating retro Organize HUD with Done button and Snap toggle (
Drop,Live,Off). - Implemented configurable grid snapping defaulting to Snap on Drop (2% grid increments, ~6 to 8px).
- Implemented
useDraggableSpot.tscomposable:- Freeform dragging with pointer capture and coordinate clamping (5% to 95%).
- Multi-touch pinch-to-scale calculation (0.5x to 2.0x) via pointer distance ratio.
- Desktop mouse wheel zoom with transient floating percentage badge feedback.
- Double-click and double-tap shortcut to reset scale to 1.0x.
- User-scoped localStorage persistence schema (
xp:spot:${screen}:${userId}:${spotId}). - Global
xp:reset-spotsCustomEvent listener with lifecycle cleanup.
- Created
XpDraggableSpot.vueorganism wrapper:- Capture-phase click interceptor preventing route navigation or modal triggers during drags or pinches.
- Dynamic isometric depth sorting (
z-index: Math.round(y)). - Drag elevation (
z-index: 300, lift scale 1.08, deep drop shadow). - Registered globally in
main.tsasxp-draggable-spot.
- Integrated across all game plaza and world scenes:
-
WorldMap.vueandWorldMap.ts: Replaced local drag divs with<xp-draggable-spot>and wired "Reset Map" action totriggerSpotsReset. -
HomeTown.vueand_HomeTown.scss: Converted plaza to relative container, wrapped all 7 landmarks and old house. -
MyHome.vueand_MyHome.scss: Converted plaza to relative container, wrapped all 6 home fixtures. - 9 World Regional Scenes: Wrapped all landmarks in
WorldPlains,WorldForest,WorldIslands,WorldSwamps,WorldMountains,WorldDesert,WorldClouds,WorldIce, andWorldMoon.
-
- Testing and verification:
- Added unit test suite
tests/unit/DraggableSpot.spec.ts(16 of 16 tests passing). - Verified
tests/unit/WorldMapDraggable.spec.ts(10 of 10 tests passing). - Total 26 of 26 tests passing.
- Verified Chemical X compliance: 100% Crystalline, 0 hazards across all modified files.
- Added unit test suite
- Mobile Touch & Drag Responsiveness Fixes:
- Removed teleported
.xp-organize-backdropwhich blocked pointer hit-testing atz-index: 9990. - Added window pointerdown listener in
spotState.tsdismissing organize mode on taps outside spots and toolbar. - Added
isOrganizeModecheck tosharedLandmarkRenderer.tspointer events to prevent 3D rotation from capturing events during organize mode. - Applied
touch-action: none !important;,-webkit-user-select: none;, and-webkit-touch-callout: none;across all draggable spots and children. - Bound pointer tracking to
windowduring active touches inuseDraggableSpot.tswith immediate drag engagement on touch down during organize mode.
- Removed teleported
- Platform UI Sound Migration:
- Replaced RPG fallback sounds (
equip) with native platform UI sounds fromuiSounds(nintendo/sony):- Enter organize mode:
openTask(nintendo.News/sony.NavigationEnter). - Exit organize mode / reset:
closeTask(nintendo.Home/sony.NavigationBack). - Landmark drop / placement:
click(nintendo.Klick/sony.Navigation). - Snap cycling & scale reset:
select(nintendo.Select/sony.Navigation).
- Enter organize mode:
- Replaced RPG fallback sounds (
What was done:
- Fixed counterintuitive refusal where Potions and Ethers in the backpack displayed "Can't use that in a fight":
- Root Cause: In
BattleItems.ts, only combat relics (BATTLE_ITEMS) and containers (CONTAINERS: Bottles, Book of Spells) were recognized. Individual potions like "Health Potion", "Mana Potion", "Ether", "Elixir" were unmapped, defaulting torole: 'none'and returning refusal reason"Can't use that in a fight.". - Solutions implemented:
-
BattlePotions.ts:- Added
findPotionRule(name)supporting case-insensitive and normalized name matching. - Expanded
POTIONSregistry withHi-Potion,X-Potion, andMega Potion. - Exported
potionReason(rule, userId)to evaluate live eligibility based on current HP/MP and caps. - Updated
drinkPotion(userId, entryId)to match either byidor name, and spend item safely usingcard.id.
- Added
-
BattleItems.ts:- Added
'potion'toBattleBagRole. - Updated
battleBagRole(item)to recognize items matchingfindPotionRule(name). - Updated
describeBattleItem(item, ctx): Potions display their healing effect (e.g. "Restores 50 HP", "Restores 50 MP"), 0 MP cost, and dynamic refusal reasons (e.g. "Your HP is full.", "Your MP is full.", "You are already at full strength."). - Updated
useBattleItem(item, ctx): Potions execute directly viadrinkPotion(ctx.userId, item.id || name), restoring HP/MP, playing heal audio, spending 1 item from inventory, and preserving the hero's turn.
- Added
-
- Root Cause: In
- Test coverage & verification:
- Added unit test in
src/app/Console/MyPortal/UserHud/MyInventory/__tests__/XpInventoryModal.spec.tsverifying Health Potion and Ether battle cards and direct consumption (5 of 5 tests passing). - Verified
tests/unit/BattleItems.spec.tspasses (26 of 26 tests passing). - Verified
tests/unit/BattlePotions.spec.tspasses (24 of 24 tests passing). - Verified
src/app/Console/BattleField/__tests__/BattleField.spec.tspasses (14 of 14 tests passing).
- Added unit test in
What was done:
- Unified the backpack Goods experience across the My Goods page and the battle arena:
- Created
XpInventorySheet.vue(src/app/Console/MyPortal/UserHud/MyInventory/XpInventorySheet.vue) as an Organism:- 5 category tabs: All, Potions, Keys, Materials, Tools.
- Category icons and tab counts directly from
groupInventory(entries). - Merges items from
inventoryOf(user)andprops.equipmentfor seamless combat and general bag access. - Displays item icon, name, description / battle effect, and quantity badge (
x{qty}). - In battle mode (
mode="battle"): evaluatesbattleCard(item)to render MP costs, battle effect lines, disabled states, and "Use" triggers. - Strictly compliant with atomic design hierarchy (no raw DOM HTML elements).
- Created
XpInventoryModal.vue(src/app/Console/MyPortal/UserHud/MyInventory/XpInventoryModal.vue):- Reusable
<ion-modal>organism with<xp-close-button>, red toolbar, backpack icon, and "My Goods" title.
- Reusable
- Refactored
MyInventory.vueandMyInventory.ts:- Delegated segment tabs and list rendering directly to
<xp-inventory-sheet :user-id="userId" mode="view" />, eliminating duplicated code.
- Delegated segment tabs and list rendering directly to
- Replaced
<XpEquipmentModal>with<XpInventoryModal>inBattleField.vueandBattleField.ts:- Replaced the dumbbell equipment modal in combat with the authentic backpack Goods modal.
- Created
- Test coverage & verification:
- Created unit test suite
src/app/Console/MyPortal/UserHud/MyInventory/__tests__/XpInventoryModal.spec.ts(4 of 4 tests passing). - Verified full
BattleField.spec.tssuite passes (14 of 14 tests passing). - Verified full
XpBattleRadialMenu.spec.tssuite passes (7 of 7 tests passing).
- Created unit test suite
What was done:
- Mounted live 3D voxel hero (
XpHeroModel.vue) inside center circular button ofXpBattleRadialMenu.vue:- Added props
heroLook?: HeroLookandanimation?: HeroAnimation(defaults to"idle"). - Conditionally renders
<xp-hero-model>whenheroLookis provided, with fallback to avatar image or shield icon. - Clipped inside 68px gold-bordered circular button with smooth overflow clipping.
- Added props
- Wired reactive combat animation states in
BattleField.tsandBattleField.vue:- Computed
heroLook = computed(() => hero.value?.look). - Computed
heroAnimationwith reactive states:-
"idle": Default stance while choosing battle actions. -
"hurt": Triggers on enemy strike (feedback.hitSignal) for 600ms. -
"walk": Triggers during attack execution (finishCombatTask). -
"victory": Triggers upon winning the battle (victoryCard).
-
- Computed
- Test coverage & verification:
- Updated
src/app/Console/BattleField/__tests__/XpBattleRadialMenu.spec.ts(7 of 7 tests passing). - Verified full
BattleField.spec.tssuite passes (14 of 14 tests passing).
- Updated
What was done:
- Implemented
XpBattleRadialMenu.vue(src/app/Console/BattleField/components/XpBattleRadialMenu.vue) as an Organism:- 5-node tactile radial cluster:
- Top: Tackle / Attack (
ion-button color="success") with class weapon icon. - Start (Left): Powers (
ion-button color="tertiary") and Defend (ion-button color="warning"). - End (Right): Goods (
ion-button color="danger") and Run Away (ion-button color="dark"). - Center: Circular Hero Avatar button with gold border, pulsing on active turn and acting as Attack shortcut on tap.
- Top: Tackle / Attack (
- Run confirmation mode: Dynamically switches to "Keep fighting" (cancel) and "Run" (confirm).
- Contextual combat prompt: Displays
menuPrompt("Do its chores to win!", "Run away?") above the radial cluster.
- 5-node tactile radial cluster:
- Integrated into
BattleField.vueandBattleField.ts:- Conditioned on
gameStore.fabStyle:-
fabStyle === 'modern': Displays<XpBattleRadialMenu>whenshowMenuis active. -
fabStyle === 'retro': Preserves classicXpRpgMenuinsideBattleDialogBox.
-
- Computed reactive properties
isModern,isRetro, andheroAvatarviaappConfig.$getUserAvatar.
- Conditioned on
- Test coverage & verification:
- Created unit test suite in
src/app/Console/BattleField/__tests__/XpBattleRadialMenu.spec.ts(6 of 6 tests passing). - Verified full
BattleField.spec.tssuite passes (14 of 14 tests passing).
- Created unit test suite in
What was done:
- Fixed uncaught runtime error overlay on
/xp-intro:-
src/views/XpIntro/XpIntro.vue: Replaced raw.options.play()inbeforeMount()withplay$fx("options"), which checks user interaction permissions and catches rejections safely. -
src/components/organisms/IntroSplash/XpIntroSplash.vue: RoutedplaySound()throughplay$fx(sound)and guarded direct audio playback promises with.catch(...). -
src/app/App.ts: Guardedthis.bgm.audio.play()inplayAudio()with a.catch(...)handler. -
src/main.ts: Added globalunhandledrejectionhandler to suppress browser autoplayNotAllowedErrorrejections from popping webpack-dev-server overlays. -
src/main.ts: Expanded user interaction listeners to includekeydownandtouchstartalongsideclick.
-
- Verification:
- Verified
tests/unit/AudioSilentStart.spec.tspasses (5/5).
- Verified
What was done:
- Fixed audio playback during silent start in
XpAudioPermissionModal:-
continueSilentlycancels pending route music delays viacancelPendingRouteMusic(). - Immediately stops all active and loaded music tracks with
audioEngine.stopAllMusic(0). - Disables BGM in
useAudioStore(audioStore.bgm.is_on = false) and pauses store audio. - Clears
pendingMusicIdand setsaudioPermissionGranted = true.
-
- Hardened
AudioEngineagainst playing audio while muted:-
playMusicshort-circuits and prevents track playback ifthis.state.mutedis true. - Added cancellation handle
_musicFadeAnimationIdto cancel running fade-in animations on mute, stop, and stop-all. - Guarded
fadeInanimation steps to stop immediately if engine is muted or track is paused. -
stopAllMusicwith zero fade time forcefully pauses and zeroes volume for all registered tracks. -
mute()cancels pending fade animations and zeroes volume across all music tracks in cache. - Guarded
initializeAudioContextagainst missingAudioContextconstructor in non-browser environments.
-
- Hardened
routeMusic:- Exported
cancelPendingRouteMusic()to abort stale delayed starts. -
playRouteMusichalts and stops music immediately whenengine.state.mutedis true. - Delayed route start checks both
audioStore.bgm.is_onand!engine.state.muted.
- Exported
- Updated
App.ts:-
clickSoundusesplay$fx('select')instead of directly triggering raw audio elements.
-
- Added test coverage:
-
tests/unit/AudioSilentStart.spec.tsverifies silent start, muted play prevention, and store synchronization.
-
Decisions resolved (Tasks #1103 to #1112):
-
Sequential Unlocks (Task #1104, Q5):
- Sequence: Bed Basilisk ambush (XP) -> Gold Bank account creation (GP) -> First real chore quest (Profile tab) -> Larger wallet upgrade (Shop) -> Damage taken (Hospital HP / Hotel MP) -> Pegasus egg quest & flight (Overworld unlocks, prologue completes).
-
Guide Persona (Task #1105, Q6):
- Town Crier acts as single overarching narrative guide, with individual hub NPCs (Bank Manager, Shopkeeper, Nurse) teaching local mechanics.
-
Parent Experience (Task #1106, Q7):
- Parent plays the identical ambush-first prologue as a hero, augmented by contextual coaching lines across the Game Master console.
-
Existing Heroes (Task #1107, Q8):
- All existing heroes start fresh on the prologue upon next launch.
-
Ambush Battle Mechanics (Task #1108, Q9):
- Standard battle rules apply to the Bed Basilisk ambush; defeat routes the hero to the Hospital, teaching HP and healing mechanics early.
-
Device Support Target (Task #1109, Q10):
- Includes "Join a family" in v1 to import a parent backup file via QR code or file share on separate child devices.
-
Parent Chore Pool (Task #1110, Q11):
- Parents select chores from existing age bands, supplemented by chores assigned directly to them or household maintenance tasks.
-
Wizard Entry Point (Task #1111, Q12):
- "Start a new family" and "Restore a backup" buttons mounted on the Press Start screen; intro slideshow acts as page 1 of the setup wizard.
-
Unlock Pacing (Task #1112, Q13):
- Pure progress gating with zero artificial delays; features unlock immediately upon clearing prerequisite tasks and story beats.
-
Coordination Status:
- Recorded all answers on board tasks #1104 through #1112; notified @fable via DM #1339 to begin authoring the technical specification.
What was done:
- Battle Transition Sound Before Animation:
- Added
sound: "enterBattle"to{ effect: "swirl", direction: "in" }insceneTransitions.ts. - Added an 800 ms pause before
cover(plan)intransition.guard.tsfor swirl transitions when reduced motion is disabled, allowing the encounter sting to ring out before the swirl covers the screen. - Registered
enterBattleandstartBattlesound effect bindings acrosschronoTriggerandfinalFantasyRPG themes insrc/assets/fx/index.ts.
- Added
- Battle Music Trigger Directly After Intro Animation:
- Removed decoupled
BATTLE_BGM_ROUTEShandling anduseBattleStoredependency frombgm.guard.ts, eliminating the arbitrary 4.2-second wait timeout. - Updated
BattleField.tsstartIntrocallback to triggeraudio.startBossBgm()for bosses andaudio.startBattleBgm()for standard encounters right when the enemy arrives on stage. - Removed duplicate
audio.startBossBgm()call frombeginBattle.
- Removed decoupled
- Test Verification:
- Updated
tests/unit/sceneTransitions.spec.tsassertingsound: "enterBattle"on the battle swirl transition plan. - Added unit test in
tests/unit/BattleAudio.spec.tsassertingstartBattleBgm()immediately dispatches thebattleBGM slot.
- Updated
What was done:
- Realigned World Map plaza layout from 4 rows to a 3x3 grid aligning directly with
world-map.webpillustration landmarks:- Top row (North): Islands, Mountains, Clouds shifted upward (padding-top reduced,
margin-top: autoremoved) to land directly over their background art features. - Middle row (Equator): Forests, Plains (centered between Forests and Tundras), and Tundras. Removed empty center clearing.
- Bottom row (South): Swamps, Sands, and The Moon (Stars).
- Top row (North): Islands, Mountains, Clouds shifted upward (padding-top reduced,
- Updated
WorldMap.vueand_WorldMap.scssto use uniform 100px sizing andjustify-content: space-betweenacross both axes. - Lifted middle and bottom rows higher: increased bottom padding to 180px and added equator bottom margin to place middle row directly over the forest and canyon trail, and bottom row directly over the swamp, dunes, and galaxy stars.
What was done:
- Replaced cluttered shop layout in
AccessoryShop.vuewith an authentic retro-modern RPG shopfront matching Earthbound and glassmorphism standards. - Created
ShopClerkStage.vue(src/app/Console/MyPortal/HomeTown/AccessoryShop/components/ShopClerkStage.vue):- Dedicated upper scenic viewport (250px) framing authentic pixel art shopkeeper background (
wrecked-ship.webp,pegasus-ranch.webp, etc.) without obscuring cards. - Earthbound-style dialog window with clerk nameplate, greeting, charisma discount badge, and closed sign.
- Dedicated upper scenic viewport (250px) framing authentic pixel art shopkeeper background (
- Created
ShopWalletWare.vue(src/app/Console/MyPortal/HomeTown/AccessoryShop/components/ShopWalletWare.vue):- Featured wallet capacity upgrade card positioned at the top of the shelf with gold accents, live status cues, and instant upgrade modal prompt.
- Created
ShopItemCard.vue(src/app/Console/MyPortal/HomeTown/AccessoryShop/components/ShopItemCard.vue):- 2-column responsive grid card with glassmorphism backdrop, centered item photo/icon, clean
Apple Kidtypography, and embedded price tag (with shortfall indicator when out of budget). - Eliminated broken
margin: 2em,border-radius: 0 0 65px 65px, and overflow-20pxbadge positioning.
- 2-column responsive grid card with glassmorphism backdrop, centered item photo/icon, clean
- Created
ShopItemModal.vue(src/app/Console/MyPortal/HomeTown/AccessoryShop/components/ShopItemModal.vue):- Single reusable inspection and purchase modal with item artwork, description, 3-column wallet economics breakdown, and tactile Buy/Cancel actions.
- Header and Controls Refactor:
- Added interactive Gold/Purse HUD pill to header toolbar with coin icon and wallet amount routing to ATM.
- Eliminated 110px footer toolbar in favor of compact shelf filter chips ("All Items", "Can Afford", "Can't Afford") and inline search.
- Increased
ITEMS_PER_PAGEfrom 4 to 8. - Mapped missing
pond-of-life.webpbackground.
- Verification:
- Added unit test suite in
tests/unit/AccessoryShopComponents.spec.ts(10 of 10 tests passing). - Verified
tests/unit/shopHours.spec.tsandtests/unit/PurchaseService.spec.tspassing (64 of 64 tests). - Full TypeScript typecheck clean (0 errors).
- Added unit test suite in
What was done:
- Added custom 3D voxel palettes for all 9 sacred Pegasi in
src/components/organisms/BuildingModel/voxel/buildingShapes.ts, matchingPEGASUS_LOOK:- Ventus (Clouds): Silver-white coat (
#f1f2f6), storm slate mane and wings (#2f3542) - Ignis (Mountains): Crimson coat (
#ff4757), radiant gold mane and wings (#f1c40f) - Sol (Desert): Sun orange coat (
#ffa502), sunset coral mane and wings (#ff6b81) - Aura (Plains): Spring green coat (
#badc58), pure white mane and wings (#ffffff) - Terra (Forest): Emerald coat (
#2ed573), dark forest bark slate mane and wings (#2f3542) - Glacie (Ice): Crystalline cyan coat (
#00d2d3), glacier violet-blue mane and wings (#5352ed) - Aqua (Islands): Ocean cobalt coat (
#3742fa), seafoam mint mane and wings (#7bed9f) - Venenum (Swamps): Shadow purple coat (
#8e44ad), acid poison lime mane and wings (#badc58) - Umbra (Moon): Midnight navy coat (
#130f40), radiant star white mane and wings (#ffffff)
- Ventus (Clouds): Silver-white coat (
- Added locked dormant palette (
#94a3b8,#64748b,#cbd5e1,#a1a1aa) for unfreed Pegasi. - Updated
XpBuildingModel.vuewithworldprop and reactive unlock detection againstuser.stats?.pegasi:- When unlocked: displays the sacred Pegasus name (e.g., "Aura", "Ignis") and "Fly to World Map" with vibrant full-color 3D voxel model.
- When locked: displays "Travel World" with asleep cue, applies
.is-locked(45% opacity, 60% grayscale), and builds dormant voxel geometry. - Switches 3D mesh reactively via
sceneBuildingId.
- Updated all 9 world views (
WorldPlains.vue,WorldClouds.vue,WorldDesert.vue,WorldForest.vue,WorldIce.vue,WorldIslands.vue,WorldMoon.vue,WorldMountains.vue,WorldSwamps.vue) to passworld="<world>"without hardcoded label overrides. - Added comprehensive unit test suite in
tests/unit/PegasusWorldModel.spec.ts(9 of 9 tests passing). - Fixed
pegasus-ranchprefix collision inXpBuildingModel.vueandbuildingShapes.ts:-
props.buildingId.startsWith("pegasus-")was inadvertently matchingpegasus-ranch, causing the Plains ranch shop to render as a duplicate Pegasus ("Aura") and navigate to the world map instead of the shop. - Excluded
pegasus-ranchfromisPegasusinXpBuildingModel.vueandgetBuildingBoxesinbuildingShapes.ts. - Pegasus Ranch now renders its 3D barn voxel model, badge title "Pegasus Ranch", cue "Tap to shop", and routes to the shop on tap.
-
What was done:
- Fixed header identity wrapping: added
white-space: nowrapandflex-shrink: 0on.hero-levelto prevent "Lv" and level number from splitting onto two vertical lines. - Improved name truncation resilience: added
flex: 1 1 autoandmin-width: 0to.hero-name, and increased cardmax-widthto 192px to accommodate longer hero names cleanly. - Restructured
stat-labelfor HP and MP: wrapped stacked letters in individual block spans with a dedicated column flex container (width: 16px,height: 30px,font-size: 0.82rem,line-height: 0.88), replacing fragile word-wrapping and negative letter-spacing hacks. - Centered rolling odometer digits: applied
display: flex; align-items: center; justify-content: centerwithpadding-bottom: 4pxon.digittiles to offsetPixel Takhisisascender whitespace and center numbers vertically. - Verified test suite: all 36 unit tests in
src/app/Console/BattleField/__tests__/BattleHeroCard.spec.tspassing green.
What was done:
- Moved encounter and room art (
[data-cy="choice-art"]) out of the action sheet panel (.choice-reveal__panel) and into.choice-reveal__stageinsrc/app/Console/TempleGrounds/components/TempleChoiceReveal.vue. - Rendered
.choice-reveal__stagewhen eitherspriteorshowArt && artis present (hasStage). - Centered the art in the light rays and flash above the docked sheet panel, matching the chest and door reveal layout.
- Applied
choice-landbounce animation and drop shadow to the sprite. - Updated
tests/unit/TempleChoiceReveal.spec.tsto assert that art renders on the stage outside the sheet panel.
What was done:
- Fixed template branching in
src/app/Admin/XpCompendium/views/XpTemples/components/tabs/XpTempleLayout.vue: changedv-if="showMazeConfig"tov-else-if="showMazeConfig"so the grid editor does not render simultaneously with the preview modal and obscure buttons. - Hidden floating action buttons (Save, Management Shovel, Floor Switcher) during preview and maze configuration modes (
&& !showPreview && !showMazeConfig). - Added responsive styling for
.preview-containerand.code-previewwith vertical scroll constraints (max-height: 52vh) so action buttons remain visible on mobile devices. - Created
src/lib/utils/clipboard.tswithcopyTextToClipboardsupporting both standard Clipboard API anddocument.execCommand('copy')fallback for non-secure HTTP contexts. - Updated
copyToClipboardinsrc/app/Admin/XpCompendium/views/XpTemples/components/XpTempleCreator/hooks/useTempleCreator.tsto usecopyTextToClipboard. - Added unit tests in
tests/unit/clipboard.spec.tscovering secure API and non-secure fallback paths.
- Extracted 2-step footstep asset
src/assets/audio/nintendo/earthbound/step.wav(0.55s) fromsteps.wavfor room-to-room transitions. - Preserved full 4-step sequence
src/assets/audio/nintendo/earthbound/steps.wav(1.22s) for stairs transitions between floors. - Registered
step(2 steps) andsteps(4 steps) across$fxthemes insrc/assets/fx/index.tsandsrc/assets/fx/earthbound.fx.ts. - Wired
fx('step')playback on room movement inmoveWithUpdate()withinsrc/app/Console/TempleGrounds/TempleGrounds.ts. - Wired
stepssound effect to stairs climbing (climb()insrc/lib/services/temples/RoomInteractions.ts). - Updated unit test assertions in
tests/unit/RoomInteractions.spec.tscovering stairs sound outcome.
What was done:
- Updated default toast position in
src/hooks/useToast.ts(rpgToastOptionsanduseToast) frombottomtomiddle. - Verified dismiss buttons include
closeOutlinecancel action button withDismissaria-label for instant dismissal. - Updated
say()message helper insrc/app/Console/TempleGrounds/TempleGrounds.tsto display dungeon toasts atmiddleposition. - Updated toast placement documentation and comments across
src/styles/themes/earthbound.scssandCLAUDE.md. - Updated unit test assertions in
tests/unit/useToast.spec.tscovering center default positioning and dismiss button presence.
What was done:
- Converted 292 images across temple rooms, shops, and battleback backgrounds to WebP (quality 85, method 6) and removed original JPG/PNG files:
- 5 shop background PNGs in
src/assets/images/backgrounds/shops/(15.28 MB -> 1.81 MB, 88.14% reduction) - 277 temple room background JPGs across
wind-temple/,light-temple/,ice-temple/,water-temple/,earth-temple/,fire-temple/, andshadow-temple/(39.94 MB -> 21.52 MB, 46.14% reduction) - 10 battleback background PNGs
src/assets/images/backgrounds/battleback*.png(5.80 MB -> 369.59 KB, 93.63% reduction)
- 5 shop background PNGs in
- Total weight reduced from 61,029,875 bytes (58.20 MB) down to 23,698,178 bytes (22.60 MB), saving 37,331,697 bytes (35.60 MB, 61.17% overall reduction).
- Updated code references:
-
src/app/Console/TempleGrounds/TempleGrounds.ts(updatedgetBgImageandcurrentBgImagerequire statements from.jpgto.webp) -
src/app/Console/MyPortal/HomeTown/AccessoryShop/AccessoryShop.ts(updatedshopBackgroundsrequire paths from.pngto.webp) -
vue.config.js(verified IgnorePlugin regex compatibility with WebP backgrounds and updated comment) -
src/views/XpDemo/XpDemo.vue(updated commented wind temple image path to.webp)
-
What was done:
- Converted 93 monster battle sprite PNG images in
src/assets/images/beasts/(001.pngthrough093.png) to WebP (quality 85, method 6, transparency preserved) and removed original PNG files. - Reduced beast sprites weight from 8,988,589 bytes down to 2,158,374 bytes (75.99% size reduction, saving 6,830,215 bytes / 6.51 MB).
- Updated code references:
-
src/lib/services/battle/BestiaryService.ts(getAvatar()returns.webp) -
src/components/molecules/AvatarSelect/AvatarSelect.vue(getAvatarImage()returns.webp) -
src/app/Admin/XpCompendium/views/XpAchievements/XpAchievements.ts(getBeastAvatar()returns.webp) -
src/app/Admin/XpCompendium/views/XpAchievements/XpConfigAchievement/components/XpAchievementItem.vue(beastAvatarUrl()returns.webp) -
src/app/Admin/XpCompendium/views/XpAchievements/XpConfigAchievement/hooks/useAchievementForm.ts(beastAvatarUrlreturns.webp) -
src/app/Admin/XpCompendium/views/XpBestiary/XpBestiary.vue(getAvatar()returns.webp) -
src/app/Admin/XpCompendium/views/XpBestiary/components/XpAddBeast.vue(getAvatar()returns.webp) -
src/app/Admin/XpCompendium/views/XpBestiary/components/XpBeastSelectorItem.vue(avatarUrlreturns.webp) -
tests/unit/TempleChoiceReveal.spec.ts(test beast art fixtures updated to.webp)
-
- Unit tests verified clean:
TempleChoiceReveal.spec.tsandBestiaryService.spec.tspassing (23/23 tests).
What was done:
- Converted 12 full-screen background JPG images in
src/assets/images/backgrounds/to WebP (quality 85, method 6) and removed original JPG files:-
world-mountains.jpg->world-mountains.webp -
world-map.jpg->world-map.webp -
world-ice.jpg->world-ice.webp -
hometown.jpg->hometown.webp -
world-plains.jpg->world-plains.webp -
world-moon.jpg->world-moon.webp -
world-swamps.jpg->world-swamps.webp -
world-islands.jpg->world-islands.webp -
world-desert.jpg->world-desert.webp -
world-forest.jpg->world-forest.webp -
world-clouds.jpg->world-clouds.webp -
my-home.jpg->my-home.webp
-
- Reduced background asset weight from 34,019,040 bytes down to 3,527,872 bytes (89.63% size reduction, saving 30.49 MB).
- Updated code references across
worldRegistry.ts,XpDemo.vue,JobClassSelector.vue,AccessoryShop.ts,_MyHome.scss,_WorldMap.scss, and all individual world SCSS stylesheets.
What was done:
- Converted 21 full-resolution PNG images across
src/assets/images/about/andsrc/assets/images/midjourney/to WebP (quality 85). - Reduced folder weight from 53.36 MB down to 5.03 MB (90.6% size reduction, saving 48.33 MB).
- Updated code references across
XpIntro.vue,LogIn.scss,XpGameOver.vue,IntroSplashDemo.vue,AccessoryShop.ts, and town hub SCSS (GoldBank,HospitalHub,HotelHub).
What was done:
- Removed unreferenced
public/samples/wind-temple-0-0.png(31.4 MiB) exceeding Cloudflare's 25 MiB file size cap. - Created canonical production deployment on Cloudflare Pages project
do-it-for-the-xpwith branchmaster. - Verified live HTTP 200 response and app rendering on root URL
https://do-it-for-the-xp.pages.dev. - Attached custom domains
app.forthexp.comandapp.doit.forthexp.comto the live Pages project.
What was done:
-
Voxel Sizing & Camera Framing:
- Centered Y coordinates in
src/lib/engine/voxel/spriteToVoxel.tsaroundy = 0and reduced extrusion depth to1.6for crisp 3D pixel relief without bulky square silhouettes. - Adjusted camera distance to 64 and target Y to 0 in
src/components/organisms/MonsterModel/XpMonsterModel.vue, eliminating viewport clipping so full creature forms fit with balanced padding.
- Centered Y coordinates in
-
NPC Movement & Directional Facing:
- Eliminated continuous 360-degree spinning (
spinSpeed: 0). - Added directional yaw tracking in
src/components/organisms/MonsterModel/useMonsterRoam.ts: monsters face their heading when walking (+0.6 rad right, -0.6 rad left) and turn forward (0 rad) upon arrival or hover. - Added NPC walking hop (
is-moving) and gentle breathing idle (is-idle) CSS animations.
- Eliminated continuous 360-degree spinning (
-
Under-Enemy Nameplates & Authentic Monster Naming:
- Moved
XpLandmarkBadgebeneath the creature canvas and shadow (.name-under). - Eliminated generic "Temple Guardian" fallback in
src/app/Console/TempleGrounds/TempleGrounds.ts. - Added
resolveMonsterInfoto extract authored monster names (titleWords(monsterType)) and element-specific names (e.g. Fire Elemental, Stone Guardian, Ice Wyrm, Dark Phantom, Radiant Guardian) with matching bestiary avatars for both the roaming voxel and combat choice reveal.
- Moved
-
Room Lifecycle Keying & Actual Beast Data:
- Bound
:key="monster-${currentLevel}-${currentPosition[0]}-${currentPosition[1]}"onxp-monster-modelinTempleGrounds.vueso moving rooms cleanly disposes the previous room's WebGL client and spawns the new room's monster. - Updated
TempleGrounds.tsto queryBestiaryDbfor the actual beast record, supporting customimageUrlandlocalImageassets rather than only avatar numbers.
- Bound
What was done:
-
Voxel Sprite Decoding & Test Resilience:
- Added timeout fallback guard to
sampleImagePixelsinsrc/lib/engine/voxel/spriteToVoxel.tsto prevent unhandled promise hangs during headless/SSR execution. - Updated
tests/unit/spriteToVoxel.spec.tswith mock image decode failure handling.
- Added timeout fallback guard to
-
Router Guard Optional Chaining:
- Added optional chaining to
router.beforeResolve,router.afterEach, androuter.onErrorinsrc/router/_Guards/transition.guard.tsso lightweight mock router instances in unit tests run cleanly without stub errors.
- Added optional chaining to
-
Jest Worktree Isolation:
- Configured
testPathIgnorePatternsandmodulePathIgnorePatternsinjest.config.jsonto ignore<rootDir>/.claude/, preventing stale worktree spec pollution.
- Configured
-
Chemx Verification:
-
chemx typecheck: Clean (0 errors). -
chemx test: 1,863 passed, 0 failed. - Production build (
npm run vue-build): Complete.
-
What was done:
- Added
ion-menu-buttonin the#start-actionsslot ofXpRpgPagewithinXpCompendiumDashboard.vue. - Wired audio feedback with
play$fx('select')on menu button press, matchingXpDashboard.vue. - Exposed
play$fxdirectly fromsetup()inXpCompendiumDashboard.vue.
What was done:
- Updated
withoutEmptyTimesgeneric constraint intimesOfDayEditor.tsfrom{ timesOfDay?: readonly string[] }toRecord<string, any>. - Resolved TS2353 excess property error when passing objects without
timesOfDayin unit tests and consumers.
What was done:
- Configured Cloudflare Pages SPA redirection via
public/_redirects(/* -> /index.html 200). - Configured immutable asset caching headers via
public/_headersfor CSS, JS, fonts, media, and images. - Created and deployed project
do-it-for-the-xpdirectly using Wrangler CLI to Cloudflare Pages. - Production deployment live at
https://main.do-it-for-the-xp.pages.devandhttps://do-it-for-the-xp.pages.dev.
What was done:
-
2D Sprite to 3D Voxel Engine:
- Created
spriteToVoxel.ts(src/lib/engine/voxel/spriteToVoxel.ts) to sample transparent monster PNG sprites (001.pngto093.png) into extruded 3D voxelBox[]definitions with run-length consolidation and depth. - Culled hidden faces via
buildMeshDataand cached generated meshes in-memory by sprite source URL. - Added procedural fallback voxel mesh for instant display and headless resilience.
- Created
-
Voxel Monster Organism:
- Created
XpMonsterModel.vue(src/components/organisms/MonsterModel/XpMonsterModel.vue) usingsharedLandmarkRendererto share the single WebGL context without GPU overhead. - Added continuous 360-degree 3D voxel rotation (
spinSpeed: 0.9), exposingsetSpinSpeedandsetYawonLandmarkHandle. - Added
useMonsterRoam.tsto manage wandering waypoints, walking hop bobbing, and hover pause without 2D scale flipping during 3D rotation. - Rendered authentic mixed-case Earthbound floating title badges (
Apple Kid) above the monster.
- Created
-
Temple Grounds Encounter Integration:
- In
TempleGrounds.vueandTempleGrounds.ts, mounted<xp-monster-model>in uncleared combat rooms (monster,miniboss,boss). - Resolved active monster avatar dynamically via
BestiaryServicewith fallback to074.png(Dustbunny). - Hid static center action FAB in active combat rooms; tapping the 3D roaming monster directly launches the room battle action sheet.
- In
-
Unit Testing:
- Added
tests/unit/spriteToVoxel.spec.tsasserting RGBA buffer parsing, box consolidation, depth extrusion, and placeholder fallbacks.
- Added
What was done:
-
Home Background Aspect Ratio & Bottom Nav Shelf Alignment:
- Regenerated
src/assets/images/backgrounds/my-home.jpgat9:16portrait aspect ratio (768x1376) to replace legacy2:3(1024x1536) asset. - Eliminated horizontal cropping on mobile viewports.
- Removed baked-in 2D furniture (bed, table, chairs, barrels, chest), providing clean floor space for interactive 3D voxel models without visual duplication or overlap.
- Restored and repositioned the decorative horizontal shelf beam and diamond tapestry runner to sit cleanly at the bottom dock zone (bottom 11% of the viewport).
- Eliminated the doubled lower beam and dark panel beneath the tapestry so the bottom nav bar and XP/GP purse bar sit directly on a dedicated textured background.
- Preserved authentic 16-bit SNES pixel art style, glowing fireplace hearth, warm candle lighting, wood paneling, and center rugs.
- Regenerated
What was done:
-
Full-Bleed Viewport Background:
- Positioned
.portal-dockabsolutely at the bottom edge inMyPortal.vueand_MyPortal.scss, allowingion-router-outletand pageion-contentto span 100% of the viewport height. - Page backgrounds (
my-home.webp,hometown-ground.png,world-map.webp) extend completely behind the bottom nav bar and purse bar. - Added frosted glass blur (
backdrop-filter: blur(16px)) and semi-translucent tint toXpBottomNav.vueso the underlying room textures diffuse through the nav.
- Positioned
-
Plaza Layout Alignment:
- Adjusted
.my-home-plazapadding in_MyHome.scssto prevent double bottom padding, keeping all voxels aligned with the room rugs without vertical scrollbars.
- Adjusted
What was done:
-
Typography Overhaul:
- Replaced all-caps gothic font
Pixel TakhisisinXpLandmarkBadge.vuewith authentic Earthbound fontApple Kid(font-family: "Apple Kid", "StatusPlz", sans-serif). - Restored clean mixed-case readability for landmark titles across all worlds and Hometown (e.g., "The Plains", "Hero's Home", "Gold Bank").
- Preserved arcade-style high-contrast gold fill (
#ffd700) with 4-sided black drop outline and tunedfont-weight: normalwithletter-spacing: 0.6px.
- Replaced all-caps gothic font
-
Unit Test Updates:
- Updated
landmarkBadge.spec.tsto assert mixed-case title rendering and uncluttered single-line badge contract.
- Updated
What was done:
-
UI FX Mapping:
- Mapped
clickandklickinsrc/assets/fx/index.tsfor Nintendo (nintendo.Klick), Sony (sony.Navigation), Earthbound (earthbound.click), Chrono Trigger, and Final Fantasy (chronoTrigger.cursor). - Registered
clickinsrc/lib/engine/audio/soundRegistry.ts(nintendo_clickviaKlick.wav,sony_clickviaNavigation.mp3). - Added
playClickSoundconvenience helper insrc/hooks/useAudio.ts.
- Mapped
-
Passcode DialPad Integration:
- Wired
play$fx("click")on digit presses (appendToCode), backspace (removeLastDigit), clear (clearCode), and toggle show/hide passcode (toggleShowPass) insrc/app/SideMenu/SwitchProfile/DialPad.vue. - Added
play$fx("yes")on passcode match,play$fx("no")on passcode mismatch, andplay$fx("select")on dismiss. - Safe-guarded controller calls (
toastController,alertController,modalController) against null/undefined in test/offline environments.
- Wired
-
Verification: Created
tests/unit/DialPadSound.spec.tscovering registry mappings,$fx.uimappings, and all DialPad audio triggers; all 9 tests passing green.
What was done:
-
Authentic Earthbound Sprite Extraction: Sliced pixel-perfect
smash.png(82x28) andyou_won.png(69x8) with transparent backgrounds from original sprite sheet intosrc/assets/images/battle/. -
Battle Damage & Smash Overhaul:
- Replaced text smash popup in
BattleEnemyStage.vuewith authentic animated EarthboundSMAAAASH!!pixel art sprite while preserving screen-reader and DOM text contracts. - Increased floating damage numbers from 1.8rem to 3.2rem using
Pixel Takhisiswith high-contrast outlines for instant readability. - Enlarged chore counter label (1.2rem) and attack countdown labels (0.95rem / 1.55rem).
- Replaced text smash popup in
-
Victory Announcement Banner:
- Rendered authentic
YOU WON !Earthbound pixel banner inBattleVictoryCard.vuewith 4x crisp pixel scaling and purple drop shadow. - Updated battle outcome resolver in
useBattleOutcome.tsto announce "YOU WON!" across all battle victories. - Bumped victory subtitle, quest, and work line font sizes.
- Rendered authentic
-
Battle Dialog Typography: Increased
BattleDialogBoxtext from 1.2rem to 1.55rem (Apple Kid/StatusPlz) and prompt to 1.15rem in_BattleField.scssso damage taken and action text are clearly readable. -
Verification: Ran all 5 BattleField test suites (
BattleEnemyStage,BattleVictoryCard,BattleHeroCard,BattleField,XpBattleTaskMenu); all 134 tests passed.
What was done:
-
Font extraction & installation: Unzipped
pixel_takhisis.zipin Downloads and installedpixel-takhisis.otfintosrc/assets/fonts/earthbound/. -
Global font-face declaration: Added
@font-facedefinition for"Pixel Takhisis"insrc/styles/_fonts.scss. -
Battle odometer ticker integration: Applied
"Pixel Takhisis"font family to.digitinBattleHeroCard.vuefor rolling HP and MP ticker tiles. -
Verification: Ran
BattleHeroCard.spec.tstest suite; 36 of 36 unit tests passing.
What was done:
-
Reactive Area Compass Tracking: Resolved issue where the main area tab failed to update on route changes. Replaced stale Options API reassignment with a computed
compassinMyPortal.tsthat reactively resolves area name, icon, and link from active route name and route path. -
Route Name Registration: Added
name: "my-party"tomy-portal.routes.tsso route resolution handles party navigation consistently. -
Dynamic Active Tab State: Wired
:active="activeNavTab"fromMyPortal.tsandMyPortal.vuetoXpBottomNav.vue(profile,area,party), highlighting the active location or opened modal. -
MMO Hotbar Aesthetic: Redesigned
XpBottomNav.vuewith translucent glassmorphic styling (backdrop-filter: blur(16px)), metallic top border accents, tactile hotbar slot frames, and glowing active states. Removed harsh dashed borders and black blocks. -
Translucent Dock Ledges: Updated
.tab-docked-xp--ledgeand.footer-docked-xpto matching translucent glass backgrounds so page backgrounds remain visible behind the navigation dock.
What was done:
-
Dead vendored assets purged: Removed 18 unused FontAwesome JS files in
src/assets/fonts/font-awesome/js/(~23,000 lines, 20 MB). Icons continue loading cleanly viaall.csswebfonts. Reduced critical hazards from 65 to 55; token burn dropped from 4.18M to 1.03M ($117/mo); health grade upgraded to 90 (Grade A). -
Leaked markdown artifact: Removed backtick fence from line 1 of
XpTempleCreatorGrid.vue. -
Render hack eliminated: Replaced
setTimeout(..., 0)withnextTickinXpIntroSplash.vue. -
Timer handle discipline: Added explicit lifecycle tracking and teardown for
progressTimerinXpMusicPlayer.vue. -
BattleField test suite green: Corrected Defend damage expectation in
BattleField.spec.tsfor Warrior job class (braceFactor: 0.25yields 1 damage, leaving 29 HP). All 62 test suites and 1,379 tests passing green. -
WordPress API direction:
doit.forthexp.comclient endpoints preserved for future backend restoration. - Verification gate: Typecheck 0 errors, jest 1,379 passing, ChemX critical hazards down to 52.
Where v1 stands. The hero loop (see quests → claim or fight → rewards persist → GM approval → shop) was wired yesterday and verified only in jsdom. Today the battle screen was rendered in Chrome for the first time (Cypress 8.7 headless, 390×844), which exposed a dead arena background after any resize, a one-tap-skips-everything dialog, a 277 px HUD that clipped, soft-locks after Defend/Run, invalid sound keys and a 1-minute clock no real chore can beat. All fixed.
How it was done. Two critique agents (kid-UX, engineering craft) and two bug finders (each finding verified by a skeptic) reviewed the old screen and the design contract; the contract became docs/Battle-Field-Contract-v2.md. Five Sonnet builders took board tasks #25–#29 on disjoint files (stage, checklist sheet, hero card, engine + unit tests, victory card); Fable owned the page wiring, outcome flow, dialog, feedback, docs and tests. See docs/Battle-Field-Architecture.md for the result.
Rules that changed (owner, please confirm): strike ≈ 12% of max HP (was 6–19 flat); clock = 3 minutes per remaining chore via Enemy.attackCooldown (was 1); Defend = glancing hit now + fresh clock (was a free brace that double-struck); Run Away confirms first; free fights pay AP only; quests with "requires approval" are held as pending from the arena too; every fight ends at full HP (the hospital heal is still a stub).
Verification gate: typecheck 0, lint 0 errors, jest green (5 new battle specs: stage 49, hero card, checklist, victory card, engine 51, page 4), Cypress battle walk-through renders every phase at 390×844 (screenshots under tests/e2e/screenshots/battle.spec.js/, ignored by git). Hands-on: sign in, open /battle.
Open on the board: #13 (full browser walk-through of the whole loop), #19–#24 as before.
How work is organised now. The backlog lives in this project's chemx team board (chemx team task list --all); each task carries its full spec as a comment. Fable writes specs and reviews; Sonnet/Haiku agents claim (chemx team task claim <id> --as=@handle), implement, and close (done <id> --force, because the AST gate is red on this legacy code). Waves ran on disjoint file sets.
Gate at 2026-10-09 ~02:40: typecheck clean, lint 0 errors, 10 unit suites / 320 tests passing, lockfile frozen-install OK, production build green (195 MB).
Landed today (nothing seen in a browser yet at the time of writing): battle page spec (#1); temple return carries the floor, cleared rooms unlock and survive reload (#2); Game Master gating with GM-only toggle, PIN, masquerade clean-up, legacy "user 1" fallbacks removed (#3, #18); quest board shows Pending vs Tamed (#4); My Home routes carry the hero id (#5); asset diet part 1, 225 → 195 MB (#6); dev routes and Support dev tools gated to non-production (#7); lang="ts" on every external SFC script (#8, #17); docs cleanup (#9, #16); orphan sweep, 23 files (#10); random encounters every 2–4 min on Home Town / World Map (#11); shop loop: real purchases, purchase log, GM fulfil/refund (#12); temple progress persisted per hero (#14); backup/restore everything (#15). Fable: battle rebuild fix-ups (victory strobe, hero id on cleared rooms), "New Temple" route name.
Open on the board: #13 browser walk-through as a Cypress e2e suite (running), #19 encounters on region pages, #20 asset diet part 2, #21 remove the dead WordPress API, #22 GM-only restore + native file export, #23 persist chests/doors, #24 family-settings gating + PIN for legacy GM profiles.
Known limitations: battle BGM is remote (silent offline); Goods/Abilities are off the battle menu until items have effects; profile export/backups don't save files inside native shells (#22); chemx's reader is blind inside defineComponent bodies (elysium #939), so agents fall back to bounded raw reads.
Diagnosis. A 14-agent subsystem map (journal: ~/.claude/projects/-home-xopher-www-x-do-it-for-the-xp/33038804-2dfd-48ae-b87e-77d889f71ea8/subagents/workflows/wf_c5cce08c-88c/journal.jsonl) found the core loop was never wired: a hero could see quests, but Claim wrote nothing, awarded nothing, and no approval queue existed; rewards only existed inside battles, and even those Pinia stat changes were never written to ProfileDb (lost on reload). The remote WordPress API (doit.forthexp.com) is gone (404). Production build passed but was 225 MB (165 MB images via require.context("@/assets/images/")).
Done this session (uncommitted, on disk):
- Toolchain: pnpm migration gaps fixed (
@types/webpack-env,ts-jest), ambientsrc/types/shims-vue.d.ts(typecheck went 242 → 0 errors),typecheck/testscripts, chemx installed (.mcp.json,.cursor/.vscode mcp.json,chemx:*scripts,.chemx/index.db), explicit.tsextensions on 33<script src>tags (vue-jest), scaffoldexample.spec.tsremoved,isMonsterTokenacceptsM01_/M01!(hydrator test green). - Backbone:
src/lib/databases/QuestLogDb.ts(completion records),src/lib/engine/quests/QuestSchedule.ts(+11 unit tests: once/daily/weekly/custom windows),QuestEngine.getQuestBoardForUser/getOpenQuestsForUser,src/lib/services/quests/QuestCompletionService.ts(completeQuest / approveCompletion / rejectCompletion / recordBattleCompletion),userStore.persistUser()called by every stat mutator (XP/GP/HP/AP/class/pegasus/slots now persist). - Bug fixes: post-logout lockout (
requiresAuth:falseon xp-profile/xp-intro/xp-demo), stopImpersonating returns to the real GM (xp_impersonator_id),User.setNameparser (nick defaults to first name), GM Bonus/Penalty now goes through store actions (was writingstats.xp.total), four world maps pushed unregistered temple ids (now earth/storm/light/ice/shadow), Leave-Temple route names,XpTemples.vuecreator route, GM tab captions, notification/party settings links,capacitor.config.jsonno longer hardcodes a LAN dev server,window.unlockPegasusdev-only,profileStoragemoved tosrc/lib/databases/profileStorage.ts,SplashScreentype toIntroSplash/types.ts. - Delegated and finished (all typecheck/lint clean, verified in jsdom only, never opened in a browser): hero side (MyQuests board with Tamed state, real MyTask Claim with approval path and live counters, MyCalendar on the board), GM side (
/game-master/approvalsroute, real XpApprovals page with History tab, live dashboard Approvals tile), toolchain (jest now pnpm-aware with arequire.contextshim, BattleGround.spec modernised, 17/17 tests, lint 0 errors,chemx buildgreen, staleXpSettingsHome.jsdeleted).approveCompletion/rejectCompletiongot an in-flight guard after a double-pay race was measured. - Follow-ups the agents surfaced:
QuestBoardItemshould exposependingso pending claims read "Pending" not "Tamed";/calendar,/storage,/craft-item,/cook-foodroutes drop:userId(MyCalendar now falls back to currentUser); MyQuests never registers Swiper (pager likely inert); MyCalendar prints rawdueByTime; ~30.vuefiles needlang="ts"on<script src>before jest can mount them;chemx build --helpruns a real build.
Battle rebuild (later the same day, paused mid-wiring): BattleField was rebuilt from an 1,865-line page into a thin page over battle/* (context, encounter loader, rewards) and composables/* (dialog, outcome, background, audio, ATB display) plus BattleDialogBox / BattleEnemyStage components; see docs/Battle-Field-Architecture.md. Routes are now /battle/:userId/{quest|temple|free}/... (battle-quest, battle-temple, battle-free); the old battle-field* routes are gone. Fixed: 0-XP victories, unwinnable multi-beast fights (next beast steps forward), click-gated rewards (now committed at victory), no outcome recording (quest log entry + temple room cleared), always-returning-to-hometown (returns to origin). Goods/Abilities dropped from the battle menu until items have in-battle effects; in-page dev tools removed. State: typecheck clean, lint 0 errors, tests/unit/BattleContext.spec.ts green. Two agents were still running when paused: (a) dead-scaffolding sweep (BattleGround.ts, engine/battle, hooks/battle, BattleroomDevTools, battleroom config/scripts, dev battle routes, battle-store encounter helpers, random-encounter runaway fix); (b) navigators (TempleGrounds Fight + cleared-room UX, room-editor Test Fight, MyTask "Fight!" for beast quests, new __tests__/BattleField.spec.ts). Their edits land on disk regardless; read their reports first. A vue-cli-service serve dev server is up on :8100 (pid 378139).
Both agents finished before the pause: the dead-scaffolding sweep is complete (27 files removed, battle store trimmed, random-encounter runaway fixed) and the navigators are wired (temple Fight + cleared-room check marks, room-editor Test Fight, MyTask "Fight!" on beast quests). Not done: __tests__/BattleField.spec.ts (the folder was removed with the old spec; recreate it). Two gaps found and NOT yet fixed: (1) a temple fight resumed after a hard reload returns to floor 1F and markRoomCleared is a no-op because the temple route has no level and no in-memory state (carry level on the return route, e.g. as a query, and let markRoomCleared create state); (2) lockOnEnter rooms lock all doors on entry and nothing unlocks them on victory, so a hero can be stuck after winning (clear room.locked in TempleSystem.markRoomCleared). Newly orphaned, left in place: XpFabBattleActions.vue, hooks/useDialog.ts, the cross-env devDependency, docs/App/SideMenu/GameMaster/Battleroom-Dev-Tools.md.
Next steps (in order): 1) run chemx typecheck && chemx lint && chemx test, then chemx build; 2) open the app in a browser (dev server :8100) and walk the loop end to end (nothing above was seen rendered), then commit; 3) fix the two temple gaps above and write BattleField.spec.ts; 4) remaining battle wiring: battle-field-quest must load the quest's beast (BattleField.ts ~1615-1630 TODO) and call recordBattleCompletion on victory; 3) XpDashboard.ts "New Temple" route name (xp-temple-creator → xp-temple-settings); 4) GM gating: expose the isAdult checkbox in AddProfile and guard /game-master; 5) shop purchase → GM-visible record; 6) asset diet (require.context scopes, backgrounds) before any native build; 7) delete the dead files listed in the map (LogIn copy.vue, XpFabPageShortcuts copy.vue, [AppJig], MyAchievements, ProfileCards, OldSchoolHeader, AchievementsCard, XpTabBarPage, importWindTemple.ts, dsl-test-temple.ts, BattleGround.ts after audit). See Roadmap → "v1 Completion Plan".
Do It For The XP is a gamified chore management application built with Vue 3, Ionic 7, and Capacitor. The application transforms household tasks into RPG-style quests where children become "Bounty Hunters" and parents become "Game Masters."
-
Random Background: Dummy encounters now dynamically randomize
bg1andbg2across the valid earthbound background spectrum (0-325) rather than relying on static fallback defaults. - Random Beast Avatar: The dummy enemy now assigns a random avatar from the 73 available beast portraits (1-73) instead of rendering without an image.
-
All 9 Voxel Stage Models: Built voxel geometries in
stageShapes.tsinspired by map icons:- Plains (whirling tornado vortex)
- Forests (pine and canopy trees with mushrooms)
- Islands (tropical palm atoll and ocean)
- Swamps (mossy skull totem)
- Mountains (twin snow-capped volcanic peaks)
- Sands (desert saguaro cactus with arms)
- Clouds (thundercloud with electric lightning bolt)
- Tundras (arctic snow igloo with arched entryway)
- The Moon (cosmic crescent with glowing celestial star)
-
Organism Component: Created
XpStageModelorganism with 30 FPS idle throttling, 60 FPS drag rotation,pixelRatio: 1, tab visibility pause,<xp-landmark-badge>atom integration, and route navigation. -
World Map Plaza Layout: Arranged in
WorldMap.vuewith 4-row layout leaving the center 140px clearing for the navigation FAB and safe top clearance below HUD bars. -
Unit Tested: Full Jest suite in
stageVoxel.spec.tscovering box counts, positions, normals, colors, indices, and fallback handling.
Refining the core UI elements for a premium RPG feel.
- ✅ Main User HUD:
- Combined HP/MP bar and text labels for cleaner layout.
- Improved label visibility and alignment (text below bars).
- Grouped stat values for better readability.
- Added animated GP Bar stacked above XP Bar.
- Applied locale formatting to all HUD numbers (1,000 instead of 1000).
-
Menu Toggle: Implemented
menuControllerlogic for the retro menu button to sync functionality with Quick Draw.
- ✅ Battle Task Menu Style: Adjusted "Attack" menu items and "Bash" costs to match the main RPG menu font (Apple Kid 1.5rem) and color (RPG yellow). Replaced the bolt icon with claw-marks and removed the redundant header for a cleaner, unified flow. removed background circles from icons.
- ✅ Area FAB / Page Menu:
- Centered menu on screen (matching User HUD aesthetic).
- Added backdrop blur overlay with click-to-close.
- Implemented "square-x" close button in top-right.
- Fixed Ionic FAB visibility issues by moving menu outside
ion-fab-list. -
Synchronized Blur State: Fixed "phase-flipping" and "double-click" issues by letting Ionic handle natural toggles and forcing re-mounts on navigation via unique
:keybindings.
- ✅ User HUD Avatar:
- Optimized avatar image registration to perfectly cover the circular FAB button.
- Removed square green border artifacts and optimized hover scaling (1.12x).
- Improved AP badge display with "AP %" prefix.
- ✅ Navigation Highlighting:
- Implemented global styles to dim non-active tabs in
ion-tab-bar. - Non-selected tabs are grayscale (90%) and lower opacity (0.55).
- Active tabs feature saturation boost, brightness increase, and a subtle vertical lift (translateY).
- Added hover transitions for interactive feedback.
- Implemented global styles to dim non-active tabs in
- ✅ Equipment Modal:
- Converted into a full-page Ionic card modal with
presentation="card". - Integrated with the shared premium modal system (matching Profile Modal).
- Added user identity (name/level) to modal header for consistency.
- Simplified layout styles while maintaining the 7/5 grid split.
- Converted into a full-page Ionic card modal with
- ✅ Modal Dismissal System:
-
Ref-Based Dismissal: Standardized all major modals (
UserProfileModal,XpEquipmentModal,ItemInfoModal,ATMModal,SaveAndQuitModal) to use a localdismiss()method via a componentref. -
Sound Logic Refinement: Resolved the "double close sound" issue by using
@click.stopon close buttons to prevent event bubbling to global UI listeners. -
Clean Event Flow: Decoupled the parent's
closestate from the button click, moving to the modal's nativedidDismisslifecycle event to ensure single-emission logic.
-
Ref-Based Dismissal: Standardized all major modals (
- ✅ Temple Navigation: Implemented state-based smooth scrolling, formalized
/splashdefault routing, and tiered background strategy (parent-hosted vs child-transparent). - ✅ Quest Type Refactor: Replaced standard radio groups in
XpConfigAchievementwith iconic, dialpad-grid selection modals. Implemented genericXpTypeSelectorModalfor streamlined Quest and Party type definition. - ✅ Quest Navigation Optimization: Refactored
XpConfigAchievementto use nested routing andion-tabs, mirroring the Temple Settings architecture for consistent GM experience. Updated child tabs (Type, Heroes, Schedule, Rewards, Config) to individual components with shared state via Provide/Inject. - ✅ Temple Splash Page:
- Created a clean landing page for temple routes with a centered layout.
- Header: Icon, title, and description centered at top.
- Stats: 4-column responsive grid showing Rooms, Beasts, Floors, and World.
-
WeatherFX: Integrated with correct world-to-weather mapping (matching
XpTemples.vue). - Navigation: Centered "Temple" tab in navigation bar using the temple's specific icon.
- ✅ Quest Type Selection:
- Replaced
ion-radio-groupwith two clean, iconic action boxes for Quest Type and Party Type. - Implemented
XpTypeSelectorModal: a generic, two-step selector (Grid -> Confirmation) matching the temple creator aesthetic. - Updated
useAchievementFormhook with reactive state for modal visibility and active party type details.
- Replaced
- ✅ Code Refactoring: Split
XpConfigAchievement.vueinto separate template (.vue), logic (.ts), and style (.scss) files for better maintainability. - ✅ Setup Slideshow & Dashboard Polish:
-
Dynamic Themed Backgrounds: Integrated with the global
bg-slidesystem, applying color variations (.bg-slide-xp, .bg-slide-gp, etc.) to theion-pagefor stable, high-performance background transitions. -
Premium Glassmorphism: Implemented a modern design language using
backdrop-filter: blur, subtle semi-transparent borders, and deep shadows for "floating" content cards. -
Stat Counting Animations: Integrated
vue3-autocounterinto the sharedXpStatBox, providing a satisfying data revealed effect when dashboards load. -
Dashboard Grid Refinement: Updated
XpDashboardGridto support a:colsprop for explicit column control. Configured theWelcomeDashboardto a 3-column layout (3x2 for the 6 boxes) as requested by the GM. - Entrance Animations: Added cubic-bezier staggered entrance animations for hero cards and dashboard components to enhance the "alive" feel of the onboarding flow.
- Custom Navigation: Replaced standard swiper arrows and bullets with themed, RPG-style indicators matching the Earthbound aesthetic.
-
Dynamic Themed Backgrounds: Integrated with the global
- ✅ Code Quality & Linting: Performed a global cleanup of ESLint errors and warnings across the codebase, including removal of unused imports, console statements, and duplicated methods in major components like
BattleGround.ts,BattleState.ts, anduseAchievementForm.ts. - ✅ Bestiary Index Fix: Resolved critical syntax and structure errors in
XpBestiary.vuecaused by misplaced braces and broken method blocks. RefactoredclickAttachBeastto use clean async/await logic. Fixed spelling errors inDbStorageApitoast helpers. - ✅ Quest Index Icons:
- Implemented
LORE_COMBO_MATRIXshared constant for mapping Quest Type + Party Type to thematic icons/names. - Updated
XpAchievementItemto display dynamic "Combo Icons" or "Beast Previews" in the avatar slot. - Integrated beast loading into
XpAchievements.vueto ensure real-time beast avatars show in the quest index. - Enhanced Grid View in admin quest index to match the iconic combo logic.
- Updated
useAchievementFormsummary card to reflect the new lore-based naming and iconography.
- Implemented
- ✅ Beast Selection UI:
- Removed the heavy "TARGET ACQUIRED" overlay in
QuestTypeTab.vue. - Simplified the selection indicator by using
XpBeastSelectorItem's native checkmark and border logic.
- Removed the heavy "TARGET ACQUIRED" overlay in
- ✅ Beast Task List:
- Replaced the
alertController(which failed to render HTML) with a dedicatedBeastTaskListModal.vue. - Implemented a premium glassmorphic list with staggered entrance animations for beast tasks.
- Replaced the
- ✅ UI Polish: Synchronized Area FAB blur, optimized Avatar presentation, standardized Ref-based modal dismissal, implemented global tab-bar highlighting, added a premium splash page for temple discovery, fixed the retro User HUD menu toggle, and matched the "Attack" task menu styles to the main RPG dialog menu (removing headers and updating icons).
- ✅ Compendium Tab Root Navigation: Resolved a bug where clicking an active tab's subtree (e.g., editing a quest) wouldn't return to the tab's root index. Implemented
handleTabClickinXpCompendium.vueto intercept clicks and force-navigate to the base tab route when already within its subtree. - ✅ Room Editor Toggles Fix: Resolved double-triggering bug on "It's a Trap" and Mimic toggles where clicking the switch itself failed to toggle.
- ✅ AI Generate Card Alignment: Corrected the sizing of the AI Generate box in
QuestTypeTab.vueto match other beast cards. Implementedaspect-ratio: 1/1, increased dashed border thickness, and added structural alignment spacers to ensure a perfectly uniform grid layout.
The Temple Creator tool has been consolidated and polished for a more cohesive experience.
Location: src/app/Admin/XpCompendium/views/XpTemples/
Recent Accomplishments:
- ✅ Consolidated Editor: Removed redundant
TempleFloorEditor.vueand unified all editing logic into theLayouttab (XpTempleLayout.vue). - ✅ Centered Grid Layout: Optimized the grid editor to be centered with the page for better focus and premium aesthetic.
- ✅ Integrated Header: Re-enabled
XpTempleCreatorHeader.vuewithin the layout tab for seamless grid resizing. - ✅ Popover Sync: Updated the quick-edit popover with full feature parity, including item/loot selection.
Current State:
- ✅ Room type selection modal complete
- ✅ Cardinal door system (N/E/S/W) with locks
- ✅ Adjacent room detection for wall limiting
- ✅ Monster room beast selector integration
- ✅ Room navigation within editor
- ✅ Loot room configuration complete
- ✅ Shop room configuration complete
- ✅ Smooth navigation return paths with auto-scroll and highlight
- ✅ Dynamic accordion tier isolation for beast management
Key Components:
-
XpTempleLayout.vue- Unified editor and layout preview -
components/RoomCardinalLayout.vue- Room direction/door UI -
components/XpTempleCreatorHeader.vue- Floor controls
The battle system has been recently enhanced:
- ✅ Proper player stats HP/MP calculation (level + class based)
- ✅ Battle HUD with animated stats display
- ✅ Integrated action menu in dialog box
- ✅ Intro dialog messages before battle starts
- ✅ Pinia migration complete (Vuex fully removed)
All stores are Pinia-based in src/lib/store/stores/:
-
user.ts- User profiles, authentication, GP -
game.ts- Global game state, theme, entity caching -
battle.ts- Battle state management -
audio.ts- Sound control -
temple-creator.ts- Temple builder state
src/lib/engine/
├── battle/ # Combat logic
├── core/dungeons/ # Temple system
└── temples/ # Pre-built temples
components/
├── atoms/ # Basic primitives
├── molecules/ # Composed units
└── organisms/ # Complex features
-
3D Voxel Landmark System:
- Unified Shared WebGL Landmark Renderer (
sharedLandmarkRenderer.ts): All buildings, stages, and temples share a single offscreen WebGL context and blit onto 2D canvases, preventing mobile WebGL context exhaustion (8/16 limit) and context loss crashes (x_xcanvases) during Ionic page navigation. - Interactive Three.js WebGL voxel models for all 9 Temples (
XpTempleModel). - Interactive 3D voxel models for all 7 HomeTown destinations matching navigation menus 1:1: Hero's Home, Market, Hospital, Hotel, Bank, Town Hall, and The Plains (
world-plainsleave town gateway located at the north plaza path between Town Hall and Gold Bank). - Center page menu FAB retired in
MyPortal.vueas 3D voxel models provide direct 1:1 tactile navigation across plazas. - Interactive 3D voxel models for all 9 World Land shops: Pegasus Ranch, Wrecked Ship, Hermit's Tent, Crystal Caverns, Pond of Life Oasis, Witch's Hut, Snow Shack, Cloud Market, Theia City Emporium.
- Interactive 3D voxel models for World Travel Pegasus (
pegasus) across all 8 World Region views (Mountains, Clouds, Desert, Forest, Ice, Islands, Moon, Swamps) providing 1:1 tactile navigation matching page menus. - Interactive 3D voxel models for Hometown return gate (
home-town) on World Plains, syncing 1:1 withuserActions(preserving World Map purely for the 9 world stages). - Interactive 3D voxel models for Home interior menu landmarks aligned with room background art: Cozy Bed (
home-bed) top-left on bed, My Storage (home-storage) top-center, My Workbench (home-workbench) middle-left, My Kitchen (home-kitchen) middle-right, My Calendar (home-calendar) bottom-left on rug, and Front Door (home-door) bottom-center on entrance mat. - Direct camera-facing idle orientation, manual touch/drag rotation, smash-style floating titles (title-only retro pixel font with thick black outline, removing black pill boxes and sublabel clutter), and click-to-enter routing (auto-rotation and idle bobbing disabled for 0% idle GPU draw calls; renders on-demand on drag and initial load).
- Modern iOS Minimalist Bottom Navigation (
XpBottomNav.vue): Borderless, transparent tabs with frosted glass dock, 0.5px hairline top border, muted inactive states, and vibrant gold active highlighting without clunky box borders or inset shadows. - Bottom dock clearance (+120px) and top safe area clearance (+5.5rem) preventing HUD and hairline overlay.
- Full unit test coverage in
templeVoxel.spec.ts(9/9 passed) andbuildingVoxel.spec.ts.
- Unified Shared WebGL Landmark Renderer (
- Loot Room Configuration - Complete treasure chest reward selector
- Room Data Persistence - Ensure room edits save to temple
- Room Validation - Must have entrance, boss for temples
- Template Rooms - Pre-configured room types
- Battle dialog may show duplicate intro messages (recently fixed)
- Wall icons occasionally show wrong icon type (recently fixed)
- Floor editor grid size needs custom dimensions (recently fixed)
- ✅ Navigation Crash: Fixed a
TypeError: Cannot read properties of undefined (reading 'preventDefault')inWorldPlains.tswhen navigating via FAB shortcuts. - Area FAB menu was invisible due to Ionic
ion-fab-listopacity transitions (recently fixed)
| Doc | Purpose |
|---|---|
| Roadmap | Overall project direction |
| Architecture | Technical overview |
| Temple-System | Dungeon engine |
| Battle-System-Engine | Combat mechanics |
| Player-Stats-Leveling | HP/MP formulas |
- Read:
docs/Roadmap.md- Understand current phase - Read:
docs/current_context.md(this file) - Get oriented - Check: Active files in
XpTemples/- Temple Creator focus - Review:
lib/store/stores/- State architecture
Landed on master (all local, not pushed): Powers privilege ledger Phase 1 (AP total on profile/HUD; My Powers page with Cast; per-hero cast log; Town Crier chat line + power-cast notification; AP stamped at completion); Class Codex (full-screen, from the equipment dock) and the hybrid class tree 4 → 8 → 3 (Knight/Berserker, White/Black Mage, Assassin/Ranger, Martial Artist/Mystic; Paladin/Ninja/Sage as crown classes; passives composed from existing fields); quests carry timesOfDay (calendar tabs work, N-a-day chores as one quest, timed seed, GM chips); first-grade intro copy; RPG toasts everywhere with X + swipe; dungeon dialogs as pixel reveals (riddle, shop, room actions with art), temple-cleared egg reveal, encounter reveals with beast art, chests open closed; onboarding gates (first Pegasus unlocks the overworld; whistle = fast travel); 3D look builder in profile creation + full-screen face picker; profile edit no longer wipes fields; teleports pair themselves; any door into a boss room is the Boss door; Master Room = Pegasus Egg chamber (golden egg icon), Boss Key naming, full-screen room type guide with evenly spaced dock rail options; test script runs jest directly.
Rules decided by the owner today: AP is never spent; privileges are cast with MP; the ledger is the feature, nothing enforced; controls at the bottom within thumb reach; money-valued things stay in shops.
Open: Phase 2 of the Powers spec (rolling windows, duration timer, caps); the "empty player screen" the owner wants improved (which screen is unanswered); Pegasus chest with a checklist (offered); spell skill tree spec; Class Codex "In real life" copy for crown classes; chemx verify test step times out on the full ~6 min suite; other-session work in flight (scene transitions, apiHost, sharedLandmarkRenderer typecheck errors). Spec: docs/superpowers/specs/2026-10-11-powers-privilege-ledger-design.md.