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:
26
config/constants.js
Normal file
26
config/constants.js
Normal file
@@ -0,0 +1,26 @@
|
||||
// 游戏数值常量
|
||||
export const GAME_CONSTANTS = {
|
||||
// 时间流速:现实1秒 = 游戏时间5分钟
|
||||
TIME_SCALE: 5,
|
||||
|
||||
// 离线收益时间(小时)
|
||||
OFFLINE_HOURS_BASE: 0.5,
|
||||
OFFLINE_HOURS_AD: 2.5,
|
||||
|
||||
// 耐力相关
|
||||
STAMINA_FULL_EFFECT: 50, // 耐力高于此值时无惩罚
|
||||
STAMINA_EMPTY_PENALTY: 0.5, // 耐力耗尽时效率减半
|
||||
|
||||
// 经验倍率
|
||||
EXP_PARTIAL_SUCCESS: 0.5, // 部分成功时经验比例
|
||||
|
||||
// 品质等级
|
||||
QUALITY_LEVELS: {
|
||||
1: { name: '垃圾', color: '#808080', range: [0, 49], multiplier: 1.0 },
|
||||
2: { name: '普通', color: '#ffffff', range: [50, 99], multiplier: 1.0 },
|
||||
3: { name: '优秀', color: '#4ade80', range: [100, 129], multiplier: 1.1 },
|
||||
4: { name: '稀有', color: '#60a5fa', range: [130, 159], multiplier: 1.3 },
|
||||
5: { name: '史诗', color: '#a855f7', range: [160, 199], multiplier: 1.6 },
|
||||
6: { name: '传说', color: '#f97316', range: [200, 250], multiplier: 2.0 }
|
||||
}
|
||||
}
|
||||
45
config/enemies.js
Normal file
45
config/enemies.js
Normal file
@@ -0,0 +1,45 @@
|
||||
// 敌人配置
|
||||
export const ENEMY_CONFIG = {
|
||||
wild_dog: {
|
||||
id: 'wild_dog',
|
||||
name: '野狗',
|
||||
level: 1,
|
||||
baseStats: {
|
||||
health: 30,
|
||||
attack: 8,
|
||||
defense: 2,
|
||||
speed: 1.0
|
||||
},
|
||||
derivedStats: {
|
||||
ap: 10, // 攻击点数
|
||||
ep: 8 // 闪避点数
|
||||
},
|
||||
expReward: 15,
|
||||
skillExpReward: 10,
|
||||
drops: [
|
||||
{ itemId: 'dog_skin', chance: 0.8, count: { min: 1, max: 1 } }
|
||||
]
|
||||
},
|
||||
|
||||
test_boss: {
|
||||
id: 'test_boss',
|
||||
name: '测试Boss',
|
||||
level: 5,
|
||||
baseStats: {
|
||||
health: 200,
|
||||
attack: 25,
|
||||
defense: 10,
|
||||
speed: 0.8
|
||||
},
|
||||
derivedStats: {
|
||||
ap: 25,
|
||||
ep: 15
|
||||
},
|
||||
expReward: 150,
|
||||
skillExpReward: 50,
|
||||
drops: [
|
||||
{ itemId: 'basement_key', chance: 1.0, count: { min: 1, max: 1 } }
|
||||
],
|
||||
isBoss: true
|
||||
}
|
||||
}
|
||||
329
config/events.js
Normal file
329
config/events.js
Normal 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'
|
||||
]
|
||||
87
config/items.js
Normal file
87
config/items.js
Normal file
@@ -0,0 +1,87 @@
|
||||
// 物品配置
|
||||
export const ITEM_CONFIG = {
|
||||
// 武器
|
||||
wooden_stick: {
|
||||
id: 'wooden_stick',
|
||||
name: '木棍',
|
||||
type: 'weapon',
|
||||
subtype: 'one_handed',
|
||||
icon: '🪵',
|
||||
baseValue: 10, // 基础价值(铜币)
|
||||
baseDamage: 5,
|
||||
attackSpeed: 1.0,
|
||||
quality: 100, // 默认品质
|
||||
unlockSkill: 'stick_mastery',
|
||||
description: '一根粗糙的木棍,至少比空手强。'
|
||||
},
|
||||
|
||||
// 消耗品
|
||||
bread: {
|
||||
id: 'bread',
|
||||
name: '面包',
|
||||
type: 'consumable',
|
||||
subtype: 'food',
|
||||
icon: '🍞',
|
||||
baseValue: 10,
|
||||
effect: {
|
||||
stamina: 20
|
||||
},
|
||||
description: '普通的面包,可以恢复耐力。',
|
||||
stackable: true,
|
||||
maxStack: 99
|
||||
},
|
||||
|
||||
healing_herb: {
|
||||
id: 'healing_herb',
|
||||
name: '草药',
|
||||
type: 'consumable',
|
||||
subtype: 'medicine',
|
||||
icon: '🌿',
|
||||
baseValue: 15,
|
||||
effect: {
|
||||
health: 15
|
||||
},
|
||||
description: '常见的治疗草药,可以恢复生命值。',
|
||||
stackable: true,
|
||||
maxStack: 99
|
||||
},
|
||||
|
||||
// 书籍
|
||||
old_book: {
|
||||
id: 'old_book',
|
||||
name: '破旧书籍',
|
||||
type: 'book',
|
||||
icon: '📖',
|
||||
baseValue: 50,
|
||||
readingTime: 60, // 秒
|
||||
expReward: {
|
||||
reading: 10
|
||||
},
|
||||
completionBonus: null,
|
||||
description: '一本破旧的书籍,记录着一些基础知识。',
|
||||
consumable: false // 书籍不消耗
|
||||
},
|
||||
|
||||
// 素材
|
||||
dog_skin: {
|
||||
id: 'dog_skin',
|
||||
name: '狗皮',
|
||||
type: 'material',
|
||||
icon: '🐕',
|
||||
baseValue: 5,
|
||||
description: '野狗的皮毛,可以用来制作简单装备。',
|
||||
stackable: true,
|
||||
maxStack: 99
|
||||
},
|
||||
|
||||
// 关键道具
|
||||
basement_key: {
|
||||
id: 'basement_key',
|
||||
name: '地下室钥匙',
|
||||
type: 'key',
|
||||
icon: '🔑',
|
||||
baseValue: 0,
|
||||
description: '一把生锈的钥匙,上面刻着「B」字母。',
|
||||
stackable: false
|
||||
}
|
||||
}
|
||||
69
config/locations.js
Normal file
69
config/locations.js
Normal file
@@ -0,0 +1,69 @@
|
||||
// 区域配置
|
||||
export const LOCATION_CONFIG = {
|
||||
camp: {
|
||||
id: 'camp',
|
||||
name: '测试营地',
|
||||
type: 'safe',
|
||||
environment: 'normal',
|
||||
description: '一个临时的幸存者营地,相对安全。',
|
||||
connections: ['market', 'blackmarket', 'wild1'],
|
||||
npcs: ['injured_adventurer'],
|
||||
activities: ['rest', 'talk', 'trade']
|
||||
},
|
||||
|
||||
market: {
|
||||
id: 'market',
|
||||
name: '测试市场',
|
||||
type: 'safe',
|
||||
environment: 'normal',
|
||||
description: '商人老张在这里摆摊。',
|
||||
connections: ['camp'],
|
||||
npcs: ['merchant_zhang'],
|
||||
activities: ['trade']
|
||||
},
|
||||
|
||||
blackmarket: {
|
||||
id: 'blackmarket',
|
||||
name: '测试黑市',
|
||||
type: 'safe',
|
||||
environment: 'normal',
|
||||
description: '神秘人偶尔会在这里出现。',
|
||||
connections: ['camp'],
|
||||
npcs: ['mysterious_man'],
|
||||
activities: ['trade']
|
||||
},
|
||||
|
||||
wild1: {
|
||||
id: 'wild1',
|
||||
name: '测试野外1',
|
||||
type: 'danger',
|
||||
environment: 'normal',
|
||||
description: '野狗经常出没的区域。',
|
||||
connections: ['camp', 'boss_lair'],
|
||||
enemies: ['wild_dog'],
|
||||
activities: ['explore', 'combat']
|
||||
},
|
||||
|
||||
boss_lair: {
|
||||
id: 'boss_lair',
|
||||
name: '测试Boss巢',
|
||||
type: 'danger',
|
||||
environment: 'normal',
|
||||
description: '强大的野兽盘踞在这里。',
|
||||
connections: ['wild1', 'basement'],
|
||||
enemies: ['test_boss'],
|
||||
unlockCondition: { type: 'kill', target: 'wild_dog', count: 5 },
|
||||
activities: ['combat']
|
||||
},
|
||||
|
||||
basement: {
|
||||
id: 'basement',
|
||||
name: '地下室',
|
||||
type: 'dungeon',
|
||||
environment: 'dark',
|
||||
description: '黑暗潮湿的地下室,需要照明。',
|
||||
connections: ['boss_lair'],
|
||||
unlockCondition: { type: 'item', item: 'basement_key' },
|
||||
activities: ['explore', 'read']
|
||||
}
|
||||
}
|
||||
44
config/npcs.js
Normal file
44
config/npcs.js
Normal file
@@ -0,0 +1,44 @@
|
||||
// NPC配置
|
||||
export const NPC_CONFIG = {
|
||||
injured_adventurer: {
|
||||
id: 'injured_adventurer',
|
||||
name: '受伤的冒险者',
|
||||
location: 'camp',
|
||||
dialogue: {
|
||||
first: {
|
||||
text: '你终于醒了...这里是营地,暂时安全。外面的世界很危险,带上这根木棍防身吧。',
|
||||
choices: [
|
||||
{ text: '谢谢', next: 'thanks' },
|
||||
{ text: '这是什么地方?', next: 'explain' }
|
||||
]
|
||||
},
|
||||
thanks: {
|
||||
text: '小心野狗,它们通常成群出现。如果你能击败五只野狗,或许能找到通往深处的路。',
|
||||
choices: [
|
||||
{ text: '明白了', next: null, action: 'give_stick' }
|
||||
]
|
||||
},
|
||||
explain: {
|
||||
text: '这是末世后的世界...具体细节我也记不清了。总之,活下去是第一要务。',
|
||||
choices: [
|
||||
{ text: '我会的', next: 'thanks', action: 'give_stick' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
merchant_zhang: {
|
||||
id: 'merchant_zhang',
|
||||
name: '商人老张',
|
||||
location: 'market',
|
||||
dialogue: {
|
||||
first: {
|
||||
text: '欢迎光临!看看有什么需要的?',
|
||||
choices: [
|
||||
{ text: '查看商品', next: null, action: 'open_shop' },
|
||||
{ text: '离开', next: null }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
177
config/shop.js
Normal file
177
config/shop.js
Normal file
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* 商店配置
|
||||
* 定义不同位置商店的出售物品
|
||||
*/
|
||||
|
||||
import { ITEM_CONFIG } from './items.js'
|
||||
|
||||
// 商店配置
|
||||
export const SHOP_CONFIG = {
|
||||
// 营地商店 - 基础物品
|
||||
camp: {
|
||||
name: '营地杂货铺',
|
||||
owner: '老杰克',
|
||||
icon: '🏪',
|
||||
// 出售的物品列表
|
||||
items: [
|
||||
{
|
||||
itemId: 'bread',
|
||||
stock: 99, // 库存,-1表示无限
|
||||
baseStock: 99
|
||||
},
|
||||
{
|
||||
itemId: 'healing_herb',
|
||||
stock: 20,
|
||||
baseStock: 20
|
||||
},
|
||||
{
|
||||
itemId: 'old_book',
|
||||
stock: 5,
|
||||
baseStock: 5
|
||||
}
|
||||
],
|
||||
// 收购的物品类型
|
||||
buyItems: ['material', 'consumable'],
|
||||
// 收购价格倍率
|
||||
buyRate: 0.3
|
||||
},
|
||||
|
||||
// 测试市场 - 商人老张
|
||||
market: {
|
||||
name: '商人老张的摊位',
|
||||
owner: '商人老张',
|
||||
icon: '🛒',
|
||||
items: [
|
||||
{
|
||||
itemId: 'bread',
|
||||
stock: -1,
|
||||
baseStock: -1
|
||||
},
|
||||
{
|
||||
itemId: 'healing_herb',
|
||||
stock: 50,
|
||||
baseStock: 50
|
||||
},
|
||||
{
|
||||
itemId: 'old_book',
|
||||
stock: 10,
|
||||
baseStock: 10
|
||||
}
|
||||
],
|
||||
buyItems: ['material', 'consumable', 'weapon', 'armor'],
|
||||
buyRate: 0.4
|
||||
},
|
||||
|
||||
// 测试黑市 - 神秘人
|
||||
blackmarket: {
|
||||
name: '神秘人的黑市',
|
||||
owner: '神秘人',
|
||||
icon: '🌑',
|
||||
items: [
|
||||
{
|
||||
itemId: 'healing_herb',
|
||||
stock: 10,
|
||||
baseStock: 10
|
||||
}
|
||||
],
|
||||
buyItems: ['material', 'weapon'],
|
||||
buyRate: 0.2
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定位置的商店配置
|
||||
* @param {string} locationId - 位置ID
|
||||
* @returns {Object|null} 商店配置
|
||||
*/
|
||||
export function getShopConfig(locationId) {
|
||||
return SHOP_CONFIG[locationId] || null
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商店的可售物品列表
|
||||
* @param {string} locationId - 位置ID
|
||||
* @returns {Array} 可售物品列表
|
||||
*/
|
||||
export function getShopItems(locationId) {
|
||||
const shop = getShopConfig(locationId)
|
||||
if (!shop) return []
|
||||
|
||||
return shop.items
|
||||
.filter(item => item.stock === -1 || item.stock > 0)
|
||||
.map(shopItem => {
|
||||
const itemConfig = ITEM_CONFIG[shopItem.itemId]
|
||||
if (!itemConfig) return null
|
||||
|
||||
return {
|
||||
...itemConfig,
|
||||
stock: shopItem.stock,
|
||||
baseStock: shopItem.baseStock,
|
||||
shopItemId: shopItem.itemId
|
||||
}
|
||||
})
|
||||
.filter(Boolean)
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查物品是否可以被商店收购
|
||||
* @param {string} locationId - 位置ID
|
||||
* @param {Object} item - 物品对象
|
||||
* @returns {boolean} 是否可以收购
|
||||
*/
|
||||
export function canShopBuyItem(locationId, item) {
|
||||
const shop = getShopConfig(locationId)
|
||||
if (!shop || !shop.buyItems) return false
|
||||
|
||||
// 关键道具不能出售
|
||||
if (item.type === 'key') return false
|
||||
|
||||
return shop.buyItems.includes(item.type)
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算物品的购买价格(玩家买)
|
||||
* @param {Object} gameStore - 游戏Store
|
||||
* @param {string} itemId - 物品ID
|
||||
* @returns {number} 购买价格(铜币)
|
||||
*/
|
||||
export function getBuyPrice(gameStore, itemId) {
|
||||
const item = ITEM_CONFIG[itemId]
|
||||
if (!item || !item.baseValue) return 0
|
||||
|
||||
const marketData = gameStore.marketPrices?.prices?.[itemId]
|
||||
const basePrice = item.baseValue
|
||||
|
||||
if (marketData) {
|
||||
return Math.floor(basePrice * marketData.buyRate)
|
||||
}
|
||||
|
||||
return Math.floor(basePrice * 2)
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算物品的出售价格(玩家卖)
|
||||
* @param {Object} gameStore - 游戏Store
|
||||
* @param {string} itemId - 物品ID
|
||||
* @param {number} quality - 物品品质
|
||||
* @returns {number} 出售价格(铜币)
|
||||
*/
|
||||
export function getSellPrice(gameStore, itemId, quality = 100) {
|
||||
const item = ITEM_CONFIG[itemId]
|
||||
if (!item || !item.baseValue) return 0
|
||||
|
||||
const marketData = gameStore.marketPrices?.prices?.[itemId]
|
||||
const basePrice = item.baseValue
|
||||
|
||||
// 品质影响价格
|
||||
const qualityMultiplier = quality / 100
|
||||
let price = Math.floor(basePrice * qualityMultiplier)
|
||||
|
||||
if (marketData) {
|
||||
price = Math.floor(price * marketData.sellRate)
|
||||
} else {
|
||||
price = Math.floor(price * 0.3)
|
||||
}
|
||||
|
||||
return Math.max(1, price)
|
||||
}
|
||||
53
config/skills.js
Normal file
53
config/skills.js
Normal file
@@ -0,0 +1,53 @@
|
||||
// 技能配置
|
||||
export const SKILL_CONFIG = {
|
||||
// 战斗技能
|
||||
stick_mastery: {
|
||||
id: 'stick_mastery',
|
||||
name: '木棍精通',
|
||||
type: 'combat',
|
||||
category: 'weapon',
|
||||
icon: '',
|
||||
maxLevel: 20,
|
||||
expPerLevel: (level) => level * 100,
|
||||
milestones: {
|
||||
5: { desc: '所有武器暴击率+2%', effect: { critRate: 2 } },
|
||||
10: { desc: '所有武器攻击力+5%', effect: { attackBonus: 5 } },
|
||||
15: { desc: '武器熟练度获取速度+20%', effect: { expRate: 1.2 } },
|
||||
20: { desc: '所有武器暴击伤害+0.3', effect: { critMult: 0.3 } }
|
||||
},
|
||||
unlockCondition: null, // 初始解锁
|
||||
unlockItem: 'wooden_stick'
|
||||
},
|
||||
|
||||
reading: {
|
||||
id: 'reading',
|
||||
name: '阅读',
|
||||
type: 'life',
|
||||
category: 'reading',
|
||||
icon: '',
|
||||
maxLevel: 20,
|
||||
expPerLevel: (level) => level * 50,
|
||||
milestones: {
|
||||
3: { desc: '所有技能经验获取+5%', effect: { globalExpRate: 5 } },
|
||||
5: { desc: '阅读速度+50%', effect: { readingSpeed: 1.5 } },
|
||||
10: { desc: '完成书籍给予额外主经验+100', effect: { bookExpBonus: 100 } }
|
||||
},
|
||||
unlockCondition: null,
|
||||
unlockItem: 'old_book'
|
||||
},
|
||||
|
||||
night_vision: {
|
||||
id: 'night_vision',
|
||||
name: '夜视',
|
||||
type: 'passive',
|
||||
category: 'environment',
|
||||
icon: '',
|
||||
maxLevel: 10,
|
||||
expPerLevel: (level) => level * 30,
|
||||
milestones: {
|
||||
5: { desc: '黑暗惩罚-10%', effect: { darkPenaltyReduce: 10 } },
|
||||
10: { desc: '黑暗惩罚-25%', effect: { darkPenaltyReduce: 25 } }
|
||||
},
|
||||
unlockCondition: { location: 'basement' }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user