Showing
2 changed files
with
160 additions
and
155 deletions
app/node/model/analysis.js
0 → 100644
| 1 | +const analyzeStats = function(characterInfo, analysisEquipment) { | ||
| 2 | + const jobModel = require('./job'); | ||
| 3 | + const job = jobModel[characterInfo.character.job]; | ||
| 4 | + const jobDefault = jobModel.default; | ||
| 5 | + const weaponConst = require('./weapon')[analysisEquipment.weapon] || 1; | ||
| 6 | + | ||
| 7 | + let rebootDamage = 0; | ||
| 8 | + if (characterInfo.character.server.name.indexOf("리부트") == 0) { | ||
| 9 | + // 리부트, 리부트2 월드 반영 | ||
| 10 | + rebootDamage = parseInt(characterInfo.character.level / 2); | ||
| 11 | + } | ||
| 12 | + | ||
| 13 | + const stats = { | ||
| 14 | + major: { | ||
| 15 | + pure: 0, | ||
| 16 | + percent: analysisEquipment.majorPercent + | ||
| 17 | + job.stats.passive.major.percent + | ||
| 18 | + jobDefault.stats.passive.major.percent, | ||
| 19 | + added: 0 | ||
| 20 | + }, | ||
| 21 | + minor: characterInfo.stats.minor, | ||
| 22 | + damage: { | ||
| 23 | + all: characterInfo.stats.damageHyper + | ||
| 24 | + analysisEquipment.damagePercent + | ||
| 25 | + job.stats.passive.damage.all + | ||
| 26 | + jobDefault.stats.passive.damage.all + | ||
| 27 | + rebootDamage, | ||
| 28 | + boss: characterInfo.stats.bossAttackDamage | ||
| 29 | + }, | ||
| 30 | + finalDamage: job.stats.passive.finalDamage, | ||
| 31 | + criticalDamage: characterInfo.stats.criticalDamage + jobDefault.stats.passive.criticalDamage, | ||
| 32 | + attackPower: { | ||
| 33 | + pure: 0, | ||
| 34 | + percent: analysisEquipment.attackPowerPercent + | ||
| 35 | + job.stats.passive.attackPower.percent | ||
| 36 | + }, | ||
| 37 | + ignoreGuard: characterInfo.stats.ignoreGuard | ||
| 38 | + }; | ||
| 39 | + | ||
| 40 | + stats.major.added = characterInfo.stats.majorHyper + | ||
| 41 | + analysisEquipment.majorArcane + | ||
| 42 | + jobDefault.stats.passive.major.added; | ||
| 43 | + stats.major.pure = (characterInfo.stats.major - stats.major.added) / (1 + stats.major.percent / 100); | ||
| 44 | + | ||
| 45 | + stats.attackPower.pure = characterInfo.stats.statAttackPower * 100 / (characterInfo.stats.major * 4 + stats.minor) / job.jobConst / weaponConst / (1 + stats.attackPower.percent / 100) / (1 + stats.damage.all / 100) / (1 + stats.finalDamage / 100); | ||
| 46 | + | ||
| 47 | + return stats; | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +const calculateEfficiency = function(stats, job, weapon) { | ||
| 51 | + const efficiency = { | ||
| 52 | + major: { | ||
| 53 | + pure: 1, | ||
| 54 | + percent: 0 | ||
| 55 | + }, | ||
| 56 | + attackPower: { | ||
| 57 | + pure: 0, | ||
| 58 | + percent: 0, | ||
| 59 | + }, | ||
| 60 | + damage: 0, | ||
| 61 | + criticalDamage: 0, | ||
| 62 | + ignoreGuard: 0 | ||
| 63 | + }; | ||
| 64 | + | ||
| 65 | + const defaultPower = calculatePower(stats, job, weapon); | ||
| 66 | + | ||
| 67 | + stats.major.pure += 1; | ||
| 68 | + const majorPure = calculatePower(stats, job, weapon) - defaultPower; | ||
| 69 | + stats.major.pure -= 1; | ||
| 70 | + | ||
| 71 | + if (majorPure == 0) | ||
| 72 | + return efficiency; | ||
| 73 | + | ||
| 74 | + stats.major.percent += 1; | ||
| 75 | + efficiency.major.percent = (calculatePower(stats, job, weapon) - defaultPower) / majorPure; | ||
| 76 | + stats.major.percent -= 1; | ||
| 77 | + | ||
| 78 | + stats.attackPower.pure += 1; | ||
| 79 | + efficiency.attackPower.pure = (calculatePower(stats, job, weapon) - defaultPower) / majorPure; | ||
| 80 | + stats.attackPower.pure -= 1; | ||
| 81 | + | ||
| 82 | + stats.attackPower.percent += 1; | ||
| 83 | + efficiency.attackPower.percent = (calculatePower(stats, job, weapon) - defaultPower) / majorPure; | ||
| 84 | + stats.attackPower.percent -= 1; | ||
| 85 | + | ||
| 86 | + stats.damage.all += 1; | ||
| 87 | + efficiency.damage = (calculatePower(stats, job, weapon) - defaultPower) / majorPure; | ||
| 88 | + stats.damage.all -= 1; | ||
| 89 | + | ||
| 90 | + stats.criticalDamage += 1; | ||
| 91 | + efficiency.criticalDamage = (calculatePower(stats, job, weapon) - defaultPower) / majorPure; | ||
| 92 | + stats.criticalDamage -= 1; | ||
| 93 | + | ||
| 94 | + // 곱연산 | ||
| 95 | + const ignoreGuardSaved = stats.ignoreGuard; | ||
| 96 | + stats.ignoreGuard = (1 - (1 - stats.ignoreGuard / 100) * 0.99) * 100; | ||
| 97 | + efficiency.ignoreGuard = (calculatePower(stats, job, weapon) - defaultPower) / majorPure; | ||
| 98 | + stats.ignoreGuard = ignoreGuardSaved; | ||
| 99 | + | ||
| 100 | + return efficiency; | ||
| 101 | +} | ||
| 102 | + | ||
| 103 | +// 버프 적용 스탯 구하기 | ||
| 104 | +const getBuffStats = function(stats, job) { | ||
| 105 | + const jobModel = require('./job'); | ||
| 106 | + const buff = jobModel[job].stats.active; | ||
| 107 | + const defaultBuff = jobModel.default.stats.active; | ||
| 108 | + | ||
| 109 | + return { | ||
| 110 | + major: { | ||
| 111 | + pure: stats.major.pure + buff.major.pure, | ||
| 112 | + percent: stats.major.percent + buff.major.percent, | ||
| 113 | + added: stats.major.added | ||
| 114 | + }, | ||
| 115 | + minor: stats.minor, | ||
| 116 | + damage: { | ||
| 117 | + all: stats.damage.all + buff.damage.all + defaultBuff.damage.all, | ||
| 118 | + boss: stats.damage.boss + buff.damage.boss + defaultBuff.damage.boss | ||
| 119 | + }, | ||
| 120 | + finalDamage: stats.finalDamage, | ||
| 121 | + criticalDamage: stats.criticalDamage + buff.criticalDamage + defaultBuff.criticalDamage, | ||
| 122 | + attackPower: { | ||
| 123 | + pure: stats.attackPower.pure + buff.attackPower.pure, | ||
| 124 | + percent: stats.attackPower.percent + buff.attackPower.percent + defaultBuff.attackPower.percent | ||
| 125 | + }, | ||
| 126 | + ignoreGuard: (1 - (1 - (stats.ignoreGuard / 100)) * (1 - (buff.ignoreGuard / 100)) * (1 - (defaultBuff.ignoreGuard / 100))) * 100 | ||
| 127 | + }; | ||
| 128 | +} | ||
| 129 | + | ||
| 130 | +// 크리티컬 데미지, 보스 공격력, 방어율 무시를 반영하여 방어율 300% 몬스터 공격시 데미지 산출 값 | ||
| 131 | +const calculatePower = function(stats, job, weapon) { | ||
| 132 | + const jobConst = require('./job')[job].jobConst; | ||
| 133 | + const weaponConst = require('./weapon')[weapon]; | ||
| 134 | + return Math.max( | ||
| 135 | + ( | ||
| 136 | + (stats.major.pure * (1 + stats.major.percent / 100) + stats.major.added) * 4 + | ||
| 137 | + stats.minor | ||
| 138 | + ) * | ||
| 139 | + 0.01 * | ||
| 140 | + (stats.attackPower.pure * (1 + stats.attackPower.percent / 100)) * | ||
| 141 | + jobConst * | ||
| 142 | + weaponConst * | ||
| 143 | + (1 + stats.damage.all / 100 + stats.damage.boss / 100) * | ||
| 144 | + (1 + stats.finalDamage / 100) * | ||
| 145 | + (1.35 + stats.criticalDamage / 100) * | ||
| 146 | + (1 - 3 * (1 - stats.ignoreGuard / 100)), | ||
| 147 | + 1); | ||
| 148 | +} | ||
| 149 | + | ||
| 150 | +module.exports = { | ||
| 151 | + analyzeStats: analyzeStats, | ||
| 152 | + calculateEfficiency: calculateEfficiency, | ||
| 153 | + getBuffStats: getBuffStats, | ||
| 154 | + calculatePower: calculatePower, | ||
| 155 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | const characterModel = require('../model/character'); | 1 | const characterModel = require('../model/character'); |
| 2 | - | 2 | +const analysisModel = require('../model/analysis'); |
| 3 | -const analyzeStats = function(characterInfo, analysisEquipment) { | ||
| 4 | - const jobModel = require('../model/job'); | ||
| 5 | - const job = jobModel[characterInfo.character.job]; | ||
| 6 | - const jobDefault = jobModel.default; | ||
| 7 | - const weaponConst = require('../model/weapon')[analysisEquipment.weapon] || 1; | ||
| 8 | - | ||
| 9 | - let rebootDamage = 0; | ||
| 10 | - if (characterInfo.character.server.name.indexOf("리부트") == 0) { | ||
| 11 | - // 리부트, 리부트2 월드 반영 | ||
| 12 | - rebootDamage = parseInt(characterInfo.character.level / 2); | ||
| 13 | - } | ||
| 14 | - | ||
| 15 | - const stats = { | ||
| 16 | - major: { | ||
| 17 | - pure: 0, | ||
| 18 | - percent: analysisEquipment.majorPercent + | ||
| 19 | - job.stats.passive.major.percent + | ||
| 20 | - jobDefault.stats.passive.major.percent, | ||
| 21 | - added: 0 | ||
| 22 | - }, | ||
| 23 | - minor: characterInfo.stats.minor, | ||
| 24 | - damage: { | ||
| 25 | - all: characterInfo.stats.damageHyper + | ||
| 26 | - analysisEquipment.damagePercent + | ||
| 27 | - job.stats.passive.damage.all + | ||
| 28 | - jobDefault.stats.passive.damage.all + | ||
| 29 | - rebootDamage, | ||
| 30 | - boss: characterInfo.stats.bossAttackDamage | ||
| 31 | - }, | ||
| 32 | - finalDamage: job.stats.passive.finalDamage, | ||
| 33 | - criticalDamage: characterInfo.stats.criticalDamage + jobDefault.stats.passive.criticalDamage, | ||
| 34 | - attackPower: { | ||
| 35 | - pure: 0, | ||
| 36 | - percent: analysisEquipment.attackPowerPercent + | ||
| 37 | - job.stats.passive.attackPower.percent | ||
| 38 | - }, | ||
| 39 | - ignoreGuard: characterInfo.stats.ignoreGuard | ||
| 40 | - }; | ||
| 41 | - | ||
| 42 | - stats.major.added = characterInfo.stats.majorHyper + | ||
| 43 | - analysisEquipment.majorArcane + | ||
| 44 | - jobDefault.stats.passive.major.added; | ||
| 45 | - stats.major.pure = (characterInfo.stats.major - stats.major.added) / (1 + stats.major.percent / 100); | ||
| 46 | - | ||
| 47 | - stats.attackPower.pure = characterInfo.stats.statAttackPower * 100 / (characterInfo.stats.major * 4 + stats.minor) / job.jobConst / weaponConst / (1 + stats.attackPower.percent / 100) / (1 + stats.damage.all / 100) / (1 + stats.finalDamage / 100); | ||
| 48 | - | ||
| 49 | - return stats; | ||
| 50 | -} | ||
| 51 | - | ||
| 52 | -const calculateEfficiency = function(stats, job, weapon) { | ||
| 53 | - const efficiency = { | ||
| 54 | - major: { | ||
| 55 | - pure: 1, | ||
| 56 | - percent: 0 | ||
| 57 | - }, | ||
| 58 | - attackPower: { | ||
| 59 | - pure: 0, | ||
| 60 | - percent: 0, | ||
| 61 | - }, | ||
| 62 | - damage: 0, | ||
| 63 | - criticalDamage: 0, | ||
| 64 | - ignoreGuard: 0 | ||
| 65 | - }; | ||
| 66 | - | ||
| 67 | - const defaultPower = calculatePower(stats, job, weapon); | ||
| 68 | - | ||
| 69 | - stats.major.pure += 1; | ||
| 70 | - const majorPure = calculatePower(stats, job, weapon) - defaultPower; | ||
| 71 | - stats.major.pure -= 1; | ||
| 72 | - | ||
| 73 | - if (majorPure == 0) | ||
| 74 | - return efficiency; | ||
| 75 | - | ||
| 76 | - stats.major.percent += 1; | ||
| 77 | - efficiency.major.percent = (calculatePower(stats, job, weapon) - defaultPower) / majorPure; | ||
| 78 | - stats.major.percent -= 1; | ||
| 79 | - | ||
| 80 | - stats.attackPower.pure += 1; | ||
| 81 | - efficiency.attackPower.pure = (calculatePower(stats, job, weapon) - defaultPower) / majorPure; | ||
| 82 | - stats.attackPower.pure -= 1; | ||
| 83 | - | ||
| 84 | - stats.attackPower.percent += 1; | ||
| 85 | - efficiency.attackPower.percent = (calculatePower(stats, job, weapon) - defaultPower) / majorPure; | ||
| 86 | - stats.attackPower.percent -= 1; | ||
| 87 | - | ||
| 88 | - stats.damage.all += 1; | ||
| 89 | - efficiency.damage = (calculatePower(stats, job, weapon) - defaultPower) / majorPure; | ||
| 90 | - stats.damage.all -= 1; | ||
| 91 | - | ||
| 92 | - stats.criticalDamage += 1; | ||
| 93 | - efficiency.criticalDamage = (calculatePower(stats, job, weapon) - defaultPower) / majorPure; | ||
| 94 | - stats.criticalDamage -= 1; | ||
| 95 | - | ||
| 96 | - // 곱연산 | ||
| 97 | - const ignoreGuardSaved = stats.ignoreGuard; | ||
| 98 | - stats.ignoreGuard = (1 - (1 - stats.ignoreGuard / 100) * 0.99) * 100; | ||
| 99 | - efficiency.ignoreGuard = (calculatePower(stats, job, weapon) - defaultPower) / majorPure; | ||
| 100 | - stats.ignoreGuard = ignoreGuardSaved; | ||
| 101 | - | ||
| 102 | - return efficiency; | ||
| 103 | -} | ||
| 104 | - | ||
| 105 | -// 버프 적용 스탯 구하기 | ||
| 106 | -const getBuffStats = function(stats, job) { | ||
| 107 | - const jobModel = require('../model/job'); | ||
| 108 | - const buff = jobModel[job].stats.active; | ||
| 109 | - const defaultBuff = jobModel.default.stats.active; | ||
| 110 | - | ||
| 111 | - return { | ||
| 112 | - major: { | ||
| 113 | - pure: stats.major.pure + buff.major.pure, | ||
| 114 | - percent: stats.major.percent + buff.major.percent, | ||
| 115 | - added: stats.major.added | ||
| 116 | - }, | ||
| 117 | - minor: stats.minor, | ||
| 118 | - damage: { | ||
| 119 | - all: stats.damage.all + buff.damage.all + defaultBuff.damage.all, | ||
| 120 | - boss: stats.damage.boss + buff.damage.boss + defaultBuff.damage.boss | ||
| 121 | - }, | ||
| 122 | - finalDamage: stats.finalDamage, | ||
| 123 | - criticalDamage: stats.criticalDamage + buff.criticalDamage + defaultBuff.criticalDamage, | ||
| 124 | - attackPower: { | ||
| 125 | - pure: stats.attackPower.pure + buff.attackPower.pure, | ||
| 126 | - percent: stats.attackPower.percent + buff.attackPower.percent + defaultBuff.attackPower.percent | ||
| 127 | - }, | ||
| 128 | - ignoreGuard: (1 - (1 - (stats.ignoreGuard / 100)) * (1 - (buff.ignoreGuard / 100)) * (1 - (defaultBuff.ignoreGuard / 100))) * 100 | ||
| 129 | - }; | ||
| 130 | -} | ||
| 131 | - | ||
| 132 | -// 크리티컬 데미지, 보스 공격력, 방어율 무시를 반영하여 방어율 300% 몬스터 공격시 데미지 산출 값 | ||
| 133 | -const calculatePower = function(stats, job, weapon) { | ||
| 134 | - const jobConst = require('../model/job')[job].jobConst; | ||
| 135 | - const weaponConst = require('../model/weapon')[weapon]; | ||
| 136 | - return Math.max( | ||
| 137 | - ( | ||
| 138 | - (stats.major.pure * (1 + stats.major.percent / 100) + stats.major.added) * 4 + | ||
| 139 | - stats.minor | ||
| 140 | - ) * | ||
| 141 | - 0.01 * | ||
| 142 | - (stats.attackPower.pure * (1 + stats.attackPower.percent / 100)) * | ||
| 143 | - jobConst * | ||
| 144 | - weaponConst * | ||
| 145 | - (1 + stats.damage.all / 100 + stats.damage.boss / 100) * | ||
| 146 | - (1 + stats.finalDamage / 100) * | ||
| 147 | - (1.35 + stats.criticalDamage / 100) * | ||
| 148 | - (1 - 3 * (1 - stats.ignoreGuard / 100)), | ||
| 149 | - 1); | ||
| 150 | -} | ||
| 151 | 3 | ||
| 152 | module.exports = { | 4 | module.exports = { |
| 153 | getCharacter: async function(req, res) { | 5 | getCharacter: async function(req, res) { |
| ... | @@ -195,21 +47,19 @@ module.exports = { | ... | @@ -195,21 +47,19 @@ module.exports = { |
| 195 | return; | 47 | return; |
| 196 | } | 48 | } |
| 197 | 49 | ||
| 198 | - const stats = analyzeStats(characterInfo, analysisEquipment); | 50 | + const stats = analysisModel.analyzeStats(characterInfo, analysisEquipment); |
| 199 | - const buffStats = getBuffStats(stats, characterInfo.character.job); | 51 | + const buffStats = analysisModel.getBuffStats(stats, characterInfo.character.job); |
| 200 | - const efficiency = calculateEfficiency(stats, characterInfo.character.job, analysisEquipment.weapon); | ||
| 201 | - const buffEfficiency = calculateEfficiency(buffStats, characterInfo.character.job, analysisEquipment.weapon); | ||
| 202 | 52 | ||
| 203 | const result = { | 53 | const result = { |
| 204 | info: characterInfo.character, | 54 | info: characterInfo.character, |
| 205 | analysis: { | 55 | analysis: { |
| 206 | default: { | 56 | default: { |
| 207 | stats: stats, | 57 | stats: stats, |
| 208 | - efficiency: efficiency | 58 | + efficiency: analysisModel.calculateEfficiency(stats, characterInfo.character.job, analysisEquipment.weapon) |
| 209 | }, | 59 | }, |
| 210 | buff: { | 60 | buff: { |
| 211 | stats: buffStats, | 61 | stats: buffStats, |
| 212 | - efficiency: buffEfficiency | 62 | + efficiency: analysisModel.calculateEfficiency(buffStats, characterInfo.character.job, analysisEquipment.weapon) |
| 213 | } | 63 | } |
| 214 | } | 64 | } |
| 215 | }; | 65 | }; | ... | ... |
-
Please register or login to post a comment