mirror of
https://github.com/Kvan7/Exiled-Exchange-2.git
synced 2026-09-23 13:15:45 +00:00
base defence percentile, closes #746
This commit is contained in:
@@ -27,6 +27,7 @@ export interface ParsedItem {
|
||||
armourES?: number
|
||||
armourWARD?: number
|
||||
armourBLOCK?: number
|
||||
basePercentile?: number
|
||||
weaponCRIT?: number
|
||||
weaponAS?: number
|
||||
weaponPHYSICAL?: number
|
||||
|
||||
@@ -12,6 +12,7 @@ import { ItemCategory } from './meta'
|
||||
import { IncursionRoom, ParsedItem, ItemInfluence, ItemRarity } from './ParsedItem'
|
||||
import { magicBasetype } from './magic-name'
|
||||
import { isModInfoLine, groupLinesByMod, parseModInfoLine, parseModType, ModifierInfo, ParsedModifier, ENCHANT_LINE, SCOURGE_LINE } from './advanced-mod-desc'
|
||||
import { calcPropPercentile, QUALITY_STATS } from './calc-q20'
|
||||
|
||||
type SectionParseResult =
|
||||
| 'SECTION_PARSED'
|
||||
@@ -65,7 +66,8 @@ const parsers: Array<ParserFn | { virtual: VirtualParserFn }> = [
|
||||
{ virtual: transformToLegacyModifiers },
|
||||
{ virtual: parseFractured },
|
||||
{ virtual: parseBlightedMap },
|
||||
{ virtual: pickCorrectVariant }
|
||||
{ virtual: pickCorrectVariant },
|
||||
{ virtual: calcBasePercentile }
|
||||
]
|
||||
|
||||
export function parseClipboard (clipboard: string) {
|
||||
@@ -913,6 +915,23 @@ function transformToLegacyModifiers (item: ParsedItem) {
|
||||
item.statsByType = sumStatsByModType(item.newMods)
|
||||
}
|
||||
|
||||
function calcBasePercentile (item: ParsedItem) {
|
||||
if (!item.info.armour) return
|
||||
// Base percentile is the same for all defences.
|
||||
// Using `AR/EV -> ES -> WARD` order to improve accuracy
|
||||
// of calculation (larger rolls = more precise).
|
||||
const info = item.info.armour
|
||||
if (item.armourAR) {
|
||||
item.basePercentile = calcPropPercentile(item.armourAR, info.ar!, QUALITY_STATS.ARMOUR, item)
|
||||
} else if (item.armourEV) {
|
||||
item.basePercentile = calcPropPercentile(item.armourEV, info.ev!, QUALITY_STATS.EVASION, item)
|
||||
} else if (item.armourES) {
|
||||
item.basePercentile = calcPropPercentile(item.armourES, info.es!, QUALITY_STATS.ENERGY_SHIELD, item)
|
||||
} else if (item.armourWARD) {
|
||||
item.basePercentile = calcPropPercentile(item.armourWARD, info.ward!, QUALITY_STATS.WARD, item)
|
||||
}
|
||||
}
|
||||
|
||||
export function removeLinesEnding (
|
||||
lines: readonly string[], ending: string
|
||||
): string[] {
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
import { ParsedItem } from './ParsedItem'
|
||||
import { stat } from '@/assets/data'
|
||||
import { StatRoll, StatSource, statSourcesTotal } from './modifiers'
|
||||
|
||||
export const QUALITY_STATS = {
|
||||
ARMOUR: {
|
||||
flat: [stat('+# to Armour')],
|
||||
incr: [
|
||||
stat('#% increased Armour'),
|
||||
stat('#% increased Armour and Energy Shield'),
|
||||
stat('#% increased Armour and Evasion'),
|
||||
stat('#% increased Armour, Evasion and Energy Shield')
|
||||
]
|
||||
},
|
||||
EVASION: {
|
||||
flat: [stat('+# to Evasion Rating')],
|
||||
incr: [
|
||||
stat('#% increased Evasion Rating'),
|
||||
stat('#% increased Armour and Evasion'),
|
||||
stat('#% increased Evasion and Energy Shield'),
|
||||
stat('#% increased Armour, Evasion and Energy Shield')
|
||||
]
|
||||
},
|
||||
ENERGY_SHIELD: {
|
||||
flat: [stat('+# to maximum Energy Shield')],
|
||||
incr: [
|
||||
stat('#% increased Energy Shield'),
|
||||
stat('#% increased Armour and Energy Shield'),
|
||||
stat('#% increased Evasion and Energy Shield'),
|
||||
stat('#% increased Armour, Evasion and Energy Shield')
|
||||
]
|
||||
},
|
||||
WARD: {
|
||||
flat: [stat('+# to Ward')],
|
||||
incr: [
|
||||
stat('#% increased Ward')
|
||||
]
|
||||
},
|
||||
PHYSICAL_DAMAGE: {
|
||||
flat: [stat('Adds # to # Physical Damage')],
|
||||
incr: [
|
||||
stat('#% increased Physical Damage')
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
export function propAt20Quality (
|
||||
total: number,
|
||||
statRefs: { flat: string[], incr: string[] },
|
||||
item: ParsedItem
|
||||
): { roll: StatRoll, sources: StatSource[] } {
|
||||
const { incr, flat, sources } = calcPropBase(statRefs, item)
|
||||
const base = calcBase(total, incr.value + (item.quality ?? 0), flat.value)
|
||||
const quality = Math.max(20, item.quality ?? 0)
|
||||
return {
|
||||
roll: {
|
||||
value: calcIncreased(base + flat.value, incr.value + quality),
|
||||
min: calcIncreased(base + flat.min, incr.min + quality),
|
||||
max: calcIncreased(base + flat.max, incr.max + quality)
|
||||
},
|
||||
sources: sources.map(source => ({ ...source, contributes: undefined }))
|
||||
}
|
||||
}
|
||||
|
||||
export function calcPropBounds (
|
||||
total: number,
|
||||
statRefs: { flat: string[], incr: string[] },
|
||||
item: ParsedItem
|
||||
): { roll: StatRoll, sources: StatSource[] } {
|
||||
const { incr, flat, sources } = calcPropBase(statRefs, item)
|
||||
const base = calcBase(total, incr.value, flat.value)
|
||||
return {
|
||||
roll: {
|
||||
value: calcIncreased(base + flat.value, incr.value),
|
||||
min: calcIncreased(base + flat.min, incr.min),
|
||||
max: calcIncreased(base + flat.max, incr.max)
|
||||
},
|
||||
sources: (statRefs.incr.length && statRefs.flat.length)
|
||||
? sources.map(source => ({ ...source, contributes: undefined }))
|
||||
: (statRefs.incr.length)
|
||||
? sources.map(source => ({
|
||||
...source,
|
||||
contributes: {
|
||||
value: base * source.contributes!.value / 100,
|
||||
min: base * source.contributes!.min / 100,
|
||||
max: base * source.contributes!.max / 100
|
||||
}
|
||||
}))
|
||||
: sources
|
||||
}
|
||||
}
|
||||
|
||||
export function calcPropPercentile (
|
||||
total: number,
|
||||
bounds: [min: number, max: number],
|
||||
statRefs: { flat: string[], incr: string[] },
|
||||
item: ParsedItem
|
||||
): number {
|
||||
const { incr, flat } = calcPropBase(statRefs, item)
|
||||
const roll = calcBase(total, incr.value + (item.quality ?? 0), flat.value)
|
||||
const [min, max] = bounds
|
||||
const result = Math.round(((roll - min) / (max - min)) * 100)
|
||||
return Math.min(Math.max(result, 0), 100)
|
||||
}
|
||||
|
||||
function calcPropBase (
|
||||
statRefs: { flat: string[], incr: string[] },
|
||||
item: ParsedItem
|
||||
) {
|
||||
const incr: StatRoll = { value: 0, min: 0, max: 0 }
|
||||
const flat: StatRoll = { value: 0, min: 0, max: 0 }
|
||||
const sources: StatSource[] = []
|
||||
|
||||
for (const calc of item.statsByType) {
|
||||
let total: StatRoll
|
||||
if (statRefs.flat.includes(calc.stat.ref)) {
|
||||
total = flat
|
||||
} else if (statRefs.incr.includes(calc.stat.ref)) {
|
||||
total = incr
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
const roll = statSourcesTotal(calc.sources)!
|
||||
total.value += roll.value
|
||||
total.min += roll.min
|
||||
total.max += roll.max
|
||||
sources.push(...calc.sources)
|
||||
}
|
||||
|
||||
return { incr, flat, sources }
|
||||
}
|
||||
|
||||
function calcBase (total: number, incr: number, flat: number) {
|
||||
return (total / (1 + incr / 100)) - flat
|
||||
}
|
||||
|
||||
function calcIncreased (flat: number, incr: number) {
|
||||
return flat * (1 + incr / 100)
|
||||
}
|
||||
Reference in New Issue
Block a user