// 寵物系統核心 - 與 API 整合 import { apiService } from './api-service.js' import { PET_SPECIES } from '../data/pet-species.js' import { FATES } from '../data/fates.js' import { DEITIES } from '../data/deities.js' export class PetSystem { constructor(api = apiService) { this.api = api this.state = null this.speciesConfig = null this.tickInterval = null this.eventCheckInterval = null } // 初始化寵物(從 API 載入或創建新寵物) async initialize(speciesId = 'tinyTigerCat') { try { // 從 API 載入現有狀態 this.state = await this.api.getPetState() if (!this.state) { // 創建新寵物 this.state = this.createInitialState(speciesId) await this.api.savePetState(this.state) } // 載入種族配置 this.speciesConfig = PET_SPECIES[this.state.speciesId] || PET_SPECIES[speciesId] // 計算戰鬥數值(在 speciesConfig 設置後) this.calculateCombatStats() return this.state } catch (error) { console.error('[PetSystem] 初始化失敗:', error) // 降級到本地狀態 this.state = this.createInitialState(speciesId) this.speciesConfig = PET_SPECIES[speciesId] // 計算戰鬥數值 this.calculateCombatStats() return this.state } } // 創建初始狀態 createInitialState(speciesId) { const config = PET_SPECIES[speciesId] const state = { speciesId, stage: 'egg', hunger: 100, happiness: 100, health: 100, weight: 500, ageSeconds: 0, poopCount: 0, str: 10, int: 10, dex: 10, luck: config.baseStats.luck || 10, isSleeping: false, isSick: false, isDead: false, dyingSeconds: 0, // 瀕死計時 currentDeityId: 'mazu', deityFavors: { mazu: 0, earthgod: 0, yuelao: 0, wenchang: 0, guanyin: 0 }, dailyPrayerCount: 0, destiny: null, buffs: [], inventory: [], generation: 1, lastTickTime: Date.now() } // 分配命格 this.assignDestiny(state) // 注意:不在這裡計算戰鬥數值,因為此時 speciesConfig 可能還沒設置 // calculateCombatStats 會在 initialize 之後調用 return state } // 分配命格 assignDestiny(state) { // 隨機選擇一個命格 const fateIndex = Math.floor(Math.random() * FATES.length) state.destiny = FATES[fateIndex] console.log(`🎲 命格分配: ${state.destiny.name} - ${state.destiny.description}`) console.log(' 加成:', state.destiny.buffs) // 應用命格初始加成 (如果是直接加數值的) if (state.destiny.buffs.luck) { state.luck += state.destiny.buffs.luck console.log(` 運勢加成: +${state.destiny.buffs.luck} -> ${state.luck}`) } } // 獲取所有加成(命格 + 神明基礎 + 神明好感度等級 + 神明滿級 + Buff) getAllBonuses() { const bonuses = {} // 1. 命格加成 if (this.state.destiny && this.state.destiny.buffs) { for (const [key, value] of Object.entries(this.state.destiny.buffs)) { bonuses[key] = (bonuses[key] || 0) + value } } // 2. 神明基礎加成 if (this.state.currentDeityId) { const deity = DEITIES.find(d => d.id === this.state.currentDeityId) if (deity && deity.buffs) { for (const [key, value] of Object.entries(deity.buffs)) { bonuses[key] = (bonuses[key] || 0) + value } } // 3. 神明好感度等級加成 if (deity && deity.favorLevelBuffs) { const favor = this.state.deityFavors?.[this.state.currentDeityId] || 0 const level = Math.floor(favor / deity.favorLevelBuffs.interval) if (level > 0 && deity.favorLevelBuffs.buffsPerLevel) { for (const [key, valuePerLevel] of Object.entries(deity.favorLevelBuffs.buffsPerLevel)) { bonuses[key] = (bonuses[key] || 0) + (valuePerLevel * level) } } } // 4. 神明滿級特殊 Buff(好感度 = 100) if (deity && deity.maxFavorBuff) { const favor = this.state.deityFavors?.[this.state.currentDeityId] || 0 if (favor >= 100 && deity.maxFavorBuff.effects) { for (const [key, value] of Object.entries(deity.maxFavorBuff.effects)) { bonuses[key] = (bonuses[key] || 0) + value } } } } return bonuses } // 獲取最大健康值(100 + health加成) getMaxHealth() { const bonuses = this.getAllBonuses() return 100 + (bonuses.health || 0) } // 獲取體重狀態 getWeightStatus() { if (!this.speciesConfig || !this.state) return 'unknown' const currentStageConfig = this.speciesConfig.lifecycle.find(s => s.stage === this.state.stage) if (!currentStageConfig || !currentStageConfig.weightRange) return 'unknown' const { min, max } = currentStageConfig.weightRange const weight = this.state.weight if (weight < min) return 'underweight' if (weight > max) return 'overweight' return 'normal' } // 檢查當前階段是否允許某個動作(資料驅動) isActionAllowed(action) { if (!this.speciesConfig || !this.state) return false const currentStageConfig = this.speciesConfig.lifecycle.find(s => s.stage === this.state.stage) if (!currentStageConfig) return false const allowedActions = currentStageConfig.allowedActions || [] return allowedActions.includes(action) } // 檢查當前階段是否啟用某個系統(資料驅動) isSystemEnabled(system) { if (!this.speciesConfig || !this.state) return true const currentStageConfig = this.speciesConfig.lifecycle.find(s => s.stage === this.state.stage) if (!currentStageConfig || !currentStageConfig.enabledSystems) return true return currentStageConfig.enabledSystems[system] !== false } // 檢查當前時間是否在睡眠時段 isInSleepTime() { if (!this.speciesConfig?.baseStats?.sleepSchedule) return null const now = new Date() const currentHour = now.getHours() const currentMinute = now.getMinutes() const currentTimeInMinutes = currentHour * 60 + currentMinute const schedule = this.speciesConfig.baseStats.sleepSchedule // 檢查夜間睡眠 (21:30 - 08:00) if (schedule.nightSleep && schedule.nightSleep.autoSleep) { const startMinutes = schedule.nightSleep.startHour * 60 + schedule.nightSleep.startMinute const endMinutes = schedule.nightSleep.endHour * 60 + schedule.nightSleep.endMinute // 處理跨午夜的情況 if (startMinutes > endMinutes) { // 例如 21:30 (1290分) 到 08:00 (480分) if (currentTimeInMinutes >= startMinutes || currentTimeInMinutes < endMinutes) { return 'nightSleep' } } else { if (currentTimeInMinutes >= startMinutes && currentTimeInMinutes < endMinutes) { return 'nightSleep' } } } // 檢查午休 (12:00 - 13:00) if (schedule.noonNap && schedule.noonNap.autoSleep) { const startMinutes = schedule.noonNap.startHour * 60 + schedule.noonNap.startMinute const endMinutes = schedule.noonNap.endHour * 60 + schedule.noonNap.endMinute if (currentTimeInMinutes >= startMinutes && currentTimeInMinutes < endMinutes) { return 'noonNap' } } return null } // 獲取睡眠時段配置 getSleepPeriod(periodName) { if (!this.speciesConfig?.baseStats?.sleepSchedule) return null return this.speciesConfig.baseStats.sleepSchedule[periodName] } // 計算戰鬥數值 calculateCombatStats(state = this.state) { if (!state || !this.speciesConfig) return // 1. 獲取所有加成 const bonuses = this.getAllBonuses() // 2. 計算有效屬性 (基礎 + 加成) const effectiveStr = state.str + (bonuses.str || 0) const effectiveInt = state.int + (bonuses.int || 0) const effectiveDex = state.dex + (bonuses.dex || 0) const effectiveLuck = (state.luck || 0) + (bonuses.luck || 0) // 3. 獲取百分比加成 (Modifiers) const atkMod = 1 + (bonuses.attack || 0) const defMod = 1 + (bonuses.defense || 0) const spdMod = 1 + (bonuses.speed || 0) // 4. 從配置讀取戰鬥數值計算系數 const formulas = this.speciesConfig.baseStats.combatFormulas || { attack: { strMultiplier: 2.5, dexMultiplier: 0.5 }, defense: { strMultiplier: 1.0, intMultiplier: 2.0 }, speed: { dexMultiplier: 3.0, intMultiplier: 0.5 } } // 5. 計算最終戰鬥屬性 state.attack = (effectiveStr * formulas.attack.strMultiplier + effectiveDex * formulas.attack.dexMultiplier) * atkMod state.defense = (effectiveStr * formulas.defense.strMultiplier + effectiveInt * formulas.defense.intMultiplier) * defMod state.speed = (effectiveDex * formulas.speed.dexMultiplier + effectiveInt * formulas.speed.intMultiplier) * spdMod // 保存有效屬性到 state (供 UI 顯示) state.effectiveStr = effectiveStr state.effectiveInt = effectiveInt state.effectiveDex = effectiveDex state.effectiveLuck = effectiveLuck // 根據當前階段設定身高(每個階段固定) const currentStageConfig = this.speciesConfig.lifecycle.find(s => s.stage === state.stage) if (currentStageConfig && currentStageConfig.height) { state.height = currentStageConfig.height } else if (!state.height) { state.height = this.speciesConfig.baseStats.defaultHeight || 10 } // 體重:如果沒有初始化,使用階段基礎體重 if (!state.weight && currentStageConfig && currentStageConfig.baseWeight) { state.weight = currentStageConfig.baseWeight } else if (!state.weight) { state.weight = this.speciesConfig.baseStats.defaultWeight || 500 } } // 更新狀態(同步到 API) async updateState(updates) { this.state = { ...this.state, ...updates } try { await this.api.updatePetState(updates) } catch (error) { console.warn('[PetSystem] API 更新失敗,使用本地狀態:', error) } return this.state } // 獲取當前狀態 getState() { return { ...this.state } } // 刪除寵物 async deletePet() { try { // 停止所有循環 this.stopTickLoop() // 從 API 刪除 await this.api.deletePetState() // 重置狀態 this.state = null this.speciesConfig = null return { success: true, message: '寵物已刪除' } } catch (error) { console.error('[PetSystem] 刪除寵物失敗:', error) // 即使 API 失敗,也清除本地狀態 this.state = null this.speciesConfig = null return { success: true, message: '寵物已刪除(本地)' } } } // Tick 循環(生理系统 - 从配置读取间隔) startTickLoop(callback) { if (this.tickInterval) this.stopTickLoop() // 从配置读取间隔时间 const interval = this.speciesConfig?.baseStats?.physiologyTickInterval || 60000 this.tickInterval = setInterval(async () => { await this.tick() if (callback) callback(this.getState()) }, interval) } stopTickLoop() { if (this.tickInterval) { clearInterval(this.tickInterval) this.tickInterval = null } } // 單次 Tick 執行 async tick() { if (!this.state || this.state.isDead) return const now = Date.now() const deltaTime = (now - (this.state.lastTickTime || now)) / 1000 this.state.lastTickTime = now // 年齡增長 this.state.ageSeconds += deltaTime // 檢查階段轉換 this.checkStageTransition() // 檢查自動睡眠(基於真實時間) if (this.isSystemEnabled('sleep')) { const sleepPeriod = this.isInSleepTime() if (sleepPeriod && !this.state.isSleeping) { // 在睡眠時段且未睡覺,自動進入睡眠 this.state.isSleeping = true const periodConfig = this.getSleepPeriod(sleepPeriod) const periodName = sleepPeriod === 'nightSleep' ? '夜間睡眠' : '午休' console.log(`😴 ${periodName}時間,寵物自動進入睡眠`) } else if (!sleepPeriod && this.state.isSleeping && this.state._autoSlept) { // 不在睡眠時段且是自動睡眠狀態,自動醒來 this.state.isSleeping = false this.state._autoSlept = false console.log(`⏰ 睡眠時間結束,寵物自動醒來`) } } // 根據當前階段配置決定啟用哪些系統(資料驅動) const config = this.speciesConfig.baseStats // 睡眠狀態下的衰減倍率(從配置讀取) const sleepDecayMultiplier = this.state.isSleeping ? (config.sleepDecayMultiplier || 0.1) : 1.0 // 獲取加成(用於檢查免疫) const bonuses = this.getAllBonuses() const hasImmunity = bonuses.sicknessImmune // 妈祖满级等 // 飢餓系統 if (this.isSystemEnabled('hunger')) { this.state.hunger = Math.max(0, this.state.hunger - config.hungerDecayPerTick * sleepDecayMultiplier) // 飢餓過度扣血(有免疫則跳過) if (!hasImmunity && this.state.hunger <= 0) { const damage = config.hungerHealthDamage || 1 this.state.health = Math.max(0, this.state.health - damage) if (damage > 0) console.log(`📉 飢餓扣除健康: -${damage}`) } } // 快樂系統 if (this.isSystemEnabled('happiness')) { this.state.happiness = Math.max(0, this.state.happiness - config.happinessDecayPerTick * sleepDecayMultiplier) } // 便便系統(睡覺時不會拉屎) if (this.isSystemEnabled('poop') && !this.state.isSleeping) { if (Math.random() < config.poopChancePerTick) { const maxPoop = config.maxPoopCount || 4 this.state.poopCount = Math.min(maxPoop, this.state.poopCount + 1) } } // 便便扣健康(有免疫則跳過) if (!hasImmunity && this.isSystemEnabled('poop') && this.state.poopCount > 0) { const damage = (config.poopHealthDamage || 0.5) * this.state.poopCount this.state.health = Math.max(0, this.state.health - damage) if (damage > 0) console.log(`📉 便便扣除健康: -${damage} (數量: ${this.state.poopCount})`) } // 生病系統 if (this.isSystemEnabled('sickness')) { // 健康過低導致生病(從配置讀取閾值) const threshold = config.sicknessThreshold || 60 // 如果有免疫生病 Buff,則不會生病 if (!hasImmunity && !this.state.isSick && this.state.health < threshold) { this.state.isSick = true console.log(`🤢 健康低於 ${threshold},寵物生病了`) } } // 死亡檢查(從配置讀取瀕死時間) const dyingTime = config.dyingTimeSeconds || 1800 if (this.state.health <= 0) { this.state.dyingSeconds = (this.state.dyingSeconds || 0) + deltaTime // 每 60 秒提示一次 if (Math.floor(this.state.dyingSeconds) % 60 === 0) { const remaining = dyingTime - this.state.dyingSeconds console.log(`⚠️ 寵物瀕死中!剩餘時間: ${(remaining / 60).toFixed(1)} 分鐘`) } if (this.state.dyingSeconds >= dyingTime) { this.state.isDead = true console.log('💀 寵物死亡') await this.updateState({ isDead: true }) } } else { // 健康恢復,重置瀕死計時 if (this.state.dyingSeconds > 0) { this.state.dyingSeconds = 0 console.log('✨ 寵物脫離瀕死狀態') } } // 重新计算属性(含加成) this.calculateCombatStats() // 同步到 API await this.updateState({ // 基礎屬性 ageSeconds: this.state.ageSeconds, stage: this.state.stage, hunger: this.state.hunger, happiness: this.state.happiness, health: this.state.health, weight: this.state.weight, height: this.state.height, // 能力值 str: this.state.str, int: this.state.int, dex: this.state.dex, luck: this.state.luck, // 有效能力值 (含加成) effectiveStr: this.state.effectiveStr, effectiveInt: this.state.effectiveInt, effectiveDex: this.state.effectiveDex, effectiveLuck: this.state.effectiveLuck, // 狀態 poopCount: this.state.poopCount, isSleeping: this.state.isSleeping, isSick: this.state.isSick, isDead: this.state.isDead, dyingSeconds: this.state.dyingSeconds, // 戰鬥數值 attack: this.state.attack, defense: this.state.defense, speed: this.state.speed }) } // Debug: 直接設置屬性 async debugSetStat(stat, value) { if (!this.state) return console.log(`[Debug] 設置 ${stat} = ${value}`) await this.updateState({ [stat]: value }) // 如果修改的是戰鬥相關屬性,重新計算 if (['str', 'int', 'dex', 'weight'].includes(stat)) { this.calculateCombatStats() } return this.state } // 檢查階段轉換 checkStageTransition() { if (!this.speciesConfig || !this.state) return const config = this.speciesConfig const currentStage = this.state.stage const ageSeconds = this.state.ageSeconds // 找到當前階段 const currentIndex = config.lifecycle.findIndex(s => s.stage === currentStage) if (currentIndex < 0 || currentIndex >= config.lifecycle.length - 1) { return // 找不到或已是最終階段 } const currentStageConfig = config.lifecycle[currentIndex] const nextStage = config.lifecycle[currentIndex + 1] // 檢查時間條件:年齡是否超過當前階段的持續時間 const timeConditionMet = ageSeconds >= currentStageConfig.durationSeconds && currentStageConfig.durationSeconds > 0 // 檢查屬性條件 let statsConditionMet = true const missingStats = [] if (nextStage.conditions) { if (nextStage.conditions.str && this.state.str < nextStage.conditions.str) { statsConditionMet = false missingStats.push(`STR ${this.state.str.toFixed(1)}/${nextStage.conditions.str}`) } if (nextStage.conditions.int && this.state.int < nextStage.conditions.int) { statsConditionMet = false missingStats.push(`INT ${this.state.int.toFixed(1)}/${nextStage.conditions.int}`) } if (nextStage.conditions.dex && this.state.dex < nextStage.conditions.dex) { statsConditionMet = false missingStats.push(`DEX ${this.state.dex.toFixed(1)}/${nextStage.conditions.dex}`) } } if (timeConditionMet && statsConditionMet) { console.log(`\n✨ 進化!${currentStage} → ${nextStage.stage} (年齡: ${ageSeconds.toFixed(1)}秒)`) this.state.stage = nextStage.stage this.state._evolutionWarned = false // 重置警告狀態 this.updateState({ stage: nextStage.stage }) } else if (timeConditionMet && !statsConditionMet) { // 時間到了但屬性不足,只在第一次提示 if (!this.state._evolutionWarned) { console.log(`⚠️ 年齡已達到 (${ageSeconds.toFixed(1)}秒),但屬性不足以進化到 ${nextStage.stage}`) console.log(` 需要: ${missingStats.join(', ')}`) this.state._evolutionWarned = true } } } // 餵食 async feed(amount = 12) { if (!this.isActionAllowed('feed')) return { success: false, message: '當前階段不能餵食' } if (this.state.isDead) return { success: false, message: '寵物已死亡' } if (this.state.isSleeping) return { success: false, message: '寵物正在睡覺,無法餵食' } if (this.state.hunger >= 100) return { success: false, message: '寵物已經吃飽了' } const newHunger = Math.min(100, this.state.hunger + amount) // 體重隨機變化 ±10% const baseWeightChange = amount * 0.5 const randomFactor = 0.9 + Math.random() * 0.2 // 0.9 ~ 1.1 const weightChange = baseWeightChange * randomFactor const newWeight = this.state.weight + weightChange // 應用命格的力量成長加成 const bonuses = this.getAllBonuses() const strGainBonus = bonuses.strGain || 0 const strGain = 0.3 * (1 + strGainBonus) // 降低成長速度 if (strGainBonus > 0) { console.log(`[餵食] 力量成長加成: ${(strGainBonus * 100).toFixed(0)}% -> +${strGain.toFixed(2)} STR`) } // 自然成長上限為 100 const currentStr = this.state.str const newStr = currentStr < 100 ? Math.min(100, currentStr + strGain) : currentStr await this.updateState({ hunger: newHunger, weight: newWeight, str: newStr }) this.calculateCombatStats() return { success: true, hunger: newHunger, weight: newWeight, strGain, weightChange } } // 玩耍 async play(options = {}) { if (!this.isActionAllowed('play')) return { success: false, message: '當前階段不能玩耍' } if (this.state.isDead || this.state.isSleeping) { return { success: false, message: '寵物無法玩耍' } } // 檢查飢餓度 if (this.state.hunger <= 0) { return { success: false, message: '寵物太餓了,沒力氣玩耍' } } // 可以傳入 { amount: 10, gameType: 'training' | 'puzzle' | 'normal' } const amount = options.amount || options || 10 // 向後兼容舊的調用方式 const gameType = options.gameType || 'normal' // 應用命格和神明的屬性成長加成 const bonuses = this.getAllBonuses() const happinessBonus = bonuses.happinessRecovery || 0 const dexBonus = bonuses.dexGain || 0 const intBonus = bonuses.intGain || 0 const happinessGain = amount * (1 + happinessBonus) const dexGain = 0.3 * (1 + dexBonus) // 降低成長速度 const intGain = 0.15 * (1 + intBonus) // 降低成長速度 // 體重變化根據遊戲類型,並加入隨機 ±10% let baseWeightChange = 0 let gameTypeLabel = '' if (gameType === 'training') { // 訓練類型:消耗體力,減重 baseWeightChange = -3 gameTypeLabel = '🏃 訓練' } else if (gameType === 'puzzle') { // 益智類型:不影響體重 baseWeightChange = 0 gameTypeLabel = '🧩 益智' } else { // 一般玩耍:輕微減重 baseWeightChange = -1 gameTypeLabel = '🎮 玩耍' } // 添加隨機波動 ±10%(除了益智類型) const randomFactor = baseWeightChange !== 0 ? (0.9 + Math.random() * 0.2) : 0 const weightChange = baseWeightChange * randomFactor // 顯示加成細節 if (happinessBonus > 0 || dexBonus > 0 || intBonus > 0) { // 分別計算命格和神明的加成 let fateBonus = 0 let deityBonus = 0 if (this.state.destiny?.buffs?.happinessRecovery) fateBonus += this.state.destiny.buffs.happinessRecovery const deity = DEITIES.find(d => d.id === this.state.currentDeityId) if (deity?.buffs?.happinessRecovery) deityBonus += deity.buffs.happinessRecovery console.log(`[${gameTypeLabel}] 快樂加成: 命格${(fateBonus * 100).toFixed(0)}% + 神明${(deityBonus * 100).toFixed(0)}% = ${(happinessBonus * 100).toFixed(0)}% | DEX${(dexBonus * 100).toFixed(0)}% INT${(intBonus * 100).toFixed(0)}%`) } const newHappiness = Math.min(100, this.state.happiness + happinessGain) // 自然成長上限為 100 const currentDex = this.state.dex const currentInt = this.state.int const newDex = currentDex < 100 ? Math.min(100, currentDex + dexGain) : currentDex const newInt = currentInt < 100 ? Math.min(100, currentInt + intGain) : currentInt const newWeight = Math.max(50, this.state.weight + weightChange) // 最低50g const hungerCost = this.speciesConfig.baseStats.playHungerCost || 1 const newHunger = Math.max(0, this.state.hunger - hungerCost) // 玩耍消耗 3 點飢餓 await this.updateState({ happiness: newHappiness, hunger: newHunger, dex: newDex, int: newInt, weight: newWeight }) this.calculateCombatStats() return { success: true, happiness: newHappiness, happinessGain, dexGain, intGain, weightChange, gameType: gameTypeLabel } } // 清理便便 async cleanPoop() { if (!this.isActionAllowed('clean')) return { success: false, message: '當前階段不需要清理' } if (this.state.poopCount === 0) { return { success: false, message: '沒有便便需要清理' } } const newPoopCount = 0 const newHappiness = Math.min(100, this.state.happiness + 10) await this.updateState({ poopCount: newPoopCount, happiness: newHappiness }) return { success: true, poopCount: newPoopCount, happiness: newHappiness } } // 治療 async heal(amount = 20) { if (!this.isActionAllowed('heal')) return { success: false, message: '當前階段不需要治療' } if (this.state.isDead) return { success: false, message: '寵物已死亡' } if (this.state.isSleeping) return { success: false, message: '寵物正在睡覺,無法治療' } const maxHealth = this.getMaxHealth() if (this.state.health >= maxHealth) return { success: false, message: '寵物非常健康,不需要治療' } // 應用健康恢復加成 const bonuses = this.getAllBonuses() const healAmount = amount * (1 + (bonuses.healthRecovery || 0)) const newHealth = Math.min(maxHealth, this.state.health + healAmount) const wasSick = this.state.isSick await this.updateState({ health: newHealth, isSick: false }) return { success: true, health: newHealth, isSick: false, cured: wasSick && !this.state.isSick, healAmount } } // 睡覺/起床 async toggleSleep() { if (!this.isActionAllowed('sleep')) return { success: false, message: '當前階段不能睡覺' } if (this.state.isDead) return { success: false, message: '寵物已死亡' } const newIsSleeping = !this.state.isSleeping const healthChange = newIsSleeping ? 5 : 0 // 檢查是否在睡眠時段 const sleepPeriod = this.isInSleepTime() let message = '' let willRandomSleep = false if (newIsSleeping) { // 進入睡眠 this.state._autoSlept = false // 標記為手動睡眠 message = '寵物進入睡眠' } else { // 嘗試醒來 if (sleepPeriod) { // 在睡眠時段醒來,可能會隨機再次入睡 const periodConfig = this.getSleepPeriod(sleepPeriod) const randomWakeChance = periodConfig?.randomWakeChance || 0 if (Math.random() < randomWakeChance) { // 隨機再次入睡 willRandomSleep = true this.state._autoSlept = true const periodName = sleepPeriod === 'nightSleep' ? '夜間' : '午休' message = `寵物醒來後打了個哈欠,在${periodName}時段又睡著了...` // 延遲一下再設回睡眠狀態(給用戶看到醒來的訊息) setTimeout(async () => { if (this.state && !this.state.isDead) { this.state.isSleeping = true await this.updateState({ isSleeping: true, _autoSlept: true }) } }, 100) } else { message = '寵物醒來了' } } else { message = '寵物醒來了' } } const maxHealth = this.getMaxHealth() await this.updateState({ isSleeping: willRandomSleep ? true : newIsSleeping, health: Math.min(maxHealth, this.state.health + healthChange), _autoSlept: willRandomSleep ? true : (newIsSleeping ? false : undefined) }) return { success: true, isSleeping: willRandomSleep ? true : newIsSleeping, message, randomSleep: willRandomSleep } } }