// 寵物系統核心 - 與 API 整合 import { apiService } from './api-service.js' import { PET_SPECIES } from '../data/pet-species.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] return this.state } catch (error) { console.error('[PetSystem] 初始化失敗:', error) // 降級到本地狀態 this.state = this.createInitialState(speciesId) this.speciesConfig = PET_SPECIES[speciesId] return this.state } } // 創建初始狀態 createInitialState(speciesId) { const config = PET_SPECIES[speciesId] return { speciesId, stage: 'baby', hunger: 100, happiness: 100, health: 100, weight: 500, ageSeconds: 0, poopCount: 0, str: 0, int: 0, dex: 0, luck: config.baseStats.luck || 10, isSleeping: false, isSick: false, isDead: false, currentDeityId: 'mazu', deityFavors: { mazu: 0, earthgod: 0, yuelao: 0, wenchang: 0, guanyin: 0 }, dailyPrayerCount: 0, destiny: null, buffs: [], inventory: [], generation: 1, lastTickTime: Date.now() } } // 更新狀態(同步到 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 循環(每 3 秒) startTickLoop(callback) { if (this.tickInterval) this.stopTickLoop() this.tickInterval = setInterval(async () => { await this.tick() if (callback) callback(this.getState()) }, 3000) } 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() // 基礎數值衰減 const config = this.speciesConfig.baseStats this.state.hunger = Math.max(0, this.state.hunger - config.hungerDecayPerTick * 100) this.state.happiness = Math.max(0, this.state.happiness - config.happinessDecayPerTick * 100) // 便便機率 if (Math.random() < config.poopChancePerTick) { this.state.poopCount = Math.min(4, this.state.poopCount + 1) } // 生病機率 if (!this.state.isSick && Math.random() < config.sicknessChance) { this.state.isSick = true await this.updateState({ isSick: true }) } // 健康檢查 if (this.state.health <= 0) { this.state.isDead = true await this.updateState({ isDead: true }) } // 同步到 API await this.updateState({ ageSeconds: this.state.ageSeconds, hunger: this.state.hunger, happiness: this.state.happiness, poopCount: this.state.poopCount, isSick: this.state.isSick, isDead: this.state.isDead }) } // 檢查階段轉換 checkStageTransition() { const config = this.speciesConfig const currentStage = this.state.stage const ageSeconds = this.state.ageSeconds for (const stageConfig of config.lifecycle) { if (stageConfig.stage === currentStage) { // 找到下一個階段 const currentIndex = config.lifecycle.findIndex(s => s.stage === currentStage) if (currentIndex < config.lifecycle.length - 1) { const nextStage = config.lifecycle[currentIndex + 1] if (ageSeconds >= nextStage.durationSeconds && nextStage.durationSeconds > 0) { this.state.stage = nextStage.stage this.updateState({ stage: nextStage.stage }) } } break } } } // 餵食 async feed(amount = 20) { if (this.state.isDead) return { success: false, message: '寵物已死亡' } const newHunger = Math.min(100, this.state.hunger + amount) const newWeight = this.state.weight + (amount * 0.5) await this.updateState({ hunger: newHunger, weight: newWeight }) return { success: true, hunger: newHunger, weight: newWeight } } // 玩耍 async play(amount = 15) { if (this.state.isDead || this.state.isSleeping) { return { success: false, message: '寵物無法玩耍' } } const newHappiness = Math.min(100, this.state.happiness + amount) const newDex = this.state.dex + 0.5 await this.updateState({ happiness: newHappiness, dex: newDex }) return { success: true, happiness: newHappiness, dex: newDex } } // 清理便便 async cleanPoop() { 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.state.isDead) return { success: false, message: '寵物已死亡' } const newHealth = Math.min(100, this.state.health + amount) const wasSick = this.state.isSick await this.updateState({ health: newHealth, isSick: false }) return { success: true, health: newHealth, isSick: false, cured: wasSick && !this.state.isSick } } // 睡覺/起床 async toggleSleep() { if (this.state.isDead) return { success: false, message: '寵物已死亡' } const newIsSleeping = !this.state.isSleeping const healthChange = newIsSleeping ? 5 : 0 await this.updateState({ isSleeping: newIsSleeping, health: Math.min(100, this.state.health + healthChange) }) return { success: true, isSleeping: newIsSleeping } } }