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:
@@ -5,6 +5,8 @@
|
||||
|
||||
import { SKILL_CONFIG } from '@/config/skills.js'
|
||||
import { ITEM_CONFIG } from '@/config/items.js'
|
||||
import { RECIPE_CONFIG } from '@/config/recipes.js'
|
||||
import { addSkillExp, unlockSkill } from './skillSystem.js'
|
||||
|
||||
/**
|
||||
* 任务类型枚举
|
||||
@@ -16,7 +18,8 @@ export const TASK_TYPES = {
|
||||
WORKING: 'working', // 工作
|
||||
COMBAT: 'combat', // 战斗
|
||||
EXPLORE: 'explore', // 探索
|
||||
PRAYING: 'praying' // 祈祷
|
||||
PRAYING: 'praying', // 祈祷
|
||||
CRAFTING: 'crafting' // 制造
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,15 +30,19 @@ const MUTEX_RULES = {
|
||||
full: [
|
||||
[TASK_TYPES.COMBAT, TASK_TYPES.TRAINING], // 战斗 vs 训练
|
||||
[TASK_TYPES.COMBAT, TASK_TYPES.WORKING], // 战斗 vs 工作
|
||||
[TASK_TYPES.COMBAT, TASK_TYPES.CRAFTING], // 战斗 vs 制造
|
||||
[TASK_TYPES.TRAINING, TASK_TYPES.WORKING], // 训练 vs 工作
|
||||
[TASK_TYPES.EXPLORE, TASK_TYPES.RESTING] // 探索 vs 休息
|
||||
[TASK_TYPES.TRAINING, TASK_TYPES.CRAFTING], // 训练 vs 制造
|
||||
[TASK_TYPES.EXPLORE, TASK_TYPES.RESTING], // 探索 vs 休息
|
||||
[TASK_TYPES.EXPLORE, TASK_TYPES.CRAFTING] // 探索 vs 制造
|
||||
],
|
||||
|
||||
// 部分互斥(需要一心多用技能)
|
||||
partial: [
|
||||
[TASK_TYPES.READING, TASK_TYPES.COMBAT], // 阅读 vs 战斗
|
||||
[TASK_TYPES.READING, TASK_TYPES.TRAINING], // 阅读 vs 训练
|
||||
[TASK_TYPES.READING, TASK_TYPES.WORKING] // 阅读 vs 工作
|
||||
[TASK_TYPES.READING, TASK_TYPES.WORKING], // 阅读 vs 工作
|
||||
[TASK_TYPES.READING, TASK_TYPES.CRAFTING] // 阅读 vs 制造
|
||||
]
|
||||
}
|
||||
|
||||
@@ -182,6 +189,17 @@ function checkTaskConditions(playerStore, taskType, taskData) {
|
||||
return { canStart: false, reason: '需要圣经' }
|
||||
}
|
||||
break
|
||||
|
||||
case TASK_TYPES.CRAFTING:
|
||||
// 需要配方ID
|
||||
if (!taskData.recipeId) {
|
||||
return { canStart: false, reason: '需要选择配方' }
|
||||
}
|
||||
// 需要耐力
|
||||
if (playerStore.currentStats.stamina < 5) {
|
||||
return { canStart: false, reason: '耐力不足' }
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return { canStart: true, reason: '' }
|
||||
@@ -275,6 +293,9 @@ function processSingleTask(gameStore, playerStore, task, deltaTime) {
|
||||
case TASK_TYPES.PRAYING:
|
||||
return processPrayingTask(gameStore, playerStore, task, elapsedSeconds)
|
||||
|
||||
case TASK_TYPES.CRAFTING:
|
||||
return processCraftingTask(gameStore, playerStore, task, elapsedSeconds)
|
||||
|
||||
default:
|
||||
return { completed: false }
|
||||
}
|
||||
@@ -491,6 +512,134 @@ function processPrayingTask(gameStore, playerStore, task, elapsedSeconds) {
|
||||
return { completed: false }
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理制造任务
|
||||
*/
|
||||
function processCraftingTask(gameStore, playerStore, task, elapsedSeconds) {
|
||||
const recipeId = task.data.recipeId
|
||||
const recipe = RECIPE_CONFIG[recipeId]
|
||||
|
||||
if (!recipe) {
|
||||
return { completed: true, error: '配方不存在' }
|
||||
}
|
||||
|
||||
// 消耗耐力(制造也需要体力)
|
||||
const staminaCost = 1 * elapsedSeconds
|
||||
if (playerStore.currentStats.stamina < staminaCost) {
|
||||
return { completed: true, rewards: {}, failed: true }
|
||||
}
|
||||
|
||||
playerStore.currentStats.stamina -= staminaCost
|
||||
|
||||
// 计算实际制造时间(受技能加成影响)
|
||||
const craftingSkill = playerStore.skills[recipe.requiredSkill]
|
||||
let timeMultiplier = 1.0
|
||||
|
||||
if (craftingSkill && craftingSkill.level > 0) {
|
||||
// 制造技能每级减少5%时间
|
||||
timeMultiplier = 1 - (Math.min(craftingSkill.level, 20) * 0.05)
|
||||
}
|
||||
|
||||
// 累积制造进度(考虑时间加成)
|
||||
const effectiveProgress = task.progress * timeMultiplier
|
||||
|
||||
// 检查是否完成
|
||||
if (effectiveProgress >= recipe.baseTime) {
|
||||
// 计算成功率
|
||||
const successRate = calculateCraftingSuccessRate(playerStore, recipe)
|
||||
|
||||
// 判定是否成功
|
||||
const success = Math.random() < successRate
|
||||
|
||||
if (success) {
|
||||
// 给予制造技能经验
|
||||
const expGain = recipe.baseTime * 0.5 // 基于制造时间的经验
|
||||
|
||||
if (!task.accumulatedExp) {
|
||||
task.accumulatedExp = {}
|
||||
}
|
||||
if (!task.accumulatedExp[recipe.requiredSkill]) {
|
||||
task.accumulatedExp[recipe.requiredSkill] = 0
|
||||
}
|
||||
task.accumulatedExp[recipe.requiredSkill] += expGain
|
||||
|
||||
const rewards = {
|
||||
[recipe.requiredSkill]: task.accumulatedExp[recipe.requiredSkill] || 0,
|
||||
craftedItem: recipe.resultItem,
|
||||
craftedCount: recipe.resultCount
|
||||
}
|
||||
|
||||
// 添加制造物品到背包(这将在任务完成回调中处理)
|
||||
if (gameStore.addLog) {
|
||||
const itemConfig = ITEM_CONFIG[recipe.resultItem]
|
||||
gameStore.addLog(`制造成功:${itemConfig?.name || recipe.resultItem}`, 'reward')
|
||||
}
|
||||
|
||||
return { completed: true, rewards, success: true }
|
||||
} else {
|
||||
// 制造失败
|
||||
if (gameStore.addLog) {
|
||||
gameStore.addLog(`制造失败:${recipeId}`, 'warning')
|
||||
}
|
||||
|
||||
// 失败也给予少量经验
|
||||
const expGain = recipe.baseTime * 0.1
|
||||
if (!task.accumulatedExp) {
|
||||
task.accumulatedExp = {}
|
||||
}
|
||||
if (!task.accumulatedExp[recipe.requiredSkill]) {
|
||||
task.accumulatedExp[recipe.requiredSkill] = 0
|
||||
}
|
||||
task.accumulatedExp[recipe.requiredSkill] += expGain
|
||||
|
||||
const rewards = {
|
||||
[recipe.requiredSkill]: task.accumulatedExp[recipe.requiredSkill] || 0
|
||||
}
|
||||
|
||||
return { completed: true, rewards, success: false }
|
||||
}
|
||||
}
|
||||
|
||||
// 进行中,给予少量经验
|
||||
const expPerTick = 0.5 * elapsedSeconds
|
||||
if (!task.accumulatedExp) {
|
||||
task.accumulatedExp = {}
|
||||
}
|
||||
if (!task.accumulatedExp[recipe.requiredSkill]) {
|
||||
task.accumulatedExp[recipe.requiredSkill] = 0
|
||||
}
|
||||
task.accumulatedExp[recipe.requiredSkill] += expPerTick
|
||||
|
||||
return { completed: false }
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算制造成功率
|
||||
* @param {Object} playerStore - 玩家Store
|
||||
* @param {Object} recipe - 配方对象
|
||||
* @returns {Number} 成功率 (0-1)
|
||||
*/
|
||||
function calculateCraftingSuccessRate(playerStore, recipe) {
|
||||
let successRate = recipe.baseSuccessRate
|
||||
|
||||
// 技能等级加成(每级+2%)
|
||||
const skill = playerStore.skills[recipe.requiredSkill]
|
||||
if (skill && skill.level > 0) {
|
||||
successRate += Math.min(skill.level, 20) * 0.02
|
||||
}
|
||||
|
||||
// 运气加成
|
||||
const luck = playerStore.baseStats?.luck || 10
|
||||
successRate += luck * 0.001
|
||||
|
||||
// 检查是否有制造技能的全局加成
|
||||
if (playerStore.globalBonus?.craftingSuccessRate) {
|
||||
successRate += playerStore.globalBonus.craftingSuccessRate / 100
|
||||
}
|
||||
|
||||
return Math.min(0.98, Math.max(0.05, successRate))
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务奖励
|
||||
*/
|
||||
@@ -521,17 +670,17 @@ function applyTaskRewards(playerStore, task, rewards) {
|
||||
continue
|
||||
}
|
||||
if (skillId === 'faith') {
|
||||
// 信仰技能经验
|
||||
// 信仰技能经验 - 使用addSkillExp处理
|
||||
if (!playerStore.skills.faith) {
|
||||
playerStore.skills.faith = { level: 0, exp: 0, unlocked: true }
|
||||
unlockSkill(playerStore, 'faith')
|
||||
}
|
||||
playerStore.skills.faith.exp += exp
|
||||
addSkillExp(playerStore, 'faith', exp)
|
||||
continue
|
||||
}
|
||||
|
||||
// 普通技能经验
|
||||
// 普通技能经验 - 使用addSkillExp处理升级和里程碑
|
||||
if (playerStore.skills[skillId]) {
|
||||
playerStore.skills[skillId].exp += exp
|
||||
addSkillExp(playerStore, skillId, exp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -547,7 +696,8 @@ function getTaskTypeName(taskType) {
|
||||
working: '工作',
|
||||
combat: '战斗',
|
||||
explore: '探索',
|
||||
praying: '祈祷'
|
||||
praying: '祈祷',
|
||||
crafting: '制造'
|
||||
}
|
||||
return names[taskType] || taskType
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user