570 lines
15 KiB
JavaScript
570 lines
15 KiB
JavaScript
|
|
/**
|
|||
|
|
* 物品系统 - 使用/装备/品质计算
|
|||
|
|
* Phase 6 核心系统实现
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
import { ITEM_CONFIG } from '@/config/items.js'
|
|||
|
|
import { GAME_CONSTANTS } from '@/config/constants.js'
|
|||
|
|
import { SKILL_CONFIG } from '@/config/skills.js'
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 计算装备品质后的属性
|
|||
|
|
* @param {String} itemId - 物品ID
|
|||
|
|
* @param {Number} quality - 品质值 (0-250)
|
|||
|
|
* @returns {Object|null} 计算后的属性
|
|||
|
|
*/
|
|||
|
|
export function calculateItemStats(itemId, quality = 100) {
|
|||
|
|
const config = ITEM_CONFIG[itemId]
|
|||
|
|
if (!config) {
|
|||
|
|
return null
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const qualityLevel = getQualityLevel(quality)
|
|||
|
|
const qualityMultiplier = qualityLevel.multiplier
|
|||
|
|
|
|||
|
|
const stats = {
|
|||
|
|
id: itemId,
|
|||
|
|
name: config.name,
|
|||
|
|
type: config.type,
|
|||
|
|
subtype: config.subtype,
|
|||
|
|
description: config.description,
|
|||
|
|
icon: config.icon,
|
|||
|
|
quality: quality,
|
|||
|
|
qualityLevel: qualityLevel.level,
|
|||
|
|
qualityName: qualityLevel.name,
|
|||
|
|
qualityColor: qualityLevel.color
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 应用品质百分比到基础属性
|
|||
|
|
const qualityRatio = quality / 100
|
|||
|
|
|
|||
|
|
if (config.baseDamage) {
|
|||
|
|
stats.baseDamage = config.baseDamage
|
|||
|
|
stats.finalDamage = Math.floor(config.baseDamage * qualityRatio * qualityMultiplier)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (config.baseDefense) {
|
|||
|
|
stats.baseDefense = config.baseDefense
|
|||
|
|
stats.finalDefense = Math.floor(config.baseDefense * qualityRatio * qualityMultiplier)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (config.baseShield) {
|
|||
|
|
stats.baseShield = config.baseShield
|
|||
|
|
stats.finalShield = Math.floor(config.baseShield * qualityRatio * qualityMultiplier)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (config.attackSpeed) {
|
|||
|
|
stats.attackSpeed = config.attackSpeed
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 计算价值
|
|||
|
|
stats.baseValue = config.baseValue || 0
|
|||
|
|
stats.finalValue = Math.floor(config.baseValue * qualityRatio * qualityMultiplier)
|
|||
|
|
|
|||
|
|
// 消耗品效果
|
|||
|
|
if (config.effect) {
|
|||
|
|
stats.effect = { ...config.effect }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 书籍信息
|
|||
|
|
if (config.type === 'book') {
|
|||
|
|
stats.readingTime = config.readingTime
|
|||
|
|
stats.expReward = { ...config.expReward }
|
|||
|
|
stats.completionBonus = config.completionBonus
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 解锁技能
|
|||
|
|
if (config.unlockSkill) {
|
|||
|
|
stats.unlockSkill = config.unlockSkill
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 堆叠信息
|
|||
|
|
if (config.stackable !== undefined) {
|
|||
|
|
stats.stackable = config.stackable
|
|||
|
|
stats.maxStack = config.maxStack || 99
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return stats
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取品质等级
|
|||
|
|
* @param {Number} quality - 品质值
|
|||
|
|
* @returns {Object} 品质等级信息
|
|||
|
|
*/
|
|||
|
|
export function getQualityLevel(quality) {
|
|||
|
|
// 确保品质在有效范围内
|
|||
|
|
const clampedQuality = Math.max(0, Math.min(250, quality))
|
|||
|
|
|
|||
|
|
for (const [level, data] of Object.entries(GAME_CONSTANTS.QUALITY_LEVELS)) {
|
|||
|
|
if (clampedQuality >= data.range[0] && clampedQuality <= data.range[1]) {
|
|||
|
|
return {
|
|||
|
|
level: parseInt(level),
|
|||
|
|
...data
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 默认返回垃圾品质
|
|||
|
|
return GAME_CONSTANTS.QUALITY_LEVELS[1]
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 生成随机品质
|
|||
|
|
* @param {Number} luck - 运气值 (0-100),影响高品质概率
|
|||
|
|
* @returns {Number} 品质值
|
|||
|
|
*/
|
|||
|
|
export function generateRandomQuality(luck = 0) {
|
|||
|
|
// 基础品质范围 50-150
|
|||
|
|
const baseMin = 50
|
|||
|
|
const baseMax = 150
|
|||
|
|
|
|||
|
|
// 运气加成:每1点运气增加0.5品质
|
|||
|
|
const luckBonus = luck * 0.5
|
|||
|
|
|
|||
|
|
// 随机品质
|
|||
|
|
let quality = Math.floor(Math.random() * (baseMax - baseMin + 1)) + baseMin + luckBonus
|
|||
|
|
|
|||
|
|
// 小概率生成高品质(传说)
|
|||
|
|
if (Math.random() < 0.01 + luck / 10000) {
|
|||
|
|
quality = 180 + Math.floor(Math.random() * 70) // 180-250
|
|||
|
|
}
|
|||
|
|
// 史诗品质
|
|||
|
|
else if (Math.random() < 0.05 + luck / 2000) {
|
|||
|
|
quality = 160 + Math.floor(Math.random() * 40) // 160-199
|
|||
|
|
}
|
|||
|
|
// 稀有品质
|
|||
|
|
else if (Math.random() < 0.15 + luck / 500) {
|
|||
|
|
quality = 130 + Math.floor(Math.random() * 30) // 130-159
|
|||
|
|
}
|
|||
|
|
// 优秀品质
|
|||
|
|
else if (Math.random() < 0.3 + luck / 200) {
|
|||
|
|
quality = 100 + Math.floor(Math.random() * 30) // 100-129
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return Math.min(250, Math.max(0, Math.floor(quality)))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 使用物品
|
|||
|
|
* @param {Object} playerStore - 玩家Store
|
|||
|
|
* @param {Object} gameStore - 游戏Store
|
|||
|
|
* @param {String} itemId - 物品ID
|
|||
|
|
* @param {Number} count - 使用数量
|
|||
|
|
* @returns {Object} { success: boolean, message: string, effects: Object }
|
|||
|
|
*/
|
|||
|
|
export function useItem(playerStore, gameStore, itemId, count = 1) {
|
|||
|
|
const config = ITEM_CONFIG[itemId]
|
|||
|
|
if (!config) {
|
|||
|
|
return { success: false, message: '物品不存在' }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 查找背包中的物品
|
|||
|
|
const itemIndex = playerStore.inventory.findIndex(i => i.id === itemId)
|
|||
|
|
if (itemIndex === -1) {
|
|||
|
|
return { success: false, message: '背包中没有该物品' }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const inventoryItem = playerStore.inventory[itemIndex]
|
|||
|
|
|
|||
|
|
// 检查数量
|
|||
|
|
if (inventoryItem.count < count) {
|
|||
|
|
return { success: false, message: '物品数量不足' }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 根据物品类型处理
|
|||
|
|
if (config.type === 'consumable') {
|
|||
|
|
return useConsumable(playerStore, gameStore, config, inventoryItem, count, itemIndex)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (config.type === 'book') {
|
|||
|
|
return useBook(playerStore, gameStore, config, inventoryItem)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return { success: false, message: '该物品无法使用' }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 使用消耗品
|
|||
|
|
*/
|
|||
|
|
function useConsumable(playerStore, gameStore, config, inventoryItem, count, itemIndex) {
|
|||
|
|
const effects = {}
|
|||
|
|
const appliedEffects = []
|
|||
|
|
|
|||
|
|
// 应用效果
|
|||
|
|
if (config.effect) {
|
|||
|
|
if (config.effect.health) {
|
|||
|
|
const oldHealth = playerStore.currentStats.health
|
|||
|
|
playerStore.currentStats.health = Math.min(
|
|||
|
|
playerStore.currentStats.maxHealth,
|
|||
|
|
playerStore.currentStats.health + config.effect.health * count
|
|||
|
|
)
|
|||
|
|
effects.health = playerStore.currentStats.health - oldHealth
|
|||
|
|
if (effects.health > 0) appliedEffects.push(`恢复${effects.health}生命`)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (config.effect.stamina) {
|
|||
|
|
const oldStamina = playerStore.currentStats.stamina
|
|||
|
|
playerStore.currentStats.stamina = Math.min(
|
|||
|
|
playerStore.currentStats.maxStamina,
|
|||
|
|
playerStore.currentStats.stamina + config.effect.stamina * count
|
|||
|
|
)
|
|||
|
|
effects.stamina = playerStore.currentStats.stamina - oldStamina
|
|||
|
|
if (effects.stamina > 0) appliedEffects.push(`恢复${effects.stamina}耐力`)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (config.effect.sanity) {
|
|||
|
|
const oldSanity = playerStore.currentStats.sanity
|
|||
|
|
playerStore.currentStats.sanity = Math.min(
|
|||
|
|
playerStore.currentStats.maxSanity,
|
|||
|
|
playerStore.currentStats.sanity + config.effect.sanity * count
|
|||
|
|
)
|
|||
|
|
effects.sanity = playerStore.currentStats.sanity - oldSanity
|
|||
|
|
if (effects.sanity > 0) appliedEffects.push(`恢复${effects.sanity}精神`)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 消耗物品
|
|||
|
|
inventoryItem.count -= count
|
|||
|
|
if (inventoryItem.count <= 0) {
|
|||
|
|
playerStore.inventory.splice(itemIndex, 1)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 记录日志
|
|||
|
|
const effectText = appliedEffects.length > 0 ? appliedEffects.join('、') : '使用'
|
|||
|
|
if (gameStore.addLog) {
|
|||
|
|
gameStore.addLog(`使用了 ${config.name} x${count},${effectText}`, 'info')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
success: true,
|
|||
|
|
message: effectText,
|
|||
|
|
effects
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 使用书籍(阅读)
|
|||
|
|
*/
|
|||
|
|
function useBook(playerStore, gameStore, config, inventoryItem) {
|
|||
|
|
// 书籍不消耗,返回阅读任务信息
|
|||
|
|
return {
|
|||
|
|
success: true,
|
|||
|
|
message: '开始阅读',
|
|||
|
|
readingTask: {
|
|||
|
|
itemId: config.id,
|
|||
|
|
bookName: config.name,
|
|||
|
|
readingTime: config.readingTime,
|
|||
|
|
expReward: config.expReward,
|
|||
|
|
completionBonus: config.completionBonus
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 装备物品
|
|||
|
|
* @param {Object} playerStore - 玩家Store
|
|||
|
|
* @param {Object} gameStore - 游戏Store
|
|||
|
|
* @param {String} uniqueId - 物品唯一ID(背包中的物品)
|
|||
|
|
* @returns {Object} { success: boolean, message: string }
|
|||
|
|
*/
|
|||
|
|
export function equipItem(playerStore, gameStore, uniqueId) {
|
|||
|
|
const inventoryItem = playerStore.inventory.find(i => i.uniqueId === uniqueId)
|
|||
|
|
if (!inventoryItem) {
|
|||
|
|
return { success: false, message: '物品不存在' }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const config = ITEM_CONFIG[inventoryItem.id]
|
|||
|
|
if (!config) {
|
|||
|
|
return { success: false, message: '物品配置不存在' }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 确定装备槽位
|
|||
|
|
let slot = config.type
|
|||
|
|
if (config.subtype === 'one_handed' || config.subtype === 'two_handed') {
|
|||
|
|
slot = 'weapon'
|
|||
|
|
} else if (config.type === 'armor') {
|
|||
|
|
slot = 'armor'
|
|||
|
|
} else if (config.type === 'shield') {
|
|||
|
|
slot = 'shield'
|
|||
|
|
} else if (config.type === 'accessory') {
|
|||
|
|
slot = 'accessory'
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!slot || !playerStore.equipment.hasOwnProperty(slot)) {
|
|||
|
|
return { success: false, message: '无法装备该物品' }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果已有装备,先卸下
|
|||
|
|
const currentlyEquipped = playerStore.equipment[slot]
|
|||
|
|
if (currentlyEquipped) {
|
|||
|
|
unequipItemBySlot(playerStore, gameStore, slot)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 装备新物品
|
|||
|
|
playerStore.equipment[slot] = inventoryItem
|
|||
|
|
inventoryItem.equipped = true
|
|||
|
|
|
|||
|
|
// 应用装备属性
|
|||
|
|
applyEquipmentStats(playerStore, slot, inventoryItem)
|
|||
|
|
|
|||
|
|
// 记录日志
|
|||
|
|
if (gameStore.addLog) {
|
|||
|
|
gameStore.addLog(`装备了 ${inventoryItem.name}`, 'info')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return { success: true, message: '装备成功' }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 卸下装备
|
|||
|
|
* @param {Object} playerStore - 玩家Store
|
|||
|
|
* @param {Object} gameStore - 游戏Store
|
|||
|
|
* @param {String} slot - 装备槽位
|
|||
|
|
* @returns {Object} { success: boolean, message: string }
|
|||
|
|
*/
|
|||
|
|
export function unequipItemBySlot(playerStore, gameStore, slot) {
|
|||
|
|
const equipped = playerStore.equipment[slot]
|
|||
|
|
if (!equipped) {
|
|||
|
|
return { success: false, message: '该槽位没有装备' }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 移除装备属性
|
|||
|
|
removeEquipmentStats(playerStore, slot)
|
|||
|
|
|
|||
|
|
// 标记为未装备
|
|||
|
|
equipped.equipped = false
|
|||
|
|
|
|||
|
|
// 清空槽位
|
|||
|
|
playerStore.equipment[slot] = null
|
|||
|
|
|
|||
|
|
// 记录日志
|
|||
|
|
if (gameStore.addLog) {
|
|||
|
|
gameStore.addLog(`卸下了 ${equipped.name}`, 'info')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return { success: true, message: '卸下成功' }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 应用装备属性到玩家
|
|||
|
|
*/
|
|||
|
|
function applyEquipmentStats(playerStore, slot, item) {
|
|||
|
|
if (!playerStore.equipmentStats) {
|
|||
|
|
playerStore.equipmentStats = {
|
|||
|
|
attack: 0,
|
|||
|
|
defense: 0,
|
|||
|
|
shield: 0,
|
|||
|
|
critRate: 0,
|
|||
|
|
attackSpeed: 1
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (item.finalDamage) {
|
|||
|
|
playerStore.equipmentStats.attack += item.finalDamage
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (item.finalDefense) {
|
|||
|
|
playerStore.equipmentStats.defense += item.finalDefense
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (item.finalShield) {
|
|||
|
|
playerStore.equipmentStats.shield += item.finalShield
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (item.attackSpeed) {
|
|||
|
|
playerStore.equipmentStats.attackSpeed *= item.attackSpeed
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 移除装备属性
|
|||
|
|
*/
|
|||
|
|
function removeEquipmentStats(playerStore, slot) {
|
|||
|
|
const equipped = playerStore.equipment[slot]
|
|||
|
|
if (!equipped || !playerStore.equipmentStats) {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (equipped.finalDamage) {
|
|||
|
|
playerStore.equipmentStats.attack -= equipped.finalDamage
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (equipped.finalDefense) {
|
|||
|
|
playerStore.equipmentStats.defense -= equipped.finalDefense
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (equipped.finalShield) {
|
|||
|
|
playerStore.equipmentStats.shield -= equipped.finalShield
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 添加物品到背包
|
|||
|
|
* @param {Object} playerStore - 玩家Store
|
|||
|
|
* @param {String} itemId - 物品ID
|
|||
|
|
* @param {Number} count - 数量
|
|||
|
|
* @param {Number} quality - 品质(装备用)
|
|||
|
|
* @returns {Object} { success: boolean, item: Object }
|
|||
|
|
*/
|
|||
|
|
export function addItemToInventory(playerStore, itemId, count = 1, quality = null) {
|
|||
|
|
const config = ITEM_CONFIG[itemId]
|
|||
|
|
if (!config) {
|
|||
|
|
return { success: false, message: '物品不存在' }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 素材和关键道具不需要品质,使用固定值
|
|||
|
|
// 装备类物品才需要随机品质
|
|||
|
|
const needsQuality = config.type === 'weapon' || config.type === 'armor' ||
|
|||
|
|
config.type === 'shield' || config.type === 'accessory'
|
|||
|
|
const itemQuality = quality !== null ? quality
|
|||
|
|
: (needsQuality ? generateRandomQuality(playerStore.baseStats?.intuition || 0) : 100)
|
|||
|
|
|
|||
|
|
// 计算物品属性
|
|||
|
|
const itemStats = calculateItemStats(itemId, itemQuality)
|
|||
|
|
|
|||
|
|
// 堆叠物品 - 只需要匹配ID,不需要匹配品质(素材类物品)
|
|||
|
|
if (config.stackable) {
|
|||
|
|
const existingItem = playerStore.inventory.find(i => i.id === itemId)
|
|||
|
|
if (existingItem) {
|
|||
|
|
existingItem.count += count
|
|||
|
|
return { success: true, item: existingItem }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 创建新物品
|
|||
|
|
const newItem = {
|
|||
|
|
...itemStats,
|
|||
|
|
uniqueId: `${itemId}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|||
|
|
count,
|
|||
|
|
equipped: false,
|
|||
|
|
obtainedAt: Date.now()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
playerStore.inventory.push(newItem)
|
|||
|
|
|
|||
|
|
return { success: true, item: newItem }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 从背包移除物品
|
|||
|
|
* @param {Object} playerStore - 玩家Store
|
|||
|
|
* @param {String} uniqueId - 物品唯一ID
|
|||
|
|
* @param {Number} count - 移除数量
|
|||
|
|
* @returns {Object} { success: boolean, message: string }
|
|||
|
|
*/
|
|||
|
|
export function removeItemFromInventory(playerStore, uniqueId, count = 1) {
|
|||
|
|
const itemIndex = playerStore.inventory.findIndex(i => i.uniqueId === uniqueId)
|
|||
|
|
if (itemIndex === -1) {
|
|||
|
|
return { success: false, message: '物品不存在' }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const item = playerStore.inventory[itemIndex]
|
|||
|
|
|
|||
|
|
if (item.count < count) {
|
|||
|
|
return { success: false, message: '物品数量不足' }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
item.count -= count
|
|||
|
|
|
|||
|
|
if (item.count <= 0) {
|
|||
|
|
// 如果已装备,先卸下
|
|||
|
|
if (item.equipped) {
|
|||
|
|
for (const [slot, equipped] of Object.entries(playerStore.equipment)) {
|
|||
|
|
if (equipped && equipped.uniqueId === uniqueId) {
|
|||
|
|
playerStore.equipment[slot] = null
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
playerStore.inventory.splice(itemIndex, 1)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return { success: true, message: '移除成功' }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 检查是否拥有物品
|
|||
|
|
* @param {Object} playerStore - 玩家Store
|
|||
|
|
* @param {String} itemId - 物品ID
|
|||
|
|
* @returns {Boolean}
|
|||
|
|
*/
|
|||
|
|
export function hasItem(playerStore, itemId) {
|
|||
|
|
return playerStore.inventory.some(i => i.id === itemId && i.count > 0)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取物品数量
|
|||
|
|
* @param {Object} playerStore - 玩家Store
|
|||
|
|
* @param {String} itemId - 物品ID
|
|||
|
|
* @returns {Number}
|
|||
|
|
*/
|
|||
|
|
export function getItemCount(playerStore, itemId) {
|
|||
|
|
const item = playerStore.inventory.find(i => i.id === itemId)
|
|||
|
|
return item ? item.count : 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 检查装备是否解锁技能
|
|||
|
|
* @param {Object} playerStore - 玩家Store
|
|||
|
|
* @param {String} itemId - 物品ID
|
|||
|
|
* @returns {String|null} 解锁的技能ID
|
|||
|
|
*/
|
|||
|
|
export function checkSkillUnlock(playerStore, itemId) {
|
|||
|
|
const config = ITEM_CONFIG[itemId]
|
|||
|
|
if (!config || !config.unlockSkill) {
|
|||
|
|
return null
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const skillId = config.unlockSkill
|
|||
|
|
|
|||
|
|
// 检查技能是否已解锁
|
|||
|
|
if (playerStore.skills[skillId] && playerStore.skills[skillId].unlocked) {
|
|||
|
|
return null
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return skillId
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 计算物品出售价格
|
|||
|
|
* @param {Object} item - 物品对象
|
|||
|
|
* @param {Number} marketRate - 市场价格倍率 (0.1-2.0)
|
|||
|
|
* @returns {Number} 出售价格(铜币)
|
|||
|
|
*/
|
|||
|
|
export function calculateSellPrice(item, marketRate = 0.3) {
|
|||
|
|
const basePrice = item.finalValue || item.baseValue || 0
|
|||
|
|
return Math.max(1, Math.floor(basePrice * marketRate))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 计算物品购买价格
|
|||
|
|
* @param {Object} item - 物品对象
|
|||
|
|
* @param {Number} marketRate - 市场价格倍率 (1.0-3.0)
|
|||
|
|
* @returns {Number} 购买价格(铜币)
|
|||
|
|
*/
|
|||
|
|
export function calculateBuyPrice(item, marketRate = 2.0) {
|
|||
|
|
const basePrice = item.finalValue || item.baseValue || 0
|
|||
|
|
return Math.max(1, Math.floor(basePrice * marketRate))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取品质颜色
|
|||
|
|
* @param {Number} quality - 品质值
|
|||
|
|
* @returns {String} 颜色代码
|
|||
|
|
*/
|
|||
|
|
export function getQualityColor(quality) {
|
|||
|
|
const level = getQualityLevel(quality)
|
|||
|
|
return level.color
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取品质名称
|
|||
|
|
* @param {Number} quality - 品质值
|
|||
|
|
* @returns {String} 品质名称
|
|||
|
|
*/
|
|||
|
|
export function getQualityName(quality) {
|
|||
|
|
const level = getQualityLevel(quality)
|
|||
|
|
return level.name
|
|||
|
|
}
|