feat: 实现游戏核心系统和UI组件

核心系统:
- 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>
This commit is contained in:
Claude
2026-01-23 16:20:10 +08:00
parent 021f6a54f5
commit 16223c89a5
25 changed files with 2731 additions and 318 deletions

View File

@@ -1,45 +1,246 @@
/**
* 敌人配置
* Phase 4 数值调整 - 战斗数值平衡
*/
// 敌人配置
export const ENEMY_CONFIG = {
// ===== Lv.1 敌人 =====
wild_dog: {
id: 'wild_dog',
name: '野狗',
level: 1,
baseStats: {
health: 30,
health: 35,
attack: 8,
defense: 2,
speed: 1.0
speed: 1.2
},
derivedStats: {
ap: 10, // 攻击点数
ep: 8 // 闪避点数
ap: 8,
ep: 10
},
expReward: 15,
skillExpReward: 10,
expReward: 20,
skillExpReward: 12,
drops: [
{ itemId: 'dog_skin', chance: 0.8, count: { min: 1, max: 1 } }
{ itemId: 'dog_skin', chance: 0.7, count: { min: 1, max: 1 } },
{ itemId: 'healing_herb', chance: 0.15, count: { min: 1, max: 2 } }
]
},
test_boss: {
id: 'test_boss',
name: '测试Boss',
level: 5,
rat: {
id: 'rat',
name: '老鼠',
level: 1,
baseStats: {
health: 200,
attack: 25,
defense: 10,
speed: 0.8
health: 20,
attack: 5,
defense: 1,
speed: 1.5
},
derivedStats: {
ap: 25,
ep: 15
ap: 6,
ep: 12
},
expReward: 150,
skillExpReward: 50,
expReward: 10,
skillExpReward: 6,
drops: [
{ itemId: 'basement_key', chance: 1.0, count: { min: 1, max: 1 } }
{ itemId: 'healing_herb', chance: 0.2, count: { min: 1, max: 1 } }
]
},
// ===== Lv.3 敌人 =====
wolf: {
id: 'wolf',
name: '灰狼',
level: 3,
baseStats: {
health: 50,
attack: 15,
defense: 5,
speed: 1.3
},
derivedStats: {
ap: 14,
ep: 13
},
expReward: 40,
skillExpReward: 20,
drops: [
{ itemId: 'wolf_fang', chance: 0.6, count: { min: 1, max: 2 } },
{ itemId: 'dog_skin', chance: 0.3, count: { min: 1, max: 1 } }
]
},
bandit: {
id: 'bandit',
name: '流浪者',
level: 3,
baseStats: {
health: 60,
attack: 18,
defense: 8,
speed: 1.0
},
derivedStats: {
ap: 16,
ep: 10
},
expReward: 50,
skillExpReward: 25,
drops: [
{ itemId: 'copper_coin', chance: 0.8, count: { min: 3, max: 8 } },
{ itemId: 'bread', chance: 0.3, count: { min: 1, max: 2 } }
]
},
// ===== Lv.5 Boss =====
test_boss: {
id: 'test_boss',
name: '流浪狗王',
level: 5,
baseStats: {
health: 250,
attack: 30,
defense: 15,
speed: 1.1
},
derivedStats: {
ap: 30,
ep: 18
},
expReward: 200,
skillExpReward: 80,
drops: [
{ itemId: 'basement_key', chance: 1.0, count: { min: 1, max: 1 } },
{ itemId: 'dog_skin', chance: 0.5, count: { min: 2, max: 4 } }
],
isBoss: true
},
// ===== Lv.7 敌人 =====
cave_bat: {
id: 'cave_bat',
name: '洞穴蝙蝠',
level: 7,
baseStats: {
health: 40,
attack: 25,
defense: 3,
speed: 1.8
},
derivedStats: {
ap: 22,
ep: 24
},
expReward: 70,
skillExpReward: 35,
drops: [
{ itemId: 'bat_wing', chance: 0.5, count: { min: 1, max: 2 } }
]
},
// ===== Lv.10 Boss =====
cave_boss: {
id: 'cave_boss',
name: '洞穴领主',
level: 10,
baseStats: {
health: 500,
attack: 50,
defense: 25,
speed: 0.9
},
derivedStats: {
ap: 50,
ep: 25
},
expReward: 500,
skillExpReward: 200,
drops: [
{ itemId: 'rare_gem', chance: 0.8, count: { min: 1, max: 1 } },
{ itemId: 'iron_sword', chance: 0.3, count: { min: 1, max: 1 } }
],
isBoss: true
}
}
/**
* 根据区域获取可用的敌人列表
* @param {String} locationId - 位置ID
* @returns {Array} 敌人ID列表
*/
export function getEnemiesForLocation(locationId) {
const locationEnemies = {
'wild1': ['wild_dog', 'rat'],
'wild2': ['wolf', 'bandit'],
'wild3': ['cave_bat', 'wolf'],
'boss_lair': ['test_boss'],
'cave_depth': ['cave_bat', 'cave_boss']
}
return locationEnemies[locationId] || []
}
/**
* 获取位置的敌人完整配置
* @param {String} locationId - 位置ID
* @returns {Array} 敌人配置对象列表
*/
export function getEnemyConfigsForLocation(locationId) {
const enemyIds = getEnemiesForLocation(locationId)
return enemyIds.map(id => ENEMY_CONFIG[id]).filter(Boolean)
}
/**
* 根据等级获取推荐的敌人
* @param {Number} playerLevel - 玩家等级
* @returns {Array} 敌人ID列表
*/
export function getRecommendedEnemies(playerLevel) {
const enemies = []
for (const [id, enemy] of Object.entries(ENEMY_CONFIG)) {
const levelDiff = Math.abs(enemy.level - playerLevel)
// 推荐等级差在3以内的敌人
if (levelDiff <= 3 && !enemy.isBoss) {
enemies.push({ id, levelDiff, enemy })
}
}
// 按等级差排序
enemies.sort((a, b) => a.levelDiff - b.levelDiff)
return enemies.map(e => e.id)
}
/**
* 随机获取位置的一个敌人
* @param {String} locationId - 位置ID
* @returns {Object|null} 敌人配置
*/
export function getRandomEnemyForLocation(locationId) {
const enemyIds = getEnemiesForLocation(locationId)
if (enemyIds.length === 0) return null
const randomIndex = Math.floor(Math.random() * enemyIds.length)
const enemyId = enemyIds[randomIndex]
return ENEMY_CONFIG[enemyId] || null
}
/**
* 获取所有敌人列表
* @returns {Array} 所有敌人ID
*/
export function getAllEnemyIds() {
return Object.keys(ENEMY_CONFIG)
}
/**
* 获取Boss列表
* @returns {Array} Boss敌人ID
*/
export function getBossIds() {
return Object.entries(ENEMY_CONFIG)
.filter(([_, config]) => config.isBoss)
.map(([id, _]) => id)
}

View File

@@ -3,6 +3,8 @@
* Phase 6 核心系统实现
*/
import { LOCATION_CONFIG } from './locations.js'
/**
* 事件配置
* 每个事件包含:
@@ -236,9 +238,56 @@ export const EVENT_CONFIG = {
title: '新区域',
textTemplate: '解锁了新区域:{areaName}\n\n{description}',
choices: [
{ text: '前往探索', next: null, action: 'teleport', actionData: { locationId: '{areaId}' } },
{ 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' }
]
}
}

View File

@@ -1,21 +1,172 @@
// 物品配置
// Phase 5 内容扩展 - 更多物品
export const ITEM_CONFIG = {
// 武器
// ===== 武器 =====
wooden_stick: {
id: 'wooden_stick',
name: '木棍',
type: 'weapon',
subtype: 'one_handed',
icon: '🪵',
baseValue: 10, // 基础价值(铜币)
baseValue: 10,
baseDamage: 5,
attackSpeed: 1.0,
quality: 100, // 默认品质
quality: 100,
unlockSkill: 'stick_mastery',
description: '一根粗糙的木棍,至少比空手强。'
},
// 消耗品
rusty_sword: {
id: 'rusty_sword',
name: '生锈铁剑',
type: 'weapon',
subtype: 'sword',
icon: '🗡️',
baseValue: 100,
baseDamage: 12,
attackSpeed: 1.1,
quality: 50,
unlockSkill: 'sword_mastery',
stats: { critRate: 2 },
description: '一把生锈的铁剑,虽然旧了但依然锋利。'
},
iron_sword: {
id: 'iron_sword',
name: '铁剑',
type: 'weapon',
subtype: 'sword',
icon: '⚔️',
baseValue: 500,
baseDamage: 25,
attackSpeed: 1.2,
quality: 100,
unlockSkill: 'sword_mastery',
stats: { critRate: 5 },
description: '一把精工打造的铁剑。'
},
wooden_club: {
id: 'wooden_club',
name: '木棒',
type: 'weapon',
subtype: 'blunt',
icon: '🏏',
baseValue: 30,
baseDamage: 8,
attackSpeed: 0.9,
quality: 80,
unlockSkill: 'blunt_mastery',
description: '一根粗大的木棒,攻击力强但速度慢。'
},
stone_axe: {
id: 'stone_axe',
name: '石斧',
type: 'weapon',
subtype: 'axe',
icon: '🪓',
baseValue: 80,
baseDamage: 18,
attackSpeed: 0.8,
quality: 60,
unlockSkill: 'axe_mastery',
stats: { critRate: 3 },
description: '用石头打磨成的斧头,笨重但有效。'
},
hunter_bow: {
id: 'hunter_bow',
name: '猎弓',
type: 'weapon',
subtype: 'ranged',
icon: '🏹',
baseValue: 200,
baseDamage: 15,
attackSpeed: 1.3,
quality: 90,
unlockSkill: 'archery',
stats: { accuracy: 10 },
description: '猎人使用的弓,可以远程攻击。'
},
// ===== 防具 =====
rag_armor: {
id: 'rag_armor',
name: '破布护甲',
type: 'armor',
subtype: 'light',
icon: '👕',
baseValue: 20,
defense: 3,
quality: 50,
description: '用破布拼凑成的简易护甲。'
},
leather_armor: {
id: 'leather_armor',
name: '皮甲',
type: 'armor',
subtype: 'light',
icon: '🦺',
baseValue: 150,
defense: 8,
quality: 100,
stats: { evasion: 5 },
description: '用兽皮制成的轻甲,提供基础保护。'
},
iron_armor: {
id: 'iron_armor',
name: '铁甲',
type: 'armor',
subtype: 'heavy',
icon: '🛡️',
baseValue: 800,
defense: 20,
quality: 100,
stats: { maxStamina: -10 }, // 重量影响耐力
description: '铁制重甲,防御力强但会影响行动。'
},
// ===== 盾牌 =====
wooden_shield: {
id: 'wooden_shield',
name: '木盾',
type: 'shield',
icon: '🛡️',
baseValue: 50,
defense: 5,
blockRate: 10,
quality: 80,
description: '简单的木制盾牌。'
},
iron_shield: {
id: 'iron_shield',
name: '铁盾',
type: 'shield',
icon: '🛡️',
baseValue: 300,
defense: 12,
blockRate: 20,
quality: 100,
description: '坚固的铁制盾牌。'
},
// ===== 饰品 =====
lucky_ring: {
id: 'lucky_ring',
name: '幸运戒指',
type: 'accessory',
icon: '💍',
baseValue: 200,
quality: 100,
stats: { critRate: 5, fleeRate: 5 },
description: '一枚带来幸运的戒指。'
},
// ===== 消耗品 - 食物 =====
bread: {
id: 'bread',
name: '面包',
@@ -24,13 +175,63 @@ export const ITEM_CONFIG = {
icon: '🍞',
baseValue: 10,
effect: {
stamina: 20
stamina: 20,
health: 5
},
description: '普通的面包,可以恢复耐力。',
description: '普通的面包,可以恢复耐力和少量生命。',
stackable: true,
maxStack: 99
},
meat: {
id: 'meat',
name: '肉干',
type: 'consumable',
subtype: 'food',
icon: '🥩',
baseValue: 15,
effect: {
stamina: 35,
health: 10
},
description: '风干的肉,营养丰富。',
stackable: true,
maxStack: 50
},
cooked_meat: {
id: 'cooked_meat',
name: '烤肉',
type: 'consumable',
subtype: 'food',
icon: '🍖',
baseValue: 25,
effect: {
stamina: 50,
health: 20
},
description: '烤制的肉,美味又营养。',
stackable: true,
maxStack: 50
},
fresh_water: {
id: 'fresh_water',
name: '清水',
type: 'consumable',
subtype: 'drink',
icon: '💧',
baseValue: 5,
effect: {
stamina: 10,
sanity: 5
},
description: '干净的清水,解渴提神。',
stackable: true,
maxStack: 99
},
// ===== 消耗品 - 药品 =====
healing_herb: {
id: 'healing_herb',
name: '草药',
@@ -39,30 +240,123 @@ export const ITEM_CONFIG = {
icon: '🌿',
baseValue: 15,
effect: {
health: 15
health: 20
},
description: '常见的治疗草药,可以恢复生命值。',
stackable: true,
maxStack: 99
},
// 书籍
bandage: {
id: 'bandage',
name: '绷带',
type: 'consumable',
subtype: 'medicine',
icon: '🩹',
baseValue: 20,
effect: {
health: 30,
stamina: 5
},
description: '急救用的绷带,可以止血。',
stackable: true,
maxStack: 50
},
health_potion_small: {
id: 'health_potion_small',
name: '小治疗药水',
type: 'consumable',
subtype: 'medicine',
icon: '🧪',
baseValue: 50,
effect: {
health: 50
},
description: '小瓶治疗药水,快速恢复生命值。',
stackable: true,
maxStack: 20
},
health_potion: {
id: 'health_potion',
name: '治疗药水',
type: 'consumable',
subtype: 'medicine',
icon: '🧪',
baseValue: 150,
effect: {
health: 100
},
description: '治疗药水,大幅恢复生命值。',
stackable: true,
maxStack: 10
},
// ===== 书籍 =====
old_book: {
id: 'old_book',
name: '破旧书籍',
type: 'book',
icon: '📖',
baseValue: 50,
readingTime: 60, // 秒
readingTime: 60,
expReward: {
reading: 10
},
completionBonus: null,
description: '一本破旧的书籍,记录着一些基础知识。',
consumable: false // 书籍不消耗
consumable: false
},
// 素材
survival_guide: {
id: 'survival_guide',
name: '生存指南',
type: 'book',
icon: '📕',
baseValue: 100,
readingTime: 120,
expReward: {
reading: 25,
survival_instinct: 5
},
completionBonus: { maxStamina: 10 },
description: '荒野生存技巧指南。',
consumable: false
},
combat_manual: {
id: 'combat_manual',
name: '战斗手册',
type: 'book',
icon: '📗',
baseValue: 150,
readingTime: 180,
expReward: {
reading: 30
},
completionBonus: { critRate: 3 },
description: '记录战斗技巧的手册。',
consumable: false
},
herbalism_book: {
id: 'herbalism_book',
name: '草药图鉴',
type: 'book',
icon: '📙',
baseValue: 120,
readingTime: 150,
expReward: {
reading: 20,
herbalism: 10
},
completionBonus: null,
description: '识别和采集草药的图鉴。',
consumable: false
},
// ===== 素材 =====
dog_skin: {
id: 'dog_skin',
name: '狗皮',
@@ -74,7 +368,74 @@ export const ITEM_CONFIG = {
maxStack: 99
},
// 关键道具
wolf_fang: {
id: 'wolf_fang',
name: '狼牙',
type: 'material',
icon: '🦷',
baseValue: 20,
description: '锋利的狼牙,可用于制作武器。',
stackable: true,
maxStack: 99
},
bat_wing: {
id: 'bat_wing',
name: '蝙蝠翼',
type: 'material',
icon: '🦇',
baseValue: 15,
description: '蝙蝠的翅膀,有特殊用途。',
stackable: true,
maxStack: 99
},
leather: {
id: 'leather',
name: '皮革',
type: 'material',
icon: '🟤',
baseValue: 30,
description: '加工过的兽皮,可用于制作装备。',
stackable: true,
maxStack: 99
},
iron_ore: {
id: 'iron_ore',
name: '铁矿石',
type: 'material',
icon: '⛰️',
baseValue: 50,
description: '含铁的矿石,可以提炼金属。',
stackable: true,
maxStack: 99
},
rare_gem: {
id: 'rare_gem',
name: '稀有宝石',
type: 'material',
icon: '💎',
baseValue: 500,
description: '闪闪发光的宝石,价值不菲。',
stackable: true,
maxStack: 10
},
// ===== 货币 =====
copper_coin: {
id: 'copper_coin',
name: '铜币',
type: 'currency',
icon: '🪙',
baseValue: 1,
description: '通用的货币单位。',
stackable: true,
maxStack: 9999
},
// ===== 关键道具 =====
basement_key: {
id: 'basement_key',
name: '地下室钥匙',
@@ -83,5 +444,71 @@ export const ITEM_CONFIG = {
baseValue: 0,
description: '一把生锈的钥匙上面刻着「B」字母。',
stackable: false
},
cave_key: {
id: 'cave_key',
name: '洞穴钥匙',
type: 'key',
icon: '🗝️',
baseValue: 0,
description: '开启深处洞穴的钥匙。',
stackable: false
},
mystic_key: {
id: 'mystic_key',
name: '神秘钥匙',
type: 'key',
icon: '🔮',
baseValue: 1000,
description: '一把散发着神秘光芒的钥匙,似乎能打开某扇重要的门。',
stackable: false,
keyItem: true
},
// ===== 特殊物品 =====
bomb: {
id: 'bomb',
name: '炸弹',
type: 'special',
subtype: 'explosive',
icon: '💣',
baseValue: 100,
description: '可以造成范围伤害的爆炸物,在战斗中特别有效。',
stackable: true,
maxStack: 10,
effect: {
damage: 50,
radius: 1
},
consumable: true
},
bible: {
id: 'bible',
name: '圣经',
type: 'special',
icon: '📿',
baseValue: 0,
description: '一本神圣的书籍,可以用来祈祷。',
stackable: false,
effect: { sanity: 10 }
}
}
/**
* 获取物品商店分类
* @returns {Object} 分类列表
*/
export const ITEM_CATEGORIES = {
weapon: { id: 'weapon', name: '武器', icon: '⚔️' },
armor: { id: 'armor', name: '防具', icon: '🛡️' },
shield: { id: 'shield', name: '盾牌', icon: '🛡️' },
accessory: { id: 'accessory', name: '饰品', icon: '💍' },
consumable: { id: 'consumable', name: '消耗品', icon: '🧪' },
book: { id: 'book', name: '书籍', icon: '📖' },
material: { id: 'material', name: '素材', icon: '📦' },
key: { id: 'key', name: '钥匙', icon: '🔑' },
special: { id: 'special', name: '特殊', icon: '✨' }
}

View File

@@ -8,7 +8,7 @@ export const LOCATION_CONFIG = {
description: '一个临时的幸存者营地,相对安全。',
connections: ['market', 'blackmarket', 'wild1'],
npcs: ['injured_adventurer'],
activities: ['rest', 'talk', 'trade']
activities: ['rest', 'talk', 'trade', 'crafting']
},
market: {

View File

@@ -49,5 +49,67 @@ export const SKILL_CONFIG = {
10: { desc: '黑暗惩罚-25%', effect: { darkPenaltyReduce: 25 } }
},
unlockCondition: { location: 'basement' }
},
// ===== 制造技能 =====
crafting: {
id: 'crafting',
name: '制造',
type: 'life',
category: 'crafting',
icon: '🔨',
maxLevel: 20,
expPerLevel: (level) => level * 80,
parentSkill: null,
milestones: {
1: { desc: '解锁基础制造配方', effect: {} },
3: { desc: '制造时间-10%', effect: { craftingSpeed: 0.1 } },
5: { desc: '所有制造成功率+5%', effect: { craftingSuccessRate: 5 } },
10: { desc: '制造时间-25%', effect: { craftingSpeed: 0.25 } },
15: { desc: '所有制造成功率+10%', effect: { craftingSuccessRate: 10 } },
20: { desc: '制造品质+10', effect: { craftingQuality: 10 } }
},
unlockCondition: null
},
blacksmith: {
id: 'blacksmith',
name: '锻造',
type: 'life',
category: 'crafting',
icon: '⚒️',
maxLevel: 15,
expPerLevel: (level) => level * 120,
parentSkill: 'crafting',
milestones: {
1: { desc: '解锁武器锻造', effect: {} },
5: { desc: '武器品质+15', effect: { weaponQuality: 15 } },
10: { desc: '防具品质+15', effect: { armorQuality: 15 } },
15: { desc: '所有锻造成功率+15%', effect: { smithingSuccessRate: 15 } }
},
unlockCondition: {
type: 'skill',
skillId: 'crafting',
level: 5
}
},
herbalism: {
id: 'herbalism',
name: '草药学',
type: 'life',
category: 'crafting',
icon: '🌿',
maxLevel: 15,
expPerLevel: (level) => level * 60,
parentSkill: null,
milestones: {
1: { desc: '解锁药水制作', effect: {} },
3: { desc: '药水效果+20%', effect: { potionEffect: 1.2 } },
5: { desc: '解锁高级药水', effect: {} },
10: { desc: '药水效果+50%', effect: { potionEffect: 1.5 } },
15: { desc: '所有制药成功率+20%', effect: { herbingSuccessRate: 20 } }
},
unlockCondition: null
}
}