Initial commit: Text Adventure Game

Features:
- Combat system with AP/EP hit calculation and three-layer defense
- Auto-combat/farming mode
- Item system with stacking support
- Skill system with levels, milestones, and parent skill sync
- Shop system with dynamic pricing
- Inventory management with bulk selling
- Event system
- Game loop with offline earnings
- Save/Load system

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Claude
2026-01-21 17:13:51 +08:00
commit cb412544e9
90 changed files with 17149 additions and 0 deletions

329
config/events.js Normal file
View File

@@ -0,0 +1,329 @@
/**
* 事件配置
* Phase 6 核心系统实现
*/
/**
* 事件配置
* 每个事件包含:
* - 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, action: 'teleport', actionData: { locationId: '{areaId}' } },
{ text: '稍后再说', next: null }
]
}
}
/**
* 事件触发条件配置
* 用于定时事件或条件触发的事件
*/
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'
]