pet_data/core/pet-system.js

287 lines
7.3 KiB
JavaScript
Raw Normal View History

2025-11-23 18:03:56 +00:00
// 寵物系統核心 - 與 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 }
}
}