From 53bdcb8a9db386db6b50205fa1aa2485d56557c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A7=E9=A9=8A?= Date: Sat, 22 Nov 2025 21:25:35 +0800 Subject: [PATCH] good version --- src/App.vue | 24 ++- src/components/JiaobeiAnimation.vue | 7 +- src/components/PetGame.vue | 256 +++++++++++++++++++++++++++- src/components/PetInfoScreen.vue | 69 ++++++++ src/composables/useEventSystem.js | 144 ++++++++++++++++ src/composables/usePetSystem.js | 133 +++++++++++++-- 6 files changed, 614 insertions(+), 19 deletions(-) create mode 100644 src/composables/useEventSystem.js diff --git a/src/App.vue b/src/App.vue index 185892a..85c5744 100644 --- a/src/App.vue +++ b/src/App.vue @@ -5,6 +5,7 @@ import DeviceScreen from './components/DeviceScreen.vue'; import PetGame from './components/PetGame.vue'; import Menu from './components/Menu.vue'; import { usePetSystem } from './composables/usePetSystem'; +import { useEventSystem } from './composables/useEventSystem'; const currentScreen = ref('game'); const petGameRef = ref(null); @@ -12,6 +13,7 @@ const showStats = ref(false); // Stats visibility const debugAction = ref(null); // For passing debug commands to PetGame // Initialize Pet System +const petSystem = usePetSystem(); const { stage, state, @@ -24,8 +26,19 @@ const { hatchEgg, reset, achievements, - unlockAllAchievements -} = usePetSystem(); + unlockAllAchievements, + resurrect, + reincarnate +} = petSystem; + +// Initialize Event System +const { currentEvent, checkEventTriggers, triggerRandomEvent } = useEventSystem(petSystem); + +// Start Event Loop +setInterval(() => { + checkEventTriggers(); +}, 10000); // Check every 10 seconds + // Handle Action Menu Events function handleAction(action) { @@ -88,6 +101,12 @@ function handleAction(action) { console.log('求籤功能'); // TODO: 實作求籤邏輯 break; + case 'resurrect': + resurrect(); + break; + case 'reincarnate': + reincarnate(); + break; default: console.log('Action not implemented:', action); } @@ -117,6 +136,7 @@ function triggerDebugAction(action, payload = null) { :showStats="showStats" :debugAction="debugAction" :achievements="achievements" + :currentEvent="currentEvent" @update:state="state = $event" @action="handleAction" /> diff --git a/src/components/JiaobeiAnimation.vue b/src/components/JiaobeiAnimation.vue index c413428..899d240 100644 --- a/src/components/JiaobeiAnimation.vue +++ b/src/components/JiaobeiAnimation.vue @@ -35,7 +35,7 @@ - + + + diff --git a/src/components/PetGame.vue b/src/components/PetGame.vue index 3713d49..70b3978 100644 --- a/src/components/PetGame.vue +++ b/src/components/PetGame.vue @@ -100,8 +100,21 @@
💀
- -
+ +
+
+
+
寵物已死亡
+
+ + +
+
+
+ + +
+
+
{{ currentEvent.text }}
+
@@ -169,6 +193,7 @@ @result="handleJiaobeiResult" @retry-fortune="handleRetryFortune" @finish-fortune="handleFinishFortune" + @resurrect-confirm="handleResurrectConfirm" /> @@ -195,6 +220,12 @@ :hunger="stats?.hunger || 100" :happiness="stats?.happiness || 100" :health="stats?.health || 100" + :str="stats?.str || 0" + :int="stats?.int || 0" + :dex="stats?.dex || 0" + :generation="stats?.generation || 1" + :deityFavor="stats?.deityFavor || 0" + :destiny="stats?.destiny || null" :achievements="achievements" @close="showPetInfo = false" /> @@ -301,6 +332,10 @@ const props = defineProps({ achievements: { type: Array, default: () => [] + }, + currentEvent: { + type: Object, + default: null } }); @@ -315,6 +350,8 @@ const showFortuneResult = ref(false); const currentLotData = ref(null); const currentLotNumber = ref(null); const consecutiveSaintCount = ref(0); +const lastJiaobeiResult = ref(null); // 記錄最後的擲筊結果用於招魂確認 + const showPetInfo = ref(false); const showInventory = ref(false); const showPlayMenu = ref(false); @@ -416,6 +453,7 @@ function handleTrainingAttack() { function handleGameComplete(won) { console.log('Game completed, won:', won); + const gameType = currentGame.value; // Capture before clearing currentGame.value = ''; if (won) { @@ -434,6 +472,20 @@ function handleGameComplete(won) { // 增加一些數值作為獎勵 stats.value.happiness = Math.min(100, stats.value.happiness + 10); stats.value.hunger = Math.max(0, stats.value.hunger - 5); // 運動會餓 + + // V2 Stats Growth + let statGain = 1; + // Destiny Effect: Diligence (勤奮) - +20% rewards (rounded up to +1 extra for small values) + if (stats.value.destiny?.id === 'diligence') { + statGain += 1; + } + + if (gameType === 'training') { + stats.value.str = (stats.value.str || 0) + statGain; + // Training also gives Deity Favor slightly? Maybe not. + } else if (gameType === 'guessing') { + stats.value.int = (stats.value.int || 0) + statGain; + } } } @@ -460,6 +512,13 @@ function handleBallGameComplete(won) { stats.value.happiness = Math.min(100, stats.value.happiness + 15); stats.value.hunger = Math.max(0, stats.value.hunger - 10); + + // V2 Stats Growth: DEX + let statGain = 1; + if (stats.value.destiny?.id === 'diligence') { + statGain += 1; + } + stats.value.dex = (stats.value.dex || 0) + statGain; } } @@ -480,17 +539,65 @@ function handleFortuneStickClose() { consecutiveSaintCount.value = 0; } +function handleResurrectAttempt() { + // 招魂:需要擲筊 + fortuneMode.value = 'resurrect'; + showJiaobeiAnimation.value = true; + consecutiveSaintCount.value = 0; +} + +function handleReincarnate() { + emit('action', 'reincarnate'); +} + function handleJiaobeiResult(type) { if (fortuneMode.value === 'fortune') { if (type === 'saint') { consecutiveSaintCount.value++; - } else { - // 如果不是聖筊,計數歸零(邏輯上失敗了,需要重新求籤) + // V2: Pet Reaction + triggerState('happy', 1000); + eventAnimation.value = { type: 'float-up', iconClass: 'pixel-heart' }; + setTimeout(() => eventAnimation.value = null, 1000); + } else if (type === 'laugh') { + // 笑筊 consecutiveSaintCount.value = 0; + triggerState('refuse', 1000); // Confused + eventAnimation.value = { type: 'float-up', iconClass: 'pixel-question' }; + setTimeout(() => eventAnimation.value = null, 1000); + } else { + // 陰筊 + consecutiveSaintCount.value = 0; + triggerState('sad', 1000); // Scared + eventAnimation.value = { type: 'float-up', iconClass: 'pixel-skull' }; + setTimeout(() => eventAnimation.value = null, 1000); } + } else if (fortuneMode.value === 'resurrect') { + // 招魂模式:記錄結果,等待用戶點擊"確認" + lastJiaobeiResult.value = type; } } +function handleResurrectConfirm() { + // 用戶點擊招魂的"確認"按鈕 + const result = lastJiaobeiResult.value; + + showJiaobeiAnimation.value = false; + fortuneMode.value = 'normal'; + lastJiaobeiResult.value = null; + + if (result === 'saint') { + // 聖筊 - 復活 + emit('action', 'resurrect'); + eventAnimation.value = { type: 'float-up', iconClass: 'pixel-heart' }; + setTimeout(() => eventAnimation.value = null, 2000); + } else { + // 非聖筊 - 直接輪迴 + emit('action', 'reincarnate'); + } +} + + + function handleRetryFortune() { // 重新開始搖籤 showJiaobeiAnimation.value = false; @@ -505,6 +612,39 @@ function handleFinishFortune() { currentLotData.value = lot; showJiaobeiAnimation.value = false; showFortuneResult.value = true; + + // --- V2 Fortune Impact --- + // Increase Deity Favor for completing the ritual + stats.value.deityFavor = (stats.value.deityFavor || 0) + 1; + + const grade = lot.grade; // e.g., "上上", "上吉", "中平", "下下" + + if (grade.includes('上上')) { + triggerState('happy', 3000); + stats.value.happiness = Math.min(100, stats.value.happiness + 20); + stats.value.health = Math.min(100, stats.value.health + 10); + eventAnimation.value = { type: 'float-up', iconClass: 'pixel-heart' }; + } else if (grade.includes('上') || grade.includes('大吉')) { + triggerState('happy', 2000); + stats.value.happiness = Math.min(100, stats.value.happiness + 10); + } else if (grade.includes('下下')) { + triggerState('sad', 3000); + // Trigger Bad Event + if (triggerRandomEvent) { + // Force a bad event or just increase risk + // For now, let's just lower stats + stats.value.happiness = Math.max(0, stats.value.happiness - 10); + } + } else if (grade.includes('下')) { + triggerState('sad', 2000); + stats.value.health = Math.max(0, stats.value.health - 5); + } + + // Destiny Effect: Luck (福運) - Bonus happiness + if (stats.value.destiny?.id === 'luck' && (grade.includes('上') || grade.includes('吉'))) { + stats.value.happiness = Math.min(100, stats.value.happiness + 5); + } + } else { console.error('Lot not found:', currentLotNumber.value); handleJiaobeiClose(); @@ -1690,6 +1830,69 @@ defineExpose({ 50% { transform: translate(-50%, -50%) translateY(-4px); } } +/* Death Screen */ +.death-screen { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.7); + z-index: 100; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.death-menu { + margin-top: -30px; /* Overlay on top of tombstone */ + background: rgba(224, 224, 224, 0.95); + border: 4px solid #555; + padding: 10px; + border-radius: 8px; + text-align: center; + box-shadow: 0 4px 0 #333; + max-width: 180px; + width: 90%; + z-index: 1; + position: relative; + box-sizing: border-box; +} + +.death-title { + font-family: 'DotGothic16', monospace; + font-size: 14px; + font-weight: bold; + color: #333; + margin-bottom: 8px; +} + +.death-actions { + display: flex; + flex-direction: column; + gap: 6px; +} + +.action-btn { + font-family: 'DotGothic16', monospace; + padding: 6px 10px; + background: #fff; + border: 2px solid #888; + border-radius: 4px; + cursor: pointer; + font-size: 11px; + transition: all 0.1s; + white-space: normal; + line-height: 1.2; + word-wrap: break-word; +} + +.action-btn:active { + transform: translateY(2px); + background: #ddd; +} + @@ -1773,6 +1976,51 @@ defineExpose({ background: transparent; } +.pixel-note { + width: 1px; + height: 1px; + background: transparent; + transform: scale(2); + color: #ff1493; + box-shadow: + -2px -2px, -1px -2px, 1px -2px, 2px -2px, + -3px -1px, -2px -1px, -1px -1px, 0px -1px, 1px -1px, 2px -1px, 3px -1px, + -3px 0px, -2px 0px, -1px 0px, 0px 0px, 1px 0px, 2px 0px, 3px 0px, + -2px 1px, -1px 1px, 0px 1px, 1px 1px, 2px 1px, + -1px 2px, 0px 2px, 1px 2px, + 0px 3px; +} + +.pixel-question { + width: 1px; + height: 1px; + background: transparent; + transform: scale(2); + color: #9C27B0; + box-shadow: + -1px -3px, 0px -3px, 1px -3px, + -2px -2px, 2px -2px, + 2px -1px, + 1px 0px, + 0px 1px, + 0px 3px; +} + +.pixel-skull { + width: 1px; + height: 1px; + background: transparent; + transform: scale(2); + color: #555; + box-shadow: + -2px -3px, -1px -3px, 0px -3px, 1px -3px, 2px -3px, + -3px -2px, 3px -2px, + -3px -1px, -1px -1px, 1px -1px, 3px -1px, + -3px 0px, 3px 0px, + -2px 1px, -1px 1px, 0px 1px, 1px 1px, 2px 1px, + -1px 2px, 1px 2px; +} + .pixel-toy { box-shadow: -1px -2px #32cd32, 0px -2px #32cd32, 1px -2px #32cd32, diff --git a/src/components/PetInfoScreen.vue b/src/components/PetInfoScreen.vue index 47e0d90..695697d 100644 --- a/src/components/PetInfoScreen.vue +++ b/src/components/PetInfoScreen.vue @@ -105,6 +105,43 @@
+ + +
+ 命格 +
+ {{ destiny.name }} + {{ destiny.description }} +
+
+
+ 命格 + ??? +
+ +
+ + +
+ 力量 (STR) + {{ str }} +
+
+ 智力 (INT) + {{ int }} +
+
+ 敏捷 (DEX) + {{ dex }} +
+
+ 世代 + 第 {{ generation }} 代 +
+
+ 神明好感 + {{ deityFavor }} +
HP @@ -170,6 +207,13 @@ const props = defineProps({ type: Number, default: 100 }, + // v2 Stats + str: { type: Number, default: 0 }, + int: { type: Number, default: 0 }, + dex: { type: Number, default: 0 }, + generation: { type: Number, default: 1 }, + deityFavor: { type: Number, default: 0 }, + destiny: { type: Object, default: null }, achievements: { type: Array, default: () => [] @@ -532,6 +576,31 @@ const weight = computed(() => { font-weight: 600; } +.destiny-item { + flex-direction: column; + align-items: flex-start; + gap: 4px; +} + +.destiny-content { + display: flex; + flex-direction: column; + width: 100%; + padding-left: 4px; + gap: 2px; +} + +.destiny-name { + color: #d32f2f; /* Red for emphasis */ + font-size: 12px; +} + +.destiny-desc { + font-family: 'DotGothic16', monospace; + font-size: 10px; + color: #665544; +} + /* Achievements */ .achievements-view { padding: 12px; diff --git a/src/composables/useEventSystem.js b/src/composables/useEventSystem.js new file mode 100644 index 0000000..34d2100 --- /dev/null +++ b/src/composables/useEventSystem.js @@ -0,0 +1,144 @@ +import { ref } from 'vue'; + +export function useEventSystem(petSystem) { + const { stats, state, triggerState } = petSystem; + + const currentEvent = ref(null); + const eventHistory = ref([]); + + // --- Event Database --- + // Categories: 'good', 'bad', 'weird' + const EVENT_DATABASE = [ + // --- Good Events --- + { + id: 'found_charm', + type: 'good', + text: '撿到小符', + effect: (s) => { s.happiness = Math.min(100, s.happiness + 5); }, + condition: () => true, + icon: 'pixel-charm' + }, + { + id: 'self_clean', + type: 'good', + text: '自己掃地', + effect: (s) => { if (s.poopCount > 0) s.poopCount--; }, + condition: (s) => s.poopCount > 0, + icon: 'pixel-broom' + }, + { + id: 'dance', + type: 'good', + text: '開心地跳舞', + effect: (s) => { s.happiness = Math.min(100, s.happiness + 10); }, + condition: (s) => s.happiness > 70, + icon: 'pixel-note' + }, + { + id: 'gift_apple', + type: 'good', + text: '給你一顆果子', + effect: (s) => { /* Add to inventory logic later */ s.hunger = Math.min(100, s.hunger + 5); }, + condition: () => Math.random() < 0.3, + icon: 'pixel-apple' + }, + + // --- Bad Events --- + { + id: 'night_noise', + type: 'bad', + text: '半夜亂叫', + effect: (s) => { s.happiness = Math.max(0, s.happiness - 5); }, + condition: (s) => isNight(), + icon: 'pixel-angry' + }, + { + id: 'overeat', + type: 'bad', + text: '偷吃太多', + effect: (s) => { s.hunger = Math.min(100, s.hunger + 20); s.health = Math.max(0, s.health - 5); }, + condition: (s) => s.hunger > 80, + icon: 'pixel-meat' + }, + { + id: 'stomach_ache', + type: 'bad', + text: '胃痛', + effect: (s) => { s.health = Math.max(0, s.health - 10); }, + condition: (s) => s.health < 50, + icon: 'pixel-skull' + }, + + // --- Weird Events --- + { + id: 'stare', + type: 'weird', + text: '盯著螢幕外面看...', + effect: () => { }, + condition: () => true, + icon: 'pixel-eye' + }, + { + id: 'corner_squat', + type: 'weird', + text: '走到角落蹲著', + effect: (s) => { s.happiness = Math.max(0, s.happiness - 5); }, + condition: () => true, + icon: 'pixel-cloud' + }, + { + id: 'glitch', + type: 'weird', + text: '#@!$%^&*', + effect: (s) => { if (s.int > 5) s.int++; }, + condition: () => Math.random() < 0.1, + icon: 'pixel-glitch' + } + ]; + + function isNight() { + const hour = new Date().getHours(); + return hour >= 22 || hour < 6; + } + + function checkEventTriggers() { + if (state.value === 'sleep' || state.value === 'dead') return; + + // 10% chance to trigger an event per check + // Destiny Effect: Luck (福運) - Good events more likely? + // Destiny Effect: Spiritual (靈視) - Night events more likely + + if (Math.random() < 0.1) { + triggerRandomEvent(); + } + } + + function triggerRandomEvent() { + // Filter valid events + const validEvents = EVENT_DATABASE.filter(e => e.condition(stats.value)); + if (validEvents.length === 0) return; + + const event = validEvents[Math.floor(Math.random() * validEvents.length)]; + + // Apply effect + event.effect(stats.value); + + // Set current event for UI + currentEvent.value = event; + eventHistory.value.unshift({ ...event, time: new Date() }); + + // Auto-clear event after 3 seconds + setTimeout(() => { + currentEvent.value = null; + }, 4000); + + console.log('Event Triggered:', event.text); + } + + return { + currentEvent, + eventHistory, + checkEventTriggers, + triggerRandomEvent + }; +} diff --git a/src/composables/usePetSystem.js b/src/composables/usePetSystem.js index 9569504..101cd02 100644 --- a/src/composables/usePetSystem.js +++ b/src/composables/usePetSystem.js @@ -5,6 +5,17 @@ export function usePetSystem() { const stage = ref('egg'); // egg, baby, adult const state = ref('idle'); // idle, sleep, eating, sick, dead, refuse + // --- Destiny Data --- + const DESTINIES = [ + { id: 'luck', name: '福運', description: '籤詩好籤率 +10%', rarity: 1 }, + { id: 'diligence', name: '勤奮', description: '訓練遊戲獎勵 +20%', rarity: 1 }, + { id: 'gluttony', name: '暴食', description: '飢餓下降速度 +30%', rarity: 1 }, + { id: 'playful', name: '愛玩', description: 'Happiness 更快下降/更快上升', rarity: 1 }, + { id: 'purification', name: '淨化', description: '生病機率 -20%', rarity: 1 }, + { id: 'thirdeye', name: '天眼', description: '擲筊出聖筊機率微升', rarity: 2 }, + { id: 'medium', name: '冥感', description: '死亡後招魂成功率提升', rarity: 2 } + ]; + // --- Stats --- const stats = ref({ hunger: 100, // 0-100 (0 = Starving) @@ -12,7 +23,14 @@ export function usePetSystem() { health: 100, // 0-100 (0 = Sick risk) weight: 500, // grams age: 1, // days (start at day 1) - poopCount: 0 // Number of poops on screen + poopCount: 0, // Number of poops on screen + // v2 Stats + str: 0, // 力量 (Fireball Game) + int: 0, // 智力 (Guessing Game) + dex: 0, // 敏捷 (Catch Ball) + generation: 1, // 輪迴世代 + deityFavor: 0, // 神明好感度 + destiny: null // 天生命格 (Object) }); const achievements = ref([ @@ -32,6 +50,24 @@ export function usePetSystem() { // --- Actions --- + function assignDestiny() { + // Simple weighted random or just random for now + // Rarity 2 has lower chance + const roll = Math.random(); + let pool = DESTINIES; + + // 20% chance for rare destiny + if (roll < 0.2) { + pool = DESTINIES.filter(d => d.rarity === 2); + } else { + pool = DESTINIES.filter(d => d.rarity === 1); + } + + const picked = pool[Math.floor(Math.random() * pool.length)]; + stats.value.destiny = picked; + console.log('Assigned Destiny:', picked); + } + function feed() { if (state.value === 'sleep' || state.value === 'dead' || stage.value === 'egg' || isCleaning.value) return false; @@ -47,6 +83,7 @@ export function usePetSystem() { stats.value.weight += 50; // Chance to poop after eating (降低機率) + // Destiny Effect: Gluttony (暴食) might increase poop chance? Or just hunger decay. if (Math.random() < 0.15) { // 從 0.3 降到 0.15 setTimeout(() => { if (stats.value.poopCount < 4) { @@ -98,18 +135,32 @@ export function usePetSystem() { if (state.value === 'dead' || stage.value === 'egg') return; // Decrease stats naturally - // 目標:飢餓值約 30-60 分鐘下降 10%,快樂值約 20-40 分鐘下降 10% - // TICK_RATE = 3000ms (3秒), 600 ticks = 30分鐘 - // 飢餓值每 tick -0.05 → 600 ticks = -30 (30分鐘下降30%) - // 快樂值每 tick -0.08 → 600 ticks = -48 (30分鐘下降48%) + // Destiny Effect: Gluttony (暴食) - Hunger decreases faster (+30%) + let hungerDecay = 0.05; + if (stats.value.destiny?.id === 'gluttony') { + hungerDecay *= 1.3; + } + + // Destiny Effect: Playful (愛玩) - Happiness decreases faster + let happinessDecay = 0.08; + if (stats.value.destiny?.id === 'playful') { + happinessDecay *= 1.2; // Faster decay + } + + // Destiny Effect: DEX (敏捷) - Hunger decreases slower + // DEX 10 = -10% decay, DEX 50 = -50% decay + if (stats.value.dex > 0) { + const reduction = Math.min(0.5, stats.value.dex * 0.01); // Max 50% reduction + hungerDecay *= (1 - reduction); + } if (state.value !== 'sleep') { - stats.value.hunger = Math.max(0, stats.value.hunger - 0.05); - stats.value.happiness = Math.max(0, stats.value.happiness - 0.08); + stats.value.hunger = Math.max(0, stats.value.hunger - hungerDecay); + stats.value.happiness = Math.max(0, stats.value.happiness - happinessDecay); } else { // Slower decay when sleeping (約 1/3 速度) - stats.value.hunger = Math.max(0, stats.value.hunger - 0.015); - stats.value.happiness = Math.max(0, stats.value.happiness - 0.025); + stats.value.hunger = Math.max(0, stats.value.hunger - (hungerDecay * 0.3)); + stats.value.happiness = Math.max(0, stats.value.happiness - (happinessDecay * 0.3)); } // Random poop generation (更低的機率:約 0.5% per tick) @@ -137,8 +188,14 @@ export function usePetSystem() { } // Sickness Check (更低的生病機率) + // Destiny Effect: Purification (淨化) - Sickness chance -20% + let sickChance = 0.1; + if (stats.value.destiny?.id === 'purification') { + sickChance *= 0.8; + } + if (stats.value.health < 30 && state.value !== 'sick') { - if (Math.random() < 0.1) { // 從 0.3 降到 0.1 + if (Math.random() < sickChance) { state.value = 'sick'; } } @@ -224,6 +281,10 @@ export function usePetSystem() { stats.value.happiness = 50; stats.value.health = 100; stats.value.poopCount = 0; + + // v2: Assign Destiny + assignDestiny(); + isCleaning.value = false; } } @@ -238,11 +299,56 @@ export function usePetSystem() { health: 100, weight: 500, age: 1, - poopCount: 0 + poopCount: 0, + // v2 Reset + str: 0, + int: 0, + dex: 0, + generation: 1, + deityFavor: 0, + destiny: null }; tickCount = 0; } + function resurrect() { + if (state.value !== 'dead') return; + + state.value = 'idle'; + stats.value.health = 50; // Revive with half health + stats.value.happiness = 50; + stats.value.hunger = 50; + + // Penalty or Ghost Buff? + // For now just a console log, maybe visual effect later + console.log('Pet Resurrected!'); + } + + function reincarnate() { + // Inherit logic + const prevDestiny = stats.value.destiny; + const prevFavor = stats.value.deityFavor; + const nextGen = (stats.value.generation || 1) + 1; + + // Reset everything + reset(); + + // Apply Inheritance + stats.value.generation = nextGen; + + // 20% Favor inheritance + stats.value.deityFavor = Math.floor(prevFavor * 0.2); + + // Destiny Inheritance (Optional: Maybe keep if it was a rare one?) + // For now, let's say if you had a Rare (2) destiny, you keep it. + // Otherwise, you get a new one on hatch. + if (prevDestiny && prevDestiny.rarity === 2) { + stats.value.destiny = prevDestiny; + } + + console.log('Pet Reincarnated to Gen', nextGen); + } + // --- Lifecycle --- onMounted(() => { gameLoopId = setInterval(tick, TICK_RATE); @@ -264,6 +370,9 @@ export function usePetSystem() { hatchEgg, reset, achievements, - unlockAllAchievements + unlockAllAchievements, + assignDestiny, // Export for debug if needed + resurrect, + reincarnate }; }