核心系统: - combatSystem: 战斗逻辑、伤害计算、战斗状态管理 - skillSystem: 技能系统、技能解锁、经验值、里程碑 - taskSystem: 任务系统、任务类型、任务执行和完成 - eventSystem: 事件系统、随机事件处理 - environmentSystem: 环境系统、时间流逝、区域效果 - levelingSystem: 升级系统、属性成长 - soundSystem: 音效系统 配置文件: - enemies: 敌人配置、掉落表 - events: 事件配置、事件效果 - items: 物品配置、装备属性 - locations: 地点配置、探索事件 - skills: 技能配置、技能树 UI组件: - CraftingDrawer: 制造界面 - InventoryDrawer: 背包界面 - 其他UI优化和动画 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
379 lines
12 KiB
JavaScript
379 lines
12 KiB
JavaScript
/**
|
||
* 事件配置
|
||
* Phase 6 核心系统实现
|
||
*/
|
||
|
||
import { LOCATION_CONFIG } from './locations.js'
|
||
|
||
/**
|
||
* 事件配置
|
||
* 每个事件包含:
|
||
* - id: 事件唯一标识
|
||
* - type: 事件类型 (story/tips/unlock/dialogue)
|
||
* - title: 事件标题
|
||
* - text: 事件文本内容
|
||
* - textTemplate: 可选的文本模板(支持变量替换)
|
||
* - npcId: 关联的NPC ID
|
||
* - choices: 选项列表
|
||
* - actions: 事件触发的动作
|
||
* - triggers: 触发条件
|
||
*/
|
||
export const EVENT_CONFIG = {
|
||
// 初始剧情事件
|
||
intro: {
|
||
id: 'intro',
|
||
type: 'story',
|
||
title: '苏醒',
|
||
text: '你在一个废弃的实验室中醒来,头痛欲裂。记忆模糊不清,周围一片狼藉。\n\n桌上放着一根粗糙的木棍和一本破旧的日记。门外隐约传来野兽的嚎叫声...\n\n你必须活下去。',
|
||
choices: [
|
||
{ text: '拿起木棍', next: null, action: 'give_stick' },
|
||
{ text: '先看看日记', next: 'intro_diary' }
|
||
]
|
||
},
|
||
|
||
intro_diary: {
|
||
id: 'intro_diary',
|
||
type: 'story',
|
||
title: '破旧的日记',
|
||
text: '日记的纸张已经泛黄,上面的字迹有些模糊。你翻开了第一页:\n\n"第X天\n世界已经变了...那些东西...它们无处不在。\n\n如果你看到这个日记,记住:\n1. 找武器,任何武器都比空手强\n2. 避开黑暗的地方,除非你有办法\n3. 商人老张在市场,他可能会帮你\n\n活下去..."',
|
||
choices: [
|
||
{ text: '收好日记,拿起木棍', next: null, action: 'give_stick' }
|
||
]
|
||
},
|
||
|
||
// 首次战斗提示
|
||
first_combat: {
|
||
id: 'first_combat',
|
||
type: 'tips',
|
||
title: '战斗提示',
|
||
textTemplate: '你来到了{locationName}。这里是危险区域,随时可能遭遇敌人!\n\n战斗提示:\n- 攻击姿态:高伤害,低防御\n- 防御姿态:低伤害,高防御\n- 平衡姿态:攻守平衡\n\n注意耐力,耐力耗尽会大幅降低战斗力!',
|
||
choices: [
|
||
{ text: '明白了', next: null }
|
||
]
|
||
},
|
||
|
||
// 黑暗环境警告
|
||
dark_warning: {
|
||
id: 'dark_warning',
|
||
type: 'tips',
|
||
title: '黑暗警告',
|
||
textTemplate: '你进入了{locationName}。这里一片漆黑,几乎看不清任何东西。\n\n黑暗效果:\n- AP(攻击点数)-20%\n- EP(闪避点数)-20%\n- 阅读效率-50%\n\n提示:在这里待着会逐渐获得"夜视"技能经验,技能等级提高后可以减少惩罚。',
|
||
choices: [
|
||
{ text: '小心前行', next: null }
|
||
]
|
||
},
|
||
|
||
// Boss解锁提示
|
||
boss_unlock: {
|
||
id: 'boss_unlock',
|
||
type: 'unlock',
|
||
title: '新的挑战',
|
||
text: '你击败了足够多的野狗,对这片区域有了更深的了解。\n\n在探索中,你发现了一个通往更深处的入口...那里似乎盘踞着什么强大的东西。\n\n[解锁区域:测试Boss巢]',
|
||
choices: [
|
||
{ text: '做好准备', next: null }
|
||
]
|
||
},
|
||
|
||
// Boss击败剧情
|
||
boss_defeat: {
|
||
id: 'boss_defeat',
|
||
type: 'story',
|
||
title: '胜利',
|
||
text: '经过一番激战,你终于击败了那只强大的野兽!\n\n在它的巢穴深处,你发现了一把生锈的钥匙,上面刻着「B」字母。\n\n这应该能打开某个地方...',
|
||
choices: [
|
||
{ text: '收起钥匙', next: null, action: 'give_item', actionData: { itemId: 'basement_key', count: 1 } }
|
||
]
|
||
},
|
||
|
||
// 夜视技能解锁
|
||
night_vision_unlock: {
|
||
id: 'night_vision_unlock',
|
||
type: 'tips',
|
||
title: '新技能',
|
||
text: '在黑暗中待了一段时间后,你的眼睛逐渐适应了...\n\n[解锁被动技能:夜视]\n\n效果:\n- Lv.5: 黑暗惩罚-10%\n- Lv.10: 黑暗惩罚-25%\n\n在黑暗环境中待着会自动获得经验。',
|
||
choices: [
|
||
{ text: '继续', next: null }
|
||
]
|
||
},
|
||
|
||
// 阅读完成奖励
|
||
book_complete: {
|
||
id: 'book_complete',
|
||
type: 'reward',
|
||
title: '阅读完成',
|
||
textTemplate: '你读完了《{bookName}》,对里面的内容有了更深的理解。\n\n获得阅读经验+{exp}!',
|
||
choices: [
|
||
{ text: '收起书籍', next: null }
|
||
]
|
||
},
|
||
|
||
// 商人老张首次对话
|
||
merchant_first: {
|
||
id: 'merchant_first',
|
||
type: 'dialogue',
|
||
title: '商人老张',
|
||
text: '哟,新人?看你的样子,刚醒来不久吧。\n\n这里的东西你可以看看,不过生意就是生意,我也要吃饭。\n\n商人售价:200%基础价格\n商人收购价:30%基础价格\n\n觉得贵?那是因为外面太危险了!',
|
||
choices: [
|
||
{ text: '查看商品', next: null, action: 'open_shop' },
|
||
{ text: '为什么这么贵?', next: 'merchant_explain' },
|
||
{ text: '离开', next: null }
|
||
]
|
||
},
|
||
|
||
merchant_explain: {
|
||
id: 'merchant_explain',
|
||
type: 'dialogue',
|
||
title: '商人老张',
|
||
text: '嘿,你想想看,外面那些野狗会咬人,外面那些地方暗得要命。\n\n我能活着把这些东西运回来,就已经很不容易了。\n\n不过...你多来几次,我也可以给你点优惠。要学会讲价!',
|
||
choices: [
|
||
{ text: '查看商品', next: null, action: 'open_shop' },
|
||
{ text: '离开', next: null }
|
||
]
|
||
},
|
||
|
||
// 神秘人对话
|
||
mysterious_first: {
|
||
id: 'mysterious_first',
|
||
type: 'dialogue',
|
||
title: '神秘人',
|
||
text: '......\n\n你?哼,还没死呢。\n\n看在你还活着的份上,给你一个建议:\n\n有些东西,不是靠蛮力能得到的。\n\n有些技能,要用心去感受。',
|
||
choices: [
|
||
{ text: '什么意思?', next: 'mysterious_hint' },
|
||
{ text: '离开', next: null }
|
||
]
|
||
},
|
||
|
||
mysterious_hint: {
|
||
id: 'mysterious_hint',
|
||
type: 'dialogue',
|
||
title: '神秘人',
|
||
text: '有些技能,不需要你主动去做。\n\n在黑暗中待着,眼睛会适应。\n\n在狭窄的地方战斗,身体会学会闪避。\n\n在恶劣的环境中生存,意志会变得坚韧。\n\n......这就是"适应"。',
|
||
choices: [
|
||
{ text: '我明白了', next: null },
|
||
{ text: '再详细说说', next: 'mysterious_detail' }
|
||
]
|
||
},
|
||
|
||
mysterious_detail: {
|
||
id: 'mysterious_detail',
|
||
type: 'dialogue',
|
||
title: '神秘人',
|
||
text: '被动技能,懂吗?\n\n夜视 - 黑暗环境中自动获得经验\n狭窄空间战斗 - 狭窄环境中自动获得经验\n生存专家 - 恶劣环境中自动获得经验\n\n这些技能不需要你训练,只需要你在相应的环境中待着。\n\n不过...前提是你得先去过那些地方。',
|
||
choices: [
|
||
{ text: '受教了', next: null }
|
||
]
|
||
},
|
||
|
||
// 技能里程碑奖励提示
|
||
skill_milestone: {
|
||
id: 'skill_milestone',
|
||
type: 'reward',
|
||
title: '技能突破',
|
||
textTemplate: '你的{skillName}达到了{level}级!\n\n获得里程碑奖励:\n{bonus}',
|
||
choices: [
|
||
{ text: '太好了', next: null }
|
||
]
|
||
},
|
||
|
||
// 等级提升提示
|
||
level_up: {
|
||
id: 'level_up',
|
||
type: 'reward',
|
||
title: '等级提升',
|
||
textTemplate: '你的等级提升到了 {level}!\n\n各项属性得到提升。\n\n现在可以学习更高等级的技能了。',
|
||
choices: [
|
||
{ text: '继续', next: null }
|
||
]
|
||
},
|
||
|
||
// 死亡提示
|
||
defeat: {
|
||
id: 'defeat',
|
||
type: 'story',
|
||
title: '失败',
|
||
text: '你的视线逐渐模糊,意识消散...\n\n......\n\n等你再次醒来时,发现自己回到了营地。\n\n那家伙救了你一命。\n\n"小心点,下次可能就没这么好运了。"',
|
||
choices: [
|
||
{ text: '...', next: null, action: 'heal', actionData: { amount: 50 } }
|
||
]
|
||
},
|
||
|
||
// 物品获得提示
|
||
item_get: {
|
||
id: 'item_get',
|
||
type: 'reward',
|
||
title: '获得物品',
|
||
textTemplate: '获得了:{itemName} x{count}',
|
||
choices: [
|
||
{ text: '收下', next: null }
|
||
]
|
||
},
|
||
|
||
// 技能解锁提示
|
||
skill_unlock: {
|
||
id: 'skill_unlock',
|
||
type: 'tips',
|
||
title: '新技能',
|
||
textTemplate: '解锁了新技能:{skillName}\n\n{description}',
|
||
choices: [
|
||
{ text: '了解了', next: null }
|
||
]
|
||
},
|
||
|
||
// 黑市开放提示
|
||
blackmarket_open: {
|
||
id: 'blackmarket_open',
|
||
type: 'tips',
|
||
title: '黑市开放',
|
||
text: '现在是黑市开放时间!\n\n黑市商人带来了稀有的商品,品质可能比普通市场更高。\n\n回收价格也比普通市场更优惠(50% vs 30%)。\n\n开放时间:周三、周六 20:00-24:00',
|
||
choices: [
|
||
{ text: '去看看', next: null, action: 'teleport', actionData: { locationId: 'blackmarket' } },
|
||
{ text: '稍后再说', next: null }
|
||
]
|
||
},
|
||
|
||
// 区域解锁提示
|
||
area_unlock: {
|
||
id: 'area_unlock',
|
||
type: 'unlock',
|
||
title: '新区域',
|
||
textTemplate: '解锁了新区域:{areaName}\n\n{description}',
|
||
choices: [
|
||
{ text: '稍后再说', next: null }
|
||
]
|
||
},
|
||
|
||
// 探索事件
|
||
explore_nothing: {
|
||
id: 'explore_nothing',
|
||
type: 'info',
|
||
title: '探索结果',
|
||
text: '你仔细搜索了这片区域,但没有发现任何有用的东西。',
|
||
choices: [
|
||
{ text: '继续', next: null }
|
||
]
|
||
},
|
||
explore_find_herb: {
|
||
id: 'explore_find_herb',
|
||
type: 'reward',
|
||
title: '探索发现',
|
||
text: '你在草丛中发现了一些草药!',
|
||
choices: [
|
||
{ text: '收下', next: null, action: 'give_item', actionData: { itemId: 'healing_herb', count: { min: 1, max: 3 } } }
|
||
]
|
||
},
|
||
explore_find_coin: {
|
||
id: 'explore_find_coin',
|
||
type: 'reward',
|
||
title: '探索发现',
|
||
textTemplate: '你在角落里发现了一些铜币!\n\n获得了 {amount} 铜币',
|
||
choices: [
|
||
{ text: '太好了', next: null }
|
||
]
|
||
},
|
||
explore_find_trash: {
|
||
id: 'explore_find_trash',
|
||
type: 'info',
|
||
title: '探索发现',
|
||
text: '你只找到了一些垃圾。',
|
||
choices: [
|
||
{ text: '离开', next: null }
|
||
]
|
||
},
|
||
explore_encounter: {
|
||
id: 'explore_encounter',
|
||
type: 'combat',
|
||
title: '遭遇',
|
||
textTemplate: '探索时突然遇到了{enemyName}!',
|
||
choices: [
|
||
{ text: '迎战', next: null },
|
||
{ text: '逃跑', next: null, action: 'flee' }
|
||
]
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 事件触发条件配置
|
||
* 用于定时事件或条件触发的事件
|
||
*/
|
||
export const EVENT_TRIGGERS = {
|
||
// 每日事件
|
||
daily: {
|
||
blackmarket_reminder: {
|
||
condition: (gameTime) => {
|
||
// 周三或周六的20:00
|
||
const dayOfWeek = (gameTime.day - 1) % 7
|
||
const isMarketDay = dayOfWeek === 2 || dayOfWeek === 5 // 0=周一, 2=周三, 5=周六
|
||
const isMarketTime = gameTime.hour === 20 && gameTime.minute === 0
|
||
return isMarketDay && isMarketTime
|
||
},
|
||
eventId: 'blackmarket_open',
|
||
oncePerDay: true
|
||
}
|
||
},
|
||
|
||
// 一次性事件
|
||
once: {
|
||
night_vision_first: {
|
||
condition: (playerStore) => {
|
||
const skill = playerStore.skills.night_vision
|
||
return skill && skill.unlocked && skill.level === 1 && !playerStore.flags.nightVisionHintShown
|
||
},
|
||
eventId: 'night_vision_unlock',
|
||
setFlag: 'nightVisionHintShown'
|
||
},
|
||
first_book_complete: {
|
||
condition: (playerStore) => {
|
||
return playerStore.readBooks && playerStore.readBooks.length > 0 && !playerStore.flags.firstBookHintShown
|
||
},
|
||
eventId: 'book_complete',
|
||
setFlag: 'firstBookHintShown'
|
||
}
|
||
},
|
||
|
||
// 环境触发事件
|
||
environment: {
|
||
basement_first_enter: {
|
||
condition: (playerStore, locationId) => {
|
||
return locationId === 'basement' && !playerStore.flags.basementFirstEnter
|
||
},
|
||
eventId: 'dark_warning'
|
||
},
|
||
narrow_first_enter: {
|
||
condition: (playerStore, locationId) => {
|
||
const location = LOCATION_CONFIG[locationId]
|
||
return location?.environment === 'narrow' && !playerStore.flags[`narrow_${locationId}_enter`]
|
||
},
|
||
eventId: null, // 只记录,不显示事件
|
||
setFlag: (locationId) => `narrow_${locationId}_enter`
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 事件选择默认动作
|
||
* 用于处理没有指定next的选项
|
||
*/
|
||
export const DEFAULT_EVENT_ACTIONS = {
|
||
close: true, // 关闭事件
|
||
log: true // 记录日志
|
||
}
|
||
|
||
/**
|
||
* 优先级事件配置
|
||
* 这些事件会优先显示,不会被其他事件打断
|
||
*/
|
||
export const PRIORITY_EVENTS = [
|
||
'intro',
|
||
'defeat',
|
||
'boss_defeat'
|
||
]
|
||
|
||
/**
|
||
* 可跳过的事件类型
|
||
* 这些类型的事件可以被玩家跳过
|
||
*/
|
||
export const SKIPPABLE_EVENT_TYPES = [
|
||
'tips',
|
||
'reward'
|
||
]
|