pet_data/core/temple-system.js

347 lines
9.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 神明系統 - 與 API 整合
import { apiService } from './api-service.js'
import { JIAOBEI_CONFIG } from '../data/jiaobei-config.js'
export class TempleSystem {
constructor(petSystem, api = apiService, achievementSystem = null) {
this.petSystem = petSystem
this.api = api
this.achievementSystem = achievementSystem
this.deities = []
}
// 初始化(從 API 載入神明資料)
async initialize() {
try {
this.deities = await this.api.getDeities()
console.log(`[TempleSystem] 載入 ${this.deities.length} 位神明`)
} catch (error) {
console.error('[TempleSystem] 載入神明失敗:', error)
// 降級到本地載入
const { DEITIES } = await import('../data/deities.js')
this.deities = DEITIES
}
}
// 獲取所有神明
getDeities() {
return [...this.deities]
}
// 獲取當前神明
getCurrentDeity() {
const state = this.petSystem.getState()
return this.deities.find(d => d.id === state.currentDeityId) || this.deities[0]
}
// 切換神明
async switchDeity(deityId) {
const deity = this.deities.find(d => d.id === deityId)
if (!deity) {
return { success: false, message: '找不到該神明' }
}
await this.petSystem.updateState({ currentDeityId: deityId })
// 重新計算屬性(新神明的加成)
this.petSystem.calculateCombatStats()
// 同步 effective 属性到状态
await this.petSystem.updateState({
effectiveStr: this.petSystem.state.effectiveStr,
effectiveInt: this.petSystem.state.effectiveInt,
effectiveDex: this.petSystem.state.effectiveDex,
effectiveLuck: this.petSystem.state.effectiveLuck
})
return { success: true, deity }
}
// 祈福(每日上限 3 次)
async pray() {
const state = this.petSystem.getState()
if (state.dailyPrayerCount >= 3) {
return { success: false, message: '今日祈福次數已用完' }
}
try {
const result = await this.api.prayToDeity({
deityId: state.currentDeityId,
petState: state
})
// 更新好感度
const currentFavor = state.deityFavors[state.currentDeityId] || 0
const newFavor = Math.min(100, currentFavor + result.favorIncrease)
// 檢查是否等級提升或達到滿級
const deity = this.getCurrentDeity()
const oldLevel = deity.favorLevelBuffs ? Math.floor(currentFavor / deity.favorLevelBuffs.interval) : 0
const newLevel = deity.favorLevelBuffs ? Math.floor(newFavor / deity.favorLevelBuffs.interval) : 0
const levelUp = newLevel > oldLevel
const reachedMax = currentFavor < 100 && newFavor >= 100
await this.petSystem.updateState({
deityFavors: {
...state.deityFavors,
[state.currentDeityId]: newFavor
},
dailyPrayerCount: state.dailyPrayerCount + 1
})
// 重新計算屬性(好感度變化影響加成)
this.petSystem.calculateCombatStats()
// 同步 effective 属性到状态
await this.petSystem.updateState({
effectiveStr: this.petSystem.state.effectiveStr,
effectiveInt: this.petSystem.state.effectiveInt,
effectiveDex: this.petSystem.state.effectiveDex,
effectiveLuck: this.petSystem.state.effectiveLuck
})
// 獲取神明對話
const dialogue = deity.dialogues[Math.floor(Math.random() * deity.dialogues.length)]
// 記錄到成就系統
if (this.achievementSystem) {
await this.achievementSystem.recordAction('pray')
// 檢查神明好感度成就
await this.achievementSystem.checkAndUnlockAchievements()
}
return {
success: true,
favorIncrease: result.favorIncrease,
newFavor,
oldLevel,
newLevel,
levelUp,
reachedMax,
dialogue,
message: result.message,
deity
}
} catch (error) {
console.error('[TempleSystem] 祈福失敗:', error)
return { success: false, message: '祈福失敗' }
}
}
// 獲取好感度星級(每 20 點一星)
getFavorStars(deityId) {
if (!deityId) return '☆☆☆☆☆'
const state = this.petSystem.getState()
if (!state || !state.deityFavors) return '☆☆☆☆☆'
const favor = state.deityFavors[deityId] || 0
const stars = Math.floor(favor / 20)
return '★'.repeat(stars) + '☆'.repeat(5 - stars)
}
// 抽籤
// 求籤(需要三聖筊驗證)
async drawLot(lotType = 'guanyin_100') {
const state = this.petSystem.getState()
const deity = this.getCurrentDeity()
// 檢查神明是否支持此簽詩
if (!deity.lotTypes || !deity.lotTypes.includes(lotType)) {
return {
success: false,
message: `${deity.name}不提供${lotType}簽詩`
}
}
try {
// 載入簽詩資料
const lots = await this.loadLots(lotType)
// 隨機抽一支簽
const randomIndex = Math.floor(Math.random() * lots.length)
const lot = lots[randomIndex]
// 記錄到成就系統
if (this.achievementSystem) {
await this.achievementSystem.recordAction('drawFortune')
await this.achievementSystem.checkAndUnlockAchievements()
}
// 返回需要擲筊驗證的狀態
return {
success: true,
needVerification: true,
lot,
lotType,
deity: deity.name,
verificationCount: 0,
requiredHoly: 3 // 需要三個聖筊
}
} catch (error) {
console.error('[TempleSystem] 抽籤失敗:', error)
return { success: false, message: '抽籤失敗' }
}
}
// 驗證簽詩(擲筊確認)
async verifyLot(lotData) {
// 擲筊
const jiaobeiResult = await this.throwJiaobei(`求問第${lotData.lot.no}`)
if (jiaobeiResult.result === 'holy') {
// 聖筊
const newCount = (lotData.verificationCount || 0) + 1
if (newCount >= lotData.requiredHoly) {
// 三聖筊,可以解簽
return {
success: true,
verified: true,
lot: lotData.lot,
jiaobeiResult,
message: `三聖筊!${lotData.deity}允准解籤`
}
} else {
// 還需要更多聖筊
return {
success: true,
verified: false,
needMore: true,
verificationCount: newCount,
requiredHoly: lotData.requiredHoly,
lot: lotData.lot,
jiaobeiResult,
message: `${newCount}個聖筊,還需${lotData.requiredHoly - newCount}個聖筊`
}
}
} else {
// 笑筊或陰筊,需要重抽
return {
success: true,
verified: false,
needRedraw: true,
jiaobeiResult,
message: `${jiaobeiResult.result === 'laughing' ? '笑筊' : '陰筊'},請重新抽籤`
}
}
}
// 載入簽詩資料
async loadLots(lotType) {
if (lotType === 'guanyin_100') {
const data = await import('../data/guanyin_100_lots.json')
return data.default || data
}
throw new Error(`未知的簽詩類型: ${lotType}`)
}
// 擲筊
async throwJiaobei(question = '') {
const state = this.petSystem.getState()
const deity = this.getCurrentDeity()
try {
// 計算實際概率
const probabilities = this.calculateJiaobeiProbabilities()
// 嘗試使用 API
const apiResult = await this.api.throwJiaobei({
petId: state.id,
deityId: deity.id,
question,
probabilities
})
// 如果 API 回傳本地降級標記,使用本地邏輯
if (!apiResult.localFallback) {
return apiResult
}
} catch (error) {
console.warn('[TempleSystem] 擲筊 API 失敗,使用本地邏輯', error)
}
// 本地邏輯
const probabilities = this.calculateJiaobeiProbabilities()
const result = this.rollJiaobei(probabilities)
return {
success: true,
result,
deity: deity.name,
message: result === 'holy' ? '聖筊' : result === 'laughing' ? '笑筊' : '陰筊',
probabilities
}
}
// 取得當前神明可用的 lotTypes可能有多個
getCurrentDeityLotTypes() {
const deity = this.getCurrentDeity()
// 若未設定則回傳空陣列,避免錯誤
return deity?.lotTypes ?? []
}
// 計算擲筊概率(考慮運勢和好感度)
calculateJiaobeiProbabilities() {
const state = this.petSystem.getState()
const deity = this.getCurrentDeity()
// 基礎概率
let { holy, laughing, negative } = JIAOBEI_CONFIG.baseProbability
// 運勢影響:增加聖筊概率
const luck = state.luck || 10
const luckBonus = Math.min(
luck * JIAOBEI_CONFIG.luckModifier,
JIAOBEI_CONFIG.maxModifier
)
// 好感度影響:減少陰筊概率
const favor = state.deityFavors[deity.id] || 0
const favorBonus = Math.min(
favor * JIAOBEI_CONFIG.favorModifier,
JIAOBEI_CONFIG.maxModifier
)
// 調整概率
holy += luckBonus + favorBonus / 2
negative -= favorBonus
laughing -= luckBonus / 2
// 確保非負
holy = Math.max(0.1, holy)
laughing = Math.max(0.1, laughing)
negative = Math.max(0.1, negative)
// 歸一化確保總和為1
const total = holy + laughing + negative
return {
holy: holy / total,
laughing: laughing / total,
negative: negative / total
}
}
// 投擲筊杯(隨機結果)
rollJiaobei(probabilities) {
const rand = Math.random()
if (rand < probabilities.holy) {
return 'holy'
} else if (rand < probabilities.holy + probabilities.laughing) {
return 'laughing'
} else {
return 'negative'
}
}
// Debug: 重置每日祈福次數
async debugResetDailyPrayer() {
console.log('[Debug] 重置每日祈福次數')
await this.petSystem.updateState({ dailyPrayerCount: 0 })
return { success: true, message: '已重置祈福次數' }
}
}