mirror of
https://github.com/Kvan7/Exiled-Exchange-2.git
synced 2026-09-29 08:05:58 +00:00
feat: unique item q20 props
This commit is contained in:
@@ -64,6 +64,12 @@ export const TRADE_TAG_BY_NAME = new Map(TRADE_TAGS)
|
||||
export interface UniqueItem {
|
||||
name: string
|
||||
basetype: string
|
||||
props: {
|
||||
pdps?: { min: number, max: number }
|
||||
ar?: { min: number, max: number }
|
||||
ev?: { min: number, max: number }
|
||||
es?: { min: number, max: number }
|
||||
}
|
||||
stats: Array<{
|
||||
text: string
|
||||
implicit?: true
|
||||
|
||||
@@ -6,6 +6,7 @@ import { StatFilter } from './interfaces'
|
||||
import { filterPseudo } from './pseudo'
|
||||
import { filterItemProp } from './pseudo/item-property'
|
||||
import { getRollAsSingleNumber } from '@/parser/utils'
|
||||
import { filterUniqueItemProp } from './pseudo/item-property-unique'
|
||||
|
||||
export interface FiltersCreationContext {
|
||||
readonly item: ParsedItem
|
||||
@@ -21,7 +22,7 @@ export function initUiModFilters (item: ParsedItem): StatFilter[] {
|
||||
}
|
||||
|
||||
if (item.rarity === ItemRarity.Unique) {
|
||||
// TODO
|
||||
filterUniqueItemProp(ctx)
|
||||
} else {
|
||||
filterItemProp(ctx)
|
||||
filterPseudo(ctx)
|
||||
@@ -131,7 +132,9 @@ function filterAdjustmentForNegate (
|
||||
if (filter.min == null && filter.max == null && filter.defaultMax != null) {
|
||||
filter.min = -1 * (raw.defaultMax as number)
|
||||
}
|
||||
filter.roll = -1 * raw.roll!
|
||||
if (filter.roll != null) {
|
||||
filter.roll = -1 * raw.roll!
|
||||
}
|
||||
} else {
|
||||
if (filter.min == null && filter.max == null && filter.defaultMin != null) {
|
||||
filter.min = filter.defaultMin
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
import { rollToFilter, percentRollDelta } from '../util'
|
||||
import { INTERNAL_TRADE_ID, StatFilter } from '../interfaces'
|
||||
import { FiltersCreationContext, itemModToFilter } from '../create-stat-filters'
|
||||
import { propAt20Quality, variablePropAt20Quality, QUALITY_STATS } from './calc-q20'
|
||||
import { stat, Uniques } from '@/assets/data'
|
||||
import { ARMOUR, WEAPON } from '@/parser/meta'
|
||||
import { Config } from '@/web/Config'
|
||||
|
||||
export function filterUniqueItemProp (ctx: FiltersCreationContext) {
|
||||
if (ARMOUR.has(ctx.item.category!)) {
|
||||
armourProps(ctx)
|
||||
}
|
||||
if (WEAPON.has(ctx.item.category!)) {
|
||||
weaponProps(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
const ARMOUR_STATS = new Set<string>([
|
||||
QUALITY_STATS.ARMOUR.flat,
|
||||
QUALITY_STATS.EVASION.flat,
|
||||
QUALITY_STATS.ENERGY_SHIELD.flat,
|
||||
...QUALITY_STATS.ARMOUR.incr,
|
||||
...QUALITY_STATS.EVASION.incr,
|
||||
...QUALITY_STATS.ENERGY_SHIELD.incr
|
||||
])
|
||||
|
||||
function armourProps (ctx: FiltersCreationContext) {
|
||||
const { item } = ctx
|
||||
|
||||
const uniqueInfo = Uniques.get(`${item.name} ${item.baseType}`)
|
||||
|
||||
if (item.props.armour) {
|
||||
const totalQ20 = Math.floor(propAt20Quality(item.props.armour, QUALITY_STATS.ARMOUR, item))
|
||||
|
||||
ctx.filters.push(propToFilter(
|
||||
totalQ20,
|
||||
uniqueInfo?.props.ar,
|
||||
'armour.armour',
|
||||
'armour',
|
||||
'Armour: #'
|
||||
))
|
||||
}
|
||||
|
||||
if (item.props.evasion) {
|
||||
const totalQ20 = Math.floor(propAt20Quality(item.props.evasion, QUALITY_STATS.EVASION, item))
|
||||
|
||||
ctx.filters.push(propToFilter(
|
||||
totalQ20,
|
||||
uniqueInfo?.props.ev,
|
||||
'armour.evasion_rating',
|
||||
'armour',
|
||||
'Evasion Rating: #'
|
||||
))
|
||||
}
|
||||
|
||||
if (item.props.energyShield) {
|
||||
const totalQ20 = Math.floor(propAt20Quality(item.props.energyShield, QUALITY_STATS.ENERGY_SHIELD, item))
|
||||
|
||||
ctx.filters.push(propToFilter(
|
||||
totalQ20,
|
||||
uniqueInfo?.props.es,
|
||||
'armour.energy_shield',
|
||||
'armour',
|
||||
'Energy Shield: #'
|
||||
))
|
||||
}
|
||||
|
||||
createHiddenFilters(ctx, ARMOUR_STATS)
|
||||
}
|
||||
|
||||
const WEAPON_STATS = new Set<string>([
|
||||
QUALITY_STATS.PHYSICAL_DAMAGE.flat,
|
||||
...QUALITY_STATS.PHYSICAL_DAMAGE.incr,
|
||||
stat('#% increased Attack Speed')
|
||||
])
|
||||
|
||||
function weaponProps (ctx: FiltersCreationContext) {
|
||||
const { item } = ctx
|
||||
|
||||
const uniqueInfo = Uniques.get(`${item.name} ${item.baseType}`)
|
||||
|
||||
if (item.props.physicalDamage) {
|
||||
const physQ20 = variablePropAt20Quality(item.props.physicalDamage!, QUALITY_STATS.PHYSICAL_DAMAGE, item)
|
||||
const pdpsQ20 = Math.floor((physQ20[0] + physQ20[1]) / 2 * item.props.attackSpeed!)
|
||||
|
||||
ctx.filters.push(propToFilter(
|
||||
pdpsQ20,
|
||||
uniqueInfo?.props.pdps,
|
||||
'weapon.physical_dps',
|
||||
'weapon',
|
||||
'Physical DPS: #'
|
||||
))
|
||||
}
|
||||
|
||||
createHiddenFilters(ctx, WEAPON_STATS)
|
||||
}
|
||||
|
||||
function createHiddenFilters (ctx: FiltersCreationContext, stats: Set<string>) {
|
||||
for (const m of ctx.modifiers) {
|
||||
if (stats.has(m.stat.ref)) {
|
||||
const filter = itemModToFilter(m, ctx.item)
|
||||
filter.hidden = 'Contributes to the item property'
|
||||
ctx.filters.push(filter)
|
||||
}
|
||||
}
|
||||
|
||||
ctx.modifiers = ctx.modifiers.filter(m => !stats.has(m.stat.ref))
|
||||
}
|
||||
|
||||
const TOLERANCE = 4
|
||||
|
||||
function isWithinBounds (value: number, bounds: { min: number, max: number }) {
|
||||
return ((value + TOLERANCE) >= bounds.min) && ((value - TOLERANCE) <= bounds.max)
|
||||
}
|
||||
|
||||
function propToFilter (
|
||||
totalQ20: number,
|
||||
propInfo: { min: number, max: number } | undefined,
|
||||
tradeId: INTERNAL_TRADE_ID,
|
||||
type: 'armour' | 'weapon',
|
||||
text: string
|
||||
): StatFilter {
|
||||
if (propInfo && isWithinBounds(totalQ20, propInfo)) {
|
||||
if (propInfo.min === propInfo.max) {
|
||||
return ({
|
||||
tradeId: [tradeId],
|
||||
text,
|
||||
type,
|
||||
disabled: true,
|
||||
hidden: 'Roll is not variable',
|
||||
defaultMin: totalQ20,
|
||||
defaultMax: totalQ20,
|
||||
min: totalQ20,
|
||||
max: totalQ20,
|
||||
roll: totalQ20
|
||||
})
|
||||
} else {
|
||||
const percent = Config.store.searchStatRange * 2
|
||||
return ({
|
||||
tradeId: [tradeId],
|
||||
text,
|
||||
type,
|
||||
disabled: true,
|
||||
boundMin: propInfo.min,
|
||||
boundMax: propInfo.max,
|
||||
defaultMin: Math.max(percentRollDelta(totalQ20, (propInfo.max - propInfo.min), -percent, Math.floor), propInfo.min),
|
||||
defaultMax: Math.min(percentRollDelta(totalQ20, (propInfo.max - propInfo.min), +percent, Math.ceil), propInfo.max),
|
||||
min: totalQ20,
|
||||
max: undefined,
|
||||
roll: totalQ20
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// missing unique (Two-Toned Boots) / stat affecting prop is variant (Atziri's Splendour) / corrupted implicit affecting prop
|
||||
return ({
|
||||
tradeId: [tradeId],
|
||||
text,
|
||||
type,
|
||||
disabled: true,
|
||||
...rollToFilter(totalQ20, { neverNegated: true })
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user