mirror of
https://github.com/Kvan7/Exiled-Exchange-2.git
synced 2026-09-21 12:15:47 +00:00
StatBetter, fix some rounding, SourceInfo
This commit is contained in:
@@ -7,10 +7,17 @@ export interface StatMatcher {
|
||||
value?: number
|
||||
}
|
||||
|
||||
export enum StatBetter {
|
||||
NegativeRoll = -1,
|
||||
PositiveRoll = 1,
|
||||
NotComparable = 0
|
||||
}
|
||||
|
||||
export interface Stat {
|
||||
ref: string
|
||||
dp?: true
|
||||
matchers: StatMatcher[]
|
||||
better: StatBetter
|
||||
trade: {
|
||||
inverted?: true
|
||||
option?: 'num' | 'str'
|
||||
|
||||
@@ -137,9 +137,9 @@ export function applyIncr (mod: ModifierInfo, parsed: ParsedStat): ParsedStat |
|
||||
roll: {
|
||||
unscalable: roll.unscalable,
|
||||
dp: roll.dp,
|
||||
value: percentRoll(roll.value, rollIncr, (roll.value > 0) ? Math.floor : Math.ceil, roll.dp && DIV_BY_100),
|
||||
min: percentRoll(roll.min, rollIncr, (roll.min > 0) ? Math.floor : Math.ceil, roll.dp && DIV_BY_100),
|
||||
max: percentRoll(roll.max, rollIncr, (roll.max > 0) ? Math.floor : Math.ceil, roll.dp && DIV_BY_100)
|
||||
value: percentRoll(roll.value, rollIncr, Math.trunc, roll.dp && DIV_BY_100),
|
||||
min: percentRoll(roll.min, rollIncr, Math.trunc, roll.dp && DIV_BY_100),
|
||||
max: percentRoll(roll.max, rollIncr, Math.trunc, roll.dp && DIV_BY_100)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div :class="$style['filter']">
|
||||
<div :class="$style['mods']">
|
||||
<div class="pl-5 pr-3 py-1" v-for="(source, idx) of filter.sources" :key="idx">
|
||||
<source-info :source="source" />
|
||||
<div v-if="showSourceInfo" :class="$style['mods']">
|
||||
<div class="pl-5 py-1" v-for="(source, idx) of filter.sources" :key="idx">
|
||||
<source-info :source="source" :filter="filter" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col min-w-0 flex-1">
|
||||
@@ -195,7 +195,7 @@ export default defineComponent({
|
||||
set (value: string) { props.filter.roll!.max = Number(value) }
|
||||
}),
|
||||
tag: computed(() => props.filter.tag),
|
||||
changeStep: computed(() => props.filter.roll!.step),
|
||||
changeStep: computed(() => props.filter.roll!.dp ? 0.01 : 1),
|
||||
showInputs: computed(() => props.filter.roll != null),
|
||||
fontSize: computed(() => AppConfig().fontSize),
|
||||
isDisabled: computed(() => props.filter.disabled),
|
||||
@@ -205,6 +205,15 @@ export default defineComponent({
|
||||
showRollBounds: computed(() => props.filter.roll?.bounds != null),
|
||||
isHidden: computed(() => props.filter.hidden != null),
|
||||
hiddenReason: computed(() => t(props.filter.hidden!)),
|
||||
showSourceInfo: computed(() =>
|
||||
props.filter.sources.length &&
|
||||
props.filter.option == null && (
|
||||
props.filter.sources.length >= 2 ||
|
||||
props.filter.sources[0].modifier.info.name != null ||
|
||||
props.filter.sources[0].modifier.info.tier != null ||
|
||||
props.filter.sources[0].modifier.info.rank != null
|
||||
)
|
||||
),
|
||||
inputFocus,
|
||||
toggleFilter
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div :class="$style['modinfo']">{{ modText }}</div>
|
||||
<div v-for="stat of stats" :key="stat.text" class="flex">
|
||||
<item-modifier-text :text="stat.text" :roll="stat.roll" :class="{ 'line-through': !stat.contributes }" />
|
||||
<div v-if="stat.contributes && stat.contribution" class="ml-auto">{{ stat.contribution }}</div>
|
||||
<div v-if="stat.contributes && stat.contribution" :class="$style['contribution']">{{ stat.contribution }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -11,10 +11,11 @@
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, PropType } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type { StatCalculated } from '@/parser/modifiers'
|
||||
import { applyIncr } from '@/parser/advanced-mod-desc'
|
||||
import { roundRoll } from './util'
|
||||
import ItemModifierText from '@/web/ui/ItemModifierText.vue'
|
||||
import type { StatCalculated } from '@/parser/modifiers'
|
||||
import type { StatFilter } from './interfaces'
|
||||
|
||||
export default defineComponent({
|
||||
components: { ItemModifierText },
|
||||
@@ -22,6 +23,10 @@ export default defineComponent({
|
||||
source: {
|
||||
type: Object as PropType<StatCalculated['sources'][number]>,
|
||||
required: true
|
||||
},
|
||||
filter: {
|
||||
type: Object as PropType<StatFilter>,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
@@ -47,8 +52,12 @@ export default defineComponent({
|
||||
const { stats } = props.source.modifier
|
||||
const { stat: contribStat } = props.source.stat
|
||||
|
||||
// TODO: percentRoll, isNegated
|
||||
const contribution = props.source.contributes?.value
|
||||
let contribution = props.source.contributes?.value
|
||||
if (contribution != null) {
|
||||
const filter = props.filter.roll!
|
||||
contribution *= (filter.isNegated) ? -1 : 1
|
||||
contribution = roundRoll(contribution, filter.dp)
|
||||
}
|
||||
|
||||
return stats.map((parsed) => {
|
||||
if (parsed.stat.ref !== contribStat.ref) {
|
||||
@@ -89,6 +98,14 @@ export default defineComponent({
|
||||
@apply text-gray-500;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.contribution {
|
||||
margin-left: auto;
|
||||
@apply w-12;
|
||||
@apply rounded;
|
||||
@apply border border-gray-700;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { ParsedItem, ItemRarity, ItemCategory } from '@/parser'
|
||||
import { ModifierType, StatCalculated, StatRoll, statSourcesTotal, translateStatWithRoll } from '@/parser/modifiers'
|
||||
import { ModifierType, StatCalculated, statSourcesTotal, translateStatWithRoll } from '@/parser/modifiers'
|
||||
import { uniqueModFilterPartial } from './unique-roll'
|
||||
import { rollToFilter, percentRoll, roundRoll } from './util'
|
||||
import { percentRoll, roundRoll } from './util'
|
||||
import { FilterTag, ItemHasEmptyModifier, StatFilter } from './interfaces'
|
||||
import { filterPseudo } from './pseudo'
|
||||
import { filterItemProp } from './pseudo/item-property'
|
||||
import { filterUniqueItemProp } from './pseudo/item-property-unique'
|
||||
import { StatBetter } from '@/assets/data'
|
||||
|
||||
export interface FiltersCreationContext {
|
||||
readonly item: ParsedItem
|
||||
@@ -133,7 +134,21 @@ export function calculatedStatToFilter (
|
||||
) {
|
||||
uniqueModFilterPartial(item, roll, filter, (opts.percent * 2), dp)
|
||||
} else {
|
||||
itemModFilterPartial(calc, roll, filter, opts.percent, dp)
|
||||
const percent = (calc.type === ModifierType.Enchant)
|
||||
? 0
|
||||
: opts.percent
|
||||
|
||||
filter.roll = {
|
||||
value: roundRoll(roll.value, dp),
|
||||
min: undefined,
|
||||
max: undefined,
|
||||
default: {
|
||||
min: percentRoll(roll.value, -percent, Math.floor, dp),
|
||||
max: percentRoll(roll.value, +percent, Math.ceil, dp)
|
||||
},
|
||||
dp: dp,
|
||||
isNegated: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,31 +157,6 @@ export function calculatedStatToFilter (
|
||||
return filter
|
||||
}
|
||||
|
||||
function itemModFilterPartial (
|
||||
calc: StatCalculated,
|
||||
roll: StatRoll,
|
||||
filter: StatFilter,
|
||||
percent: number,
|
||||
dp: boolean
|
||||
) {
|
||||
if (roll) {
|
||||
if (calc.type === ModifierType.Enchant) {
|
||||
filter.roll = {
|
||||
value: roundRoll(roll.value, dp),
|
||||
min: percentRoll(roll.value, 0, Math.floor, dp),
|
||||
max: percentRoll(roll.value, 0, Math.ceil, dp),
|
||||
default: {
|
||||
min: percentRoll(roll.value, 0, Math.floor, dp),
|
||||
max: percentRoll(roll.value, 0, Math.ceil, dp)
|
||||
},
|
||||
step: dp ? 0.01 : 1
|
||||
}
|
||||
} else {
|
||||
filter.roll = rollToFilter(roll.value, { dp: dp, percent })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function filterAdjustmentForNegate (
|
||||
calc: StatCalculated,
|
||||
negate: boolean,
|
||||
@@ -176,37 +166,41 @@ function filterAdjustmentForNegate (
|
||||
|
||||
const { roll } = filter
|
||||
|
||||
if (roll.min == null && roll.max == null) {
|
||||
switch (calc.stat.better) {
|
||||
case StatBetter.PositiveRoll:
|
||||
roll.min = roll.default.min
|
||||
break
|
||||
case StatBetter.NegativeRoll:
|
||||
roll.max = roll.default.max
|
||||
break
|
||||
case StatBetter.NotComparable:
|
||||
roll.min = roll.default.min
|
||||
roll.max = roll.default.max
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (negate) {
|
||||
roll.tradeInvert = true
|
||||
roll.isNegated = true
|
||||
const swap = JSON.parse(JSON.stringify(roll)) as typeof roll
|
||||
|
||||
if (roll.bounds) {
|
||||
roll.bounds.min = -1 * swap.bounds!.max
|
||||
roll.bounds.max = -1 * swap.bounds!.min
|
||||
if (swap.bounds) {
|
||||
roll.bounds!.min = -1 * swap.bounds.max
|
||||
roll.bounds!.max = -1 * swap.bounds.min
|
||||
}
|
||||
|
||||
roll.default.min = -1 * swap.default.max
|
||||
roll.default.max = -1 * swap.default.min
|
||||
|
||||
if (roll.min == null && roll.max == null) {
|
||||
// TODO: for some stats reduced is better
|
||||
roll.min = -1 * swap.default.max
|
||||
} else {
|
||||
if (roll.max != null) {
|
||||
roll.min = -1 * (swap.max as number)
|
||||
}
|
||||
if (roll.min != null) {
|
||||
roll.max = -1 * (swap.min as number)
|
||||
}
|
||||
}
|
||||
if (roll.value != null) {
|
||||
roll.value = -1 * swap.value
|
||||
}
|
||||
} else {
|
||||
if (roll.min == null && roll.max == null) {
|
||||
// TODO: for some stats reduced is better
|
||||
roll.min = roll.default.min
|
||||
}
|
||||
roll.value = -1 * swap.value
|
||||
roll.min = (typeof swap.max === 'number')
|
||||
? -1 * swap.max
|
||||
: undefined
|
||||
roll.max = (typeof swap.min === 'number')
|
||||
? -1 * swap.min
|
||||
: undefined
|
||||
}
|
||||
|
||||
if (calc.stat.trade.inverted) {
|
||||
|
||||
@@ -91,7 +91,8 @@ export interface StatFilter {
|
||||
default: { min: number, max: number }
|
||||
bounds?: { min: number, max: number }
|
||||
tradeInvert?: boolean
|
||||
step: number
|
||||
dp: boolean | number
|
||||
isNegated: boolean
|
||||
}
|
||||
option?: {
|
||||
value: number // NOTE: mutable in UI
|
||||
|
||||
@@ -27,7 +27,8 @@ export function uniqueModFilterPartial (
|
||||
min: statRoll.value,
|
||||
max: statRoll.value
|
||||
},
|
||||
step: dp ? 0.01 : 1
|
||||
dp: dp,
|
||||
isNegated: false
|
||||
}
|
||||
|
||||
if (filter.tag !== FilterTag.Variant && filter.tag !== FilterTag.Corrupted) {
|
||||
@@ -46,7 +47,8 @@ export function uniqueModFilterPartial (
|
||||
min: statRoll.min,
|
||||
max: statRoll.max
|
||||
},
|
||||
step: dp ? 0.01 : 1
|
||||
dp: dp,
|
||||
isNegated: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,14 +10,16 @@ function decimalPlaces (value: number, dp: number | boolean): number {
|
||||
}
|
||||
}
|
||||
|
||||
export function roundRoll (value: number, dp: number | boolean) {
|
||||
const round = Math.pow(10, decimalPlaces(value, dp))
|
||||
// round value down (toward zero)
|
||||
return Math.trunc(value * round) / round
|
||||
}
|
||||
export const roundRoll = (value: number, dp: number | boolean) =>
|
||||
percentRoll(value, 0, Math.trunc, dp)
|
||||
|
||||
export function percentRoll (value: number, p: number, method: Math['floor'] | Math['ceil'], dp: number | boolean = false): number {
|
||||
const res = value + value * p / 100
|
||||
export function percentRoll (
|
||||
value: number,
|
||||
p: number,
|
||||
method: Math['floor'] | Math['ceil'] | Math['trunc'],
|
||||
dp: number | boolean = false
|
||||
): number {
|
||||
const res = value + Math.abs(value) * p / 100
|
||||
|
||||
const rounding = Math.pow(10, decimalPlaces(value, dp))
|
||||
return method((res + Number.EPSILON) * rounding) / rounding
|
||||
@@ -32,21 +34,19 @@ export function percentRollDelta (value: number, delta: number, p: number, metho
|
||||
|
||||
export function rollToFilter (
|
||||
roll: number,
|
||||
opts: { percent: number, neverNegated?: true, dp?: boolean | number }
|
||||
opts: { percent: number, neverNegated: true, dp?: boolean | number }
|
||||
): StatFilter['roll'] {
|
||||
const { percent, neverNegated, dp } = opts
|
||||
const { percent, dp } = opts
|
||||
|
||||
// opts.neverNegated is false only in one case, but keep it
|
||||
// disabled by default, so opts.neverNegated acts more like
|
||||
// acknowledgment of what you are doing
|
||||
return {
|
||||
value: roundRoll(roll, dp ?? false),
|
||||
default: {
|
||||
min: percentRoll(roll, -percent * Math.sign(roll), Math.floor, dp),
|
||||
max: percentRoll(roll, +percent * Math.sign(roll), Math.ceil, dp)
|
||||
},
|
||||
min: neverNegated ? percentRoll(roll, -percent * Math.sign(roll), Math.floor, dp) : undefined,
|
||||
min: percentRoll(roll, -percent, Math.floor, dp),
|
||||
max: undefined,
|
||||
step: dp ? 0.01 : 1
|
||||
default: {
|
||||
min: percentRoll(roll, -percent, Math.floor, dp),
|
||||
max: percentRoll(roll, +percent, Math.ceil, dp)
|
||||
},
|
||||
dp: dp ?? false,
|
||||
isNegated: false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user