150 lines
6.2 KiB
JavaScript
150 lines
6.2 KiB
JavaScript
|
|
/**
|
||
|
|
* 数值模型验证脚本
|
||
|
|
* 运行: node tests/verify-model.js
|
||
|
|
*/
|
||
|
|
|
||
|
|
// 游戏常量
|
||
|
|
const GAME_CONSTANTS = {
|
||
|
|
QUALITY_LEVELS: {
|
||
|
|
1: { name: '垃圾', color: '#6b7280', range: [0, 49], multiplier: 0.5 },
|
||
|
|
2: { name: '普通', color: '#ffffff', range: [50, 99], multiplier: 1.0 },
|
||
|
|
3: { name: '优秀', color: '#22c55e', range: [100, 139], multiplier: 1.2 },
|
||
|
|
4: { name: '稀有', color: '#3b82f6', range: [140, 169], multiplier: 1.5 },
|
||
|
|
5: { name: '史诗', color: '#a855f7', range: [170, 199], multiplier: 2.0 },
|
||
|
|
6: { name: '传说', color: '#f59e0b', range: [200, 250], multiplier: 3.0 }
|
||
|
|
},
|
||
|
|
QUALITY: { BASE_MULTIPLIER: 0.01 },
|
||
|
|
STAT_SCALING: {
|
||
|
|
STRENGTH_TO_ATTACK: 1.0,
|
||
|
|
AGILITY_TO_DODGE: 0.5,
|
||
|
|
DEXTERITY_TO_CRIT: 0.3,
|
||
|
|
VITALITY_TO_HP: 10,
|
||
|
|
VITALITY_TO_REGEN: 0.05
|
||
|
|
},
|
||
|
|
MONSTER: {
|
||
|
|
HP_SCALING: 1.12,
|
||
|
|
ATTACK_SCALING: 1.08,
|
||
|
|
DEFENSE_SCALING: 1.06,
|
||
|
|
EXP_SCALING: 1.10
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== 计算函数 ====================
|
||
|
|
|
||
|
|
function calculateCharacterStats(baseStats, level = 1) {
|
||
|
|
const s = GAME_CONSTANTS.STAT_SCALING
|
||
|
|
return {
|
||
|
|
hp: Math.floor(100 + (baseStats.vitality || 10) * s.VITALITY_TO_HP + level * 5),
|
||
|
|
attack: Math.floor((baseStats.strength || 10) * s.STRENGTH_TO_ATTACK + level * 2),
|
||
|
|
critRate: 5 + (baseStats.dexterity || 8) * s.DEXTERITY_TO_CRIT
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function calculateEquipmentStats(baseDamage, quality, itemLevel = 1) {
|
||
|
|
const qualityMultiplier = 1 + (quality - 100) * GAME_CONSTANTS.QUALITY.BASE_MULTIPLIER
|
||
|
|
const levelMultiplier = 1 + (itemLevel - 1) * 0.02
|
||
|
|
return Math.floor(baseDamage * qualityMultiplier * levelMultiplier)
|
||
|
|
}
|
||
|
|
|
||
|
|
function calculateMonsterStats(baseHp, level) {
|
||
|
|
return Math.floor(baseHp * Math.pow(GAME_CONSTANTS.MONSTER.HP_SCALING, level - 1))
|
||
|
|
}
|
||
|
|
|
||
|
|
function getExpForLevel(level) {
|
||
|
|
return Math.floor(100 * Math.pow(1.15, level - 2) * (level - 1) * 0.8)
|
||
|
|
}
|
||
|
|
|
||
|
|
function getQualityLevel(quality) {
|
||
|
|
if (quality < 50) return GAME_CONSTANTS.QUALITY_LEVELS[1]
|
||
|
|
if (quality < 100) return GAME_CONSTANTS.QUALITY_LEVELS[2]
|
||
|
|
if (quality < 140) return GAME_CONSTANTS.QUALITY_LEVELS[3]
|
||
|
|
if (quality < 170) return GAME_CONSTANTS.QUALITY_LEVELS[4]
|
||
|
|
if (quality < 200) return GAME_CONSTANTS.QUALITY_LEVELS[5]
|
||
|
|
return GAME_CONSTANTS.QUALITY_LEVELS[6]
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== 验证测试 ====================
|
||
|
|
|
||
|
|
console.log('=== 数值模型验证 ===\n')
|
||
|
|
|
||
|
|
// 1. 品质系统测试
|
||
|
|
console.log('1. 品质倍率验证:')
|
||
|
|
console.log(` 品质50 (垃圾): 攻击力20 -> ${calculateEquipmentStats(20, 50, 1)} (0.5x)`)
|
||
|
|
console.log(` 品质100 (普通): 攻击力20 -> ${calculateEquipmentStats(20, 100, 1)} (1.0x)`)
|
||
|
|
console.log(` 品质150 (优秀): 攻击力20 -> ${calculateEquipmentStats(20, 150, 1)} (1.5x)`)
|
||
|
|
console.log(` 品质200 (史诗): 攻击力20 -> ${calculateEquipmentStats(20, 200, 1)} (2.0x)`)
|
||
|
|
console.log(` 品质250 (传说): 攻击力20 -> ${calculateEquipmentStats(20, 250, 1)} (2.5x)`)
|
||
|
|
|
||
|
|
// 2. 物品等级测试
|
||
|
|
console.log('\n2. 物品等级影响 (品质100):')
|
||
|
|
console.log(` Lv1: 攻击力20 -> ${calculateEquipmentStats(20, 100, 1)}`)
|
||
|
|
console.log(` Lv5: 攻击力20 -> ${calculateEquipmentStats(20, 100, 5)}`)
|
||
|
|
console.log(` Lv10: 攻击力20 -> ${calculateEquipmentStats(20, 100, 10)}`)
|
||
|
|
console.log(` Lv50: 攻击力20 -> ${calculateEquipmentStats(20, 100, 50)}`)
|
||
|
|
|
||
|
|
// 3. 角色属性测试
|
||
|
|
console.log('\n3. 角色属性 (Lv1, 默认属性):')
|
||
|
|
const defaultStats = { strength: 10, agility: 8, dexterity: 8, intuition: 10, vitality: 10 }
|
||
|
|
const stats = calculateCharacterStats(defaultStats, 1)
|
||
|
|
console.log(` HP: ${stats.hp}`)
|
||
|
|
console.log(` 攻击: ${stats.attack}`)
|
||
|
|
console.log(` 暴击率: ${stats.critRate}%`)
|
||
|
|
console.log(` 体质+10 -> HP +${calculateCharacterStats({ vitality: 20 }, 1).hp - stats.hp}`)
|
||
|
|
|
||
|
|
// 4. 怪物缩放测试
|
||
|
|
console.log('\n4. 怪物等级缩放 (基础HP 100):')
|
||
|
|
console.log(` Lv1: HP = ${calculateMonsterStats(100, 1)}`)
|
||
|
|
console.log(` Lv5: HP = ${calculateMonsterStats(100, 5)} (1.12^4 ≈ 1.57x)`)
|
||
|
|
console.log(` Lv10: HP = ${calculateMonsterStats(100, 10)} (1.12^9 ≈ 2.8x)`)
|
||
|
|
console.log(` Lv20: HP = ${calculateMonsterStats(100, 20)} (1.12^19 ≈ 8.0x)`)
|
||
|
|
|
||
|
|
// 5. 经验曲线测试
|
||
|
|
console.log('\n5. 升级经验需求:')
|
||
|
|
console.log(` Lv1 -> Lv2: ${getExpForLevel(2)} 经验`)
|
||
|
|
console.log(` Lv5 -> Lv6: ${getExpForLevel(6)} 经验`)
|
||
|
|
console.log(` Lv10 -> Lv11: ${getExpForLevel(11)} 经验`)
|
||
|
|
console.log(` Lv20 -> Lv21: ${getExpForLevel(21)} 经验`)
|
||
|
|
console.log(` Lv50 -> Lv51: ${getExpForLevel(51)} 经验`)
|
||
|
|
|
||
|
|
// 6. 品质等级验证
|
||
|
|
console.log('\n6. 品质等级判定:')
|
||
|
|
for (let q = 0; q <= 250; q += 50) {
|
||
|
|
const level = getQualityLevel(q)
|
||
|
|
console.log(` 品质 ${q}: ${level.name.padEnd(6)} (${level.color})`)
|
||
|
|
}
|
||
|
|
|
||
|
|
// 7. 可玩性验证
|
||
|
|
console.log('\n=== 可玩性验证 ===\n')
|
||
|
|
|
||
|
|
// 新手阶段
|
||
|
|
const playerLv1 = calculateCharacterStats(defaultStats, 1)
|
||
|
|
const monsterLv1 = calculateMonsterStats(50, 1)
|
||
|
|
console.log('新手阶段 (Lv1 vs Lv1 怪物):')
|
||
|
|
console.log(` 玩家 HP: ${playerLv1.hp}, 攻击: ${playerLv1.attack}`)
|
||
|
|
console.log(` 怪物 HP: ${monsterLv1}, 攻击: ${calculateEquipmentStats(5, 100, 1)}`)
|
||
|
|
console.log(` 预期: 玩家约需 5-6 次攻击击杀怪物,能承受 20+ 次攻击`)
|
||
|
|
console.log(` 结论: ${playerLv1.attack > 5 ? '✓ 可玩' : '✗ 太难'}`)
|
||
|
|
|
||
|
|
// 中期阶段
|
||
|
|
const playerLv15 = calculateCharacterStats({
|
||
|
|
strength: 20, agility: 15, dexterity: 15, intuition: 15, vitality: 15
|
||
|
|
}, 15)
|
||
|
|
const monsterLv15 = calculateMonsterStats(100, 15)
|
||
|
|
console.log('\n中期阶段 (Lv15 vs Lv15 怪物):')
|
||
|
|
console.log(` 玩家 HP: ${playerLv15.hp}, 攻击: ${playerLv15.attack}`)
|
||
|
|
console.log(` 怪物 HP: ${monsterLv15}, 攻击: ${calculateEquipmentStats(10, 100, 15)}`)
|
||
|
|
console.log(` 预期: 玩家约需 15-20 次攻击击杀怪物`)
|
||
|
|
console.log(` 结论: ${playerLv15.attack > 20 ? '✓ 可玩' : '需要提升'}`)
|
||
|
|
|
||
|
|
// 战斗经济
|
||
|
|
console.log('\n经济系统:')
|
||
|
|
const normalItemPrice = 100 * 1.0
|
||
|
|
const epicItemPrice = 100 * 2.0
|
||
|
|
const monsterGold = 20
|
||
|
|
console.log(` 普通装备价格: ${normalItemPrice} 铜币`)
|
||
|
|
console.log(` 史诗装备价格: ${epicItemPrice} 铜币`)
|
||
|
|
console.log(` Lv1 怪物掉落: ${monsterGold} 铜币 (假设)`)
|
||
|
|
console.log(` 需要击败 ${Math.ceil(epicItemPrice / monsterGold)} 只怪物购买史诗装备`)
|
||
|
|
|
||
|
|
console.log('\n=== 验证完成 ===')
|