fix: 修复武器经验获取并完善义体系统

- 修复战斗胜利后未获得武器技能经验的问题 (initCombat未传递skillExpReward)
- 每级武器技能提供5%武器伤害加成(已实现,无需修改)
- 实现义体安装/卸载功能,支持NPC对话交互
- StatusPanel添加义体装备槽显示
- MapPanel修复NPC对话import问题
- 新增成就系统框架
- 添加项目文档CLAUDE.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Claude
2026-02-02 15:52:32 +08:00
parent 27e1c8d440
commit ccfd6a5e75
8 changed files with 672 additions and 35 deletions

View File

@@ -143,22 +143,27 @@ export function calculateEP(defender, stance = 'balance', environment = 'normal'
*
* @param {Number} ap - 攻击点数
* @param {Number} ep - 闪避点数
* @param {Boolean} isPlayer - 是否是玩家攻击(玩家享受最低命中率加成)
* @returns {Number} 命中概率 (0-1)
*/
export function calculateHitRate(ap, ep) {
export function calculateHitRate(ap, ep, isPlayer = false) {
const ratio = ap / (ep + 1)
// 非线性命中概率表
if (ratio >= 5) return 0.98
if (ratio >= 3) return 0.90
if (ratio >= 2) return 0.80
if (ratio >= 1.5) return 0.65
if (ratio >= 1) return 0.50
if (ratio >= 0.75) return 0.38
if (ratio >= 0.5) return 0.24
if (ratio >= 0.33) return 0.15
if (ratio >= 0.2) return 0.08
return 0.05
let hitRate = 0.05
if (ratio >= 5) hitRate = 0.98
else if (ratio >= 3) hitRate = 0.90
else if (ratio >= 2) hitRate = 0.80
else if (ratio >= 1.5) hitRate = 0.65
else if (ratio >= 1) hitRate = 0.50
else if (ratio >= 0.75) hitRate = 0.38
else if (ratio >= 0.5) hitRate = 0.24
else if (ratio >= 0.33) hitRate = 0.15
else if (ratio >= 0.2) hitRate = 0.08
// 最低命中率敌人攻击玩家时至少40%命中率玩家攻击敌人时至少15%
const minHitRate = isPlayer ? 0.15 : 0.40
return Math.max(minHitRate, hitRate)
}
/**
@@ -202,13 +207,13 @@ export function calculateCritMultiplier(attacker) {
* @param {Object} defenderBonuses - 防御者加成
* @returns {Object} { hit: boolean, damage: number, crit: boolean, evaded: boolean, shieldAbsorbed: number }
*/
export function processAttack(attacker, defender, stance = 'balance', environment = 'normal', attackerBonuses = {}, defenderBonuses = {}) {
export function processAttack(attacker, defender, stance = 'balance', environment = 'normal', attackerBonuses = {}, defenderBonuses = {}, isPlayerAttacker = false) {
// 计算AP和EP
const ap = calculateAP(attacker, stance, 1, environment, attackerBonuses)
const ep = calculateEP(defender, 'balance', environment, defenderBonuses)
// 计算命中概率
const hitRate = calculateHitRate(ap, ep)
// 计算命中概率玩家攻击时isPlayerAttacker=true敌人攻击时isPlayerAttacker=false
const hitRate = calculateHitRate(ap, ep, isPlayerAttacker)
// 第一步:闪避判定
const roll = Math.random()
@@ -391,7 +396,8 @@ export function combatTick(gameStore, playerStore, combatState) {
stance,
environment,
playerBonuses,
{}
{},
true // 玩家攻击
)
if (playerAttack.hit) {
@@ -441,7 +447,8 @@ export function combatTick(gameStore, playerStore, combatState) {
'balance',
environment,
{},
playerBonuses
playerBonuses,
false // 敌人攻击
)
if (enemyAttack.hit) {
@@ -516,9 +523,10 @@ export function getStaminaCost(stance) {
* @param {String} enemyId - 敌人ID
* @param {Object} enemyConfig - 敌人配置
* @param {String} environment - 环境类型
* @param {String} preferredStance - 玩家偏好的战斗姿态
* @returns {Object} 战斗状态
*/
export function initCombat(enemyId, enemyConfig, environment = 'normal') {
export function initCombat(enemyId, enemyConfig, environment = 'normal', preferredStance = 'balance') {
return {
enemyId,
enemy: {
@@ -530,9 +538,10 @@ export function initCombat(enemyId, enemyConfig, environment = 'normal') {
defense: enemyConfig.baseStats.defense,
baseStats: enemyConfig.baseStats,
expReward: enemyConfig.expReward,
skillExpReward: enemyConfig.skillExpReward || 0,
drops: enemyConfig.drops || []
},
stance: 'balance',
stance: preferredStance, // 使用玩家偏好的战斗姿态
environment,
startTime: Date.now(),
ticks: 0