From 9708e2a830f254477297e64131a71b4b19e716e7 Mon Sep 17 00:00:00 2001
From: Van Nguyen <36019388+nguyentvan7@users.noreply.github.com>
Date: Sun, 5 Jan 2025 19:03:27 -0700
Subject: [PATCH 1/6] Add infrastructure for strikethrough on fields
---
libs/gi/ui/src/components/FieldDisplay.tsx | 1 +
libs/gi/ui/src/util/getCalcDisplay.tsx | 10 ++++++++--
libs/gi/wr/src/type.d.ts | 4 ++--
3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/libs/gi/ui/src/components/FieldDisplay.tsx b/libs/gi/ui/src/components/FieldDisplay.tsx
index d58afc9371..f4ec763dbd 100644
--- a/libs/gi/ui/src/components/FieldDisplay.tsx
+++ b/libs/gi/ui/src/components/FieldDisplay.tsx
@@ -198,6 +198,7 @@ export function NodeFieldDisplay({
gap: 1,
boxShadow: emphasize ? '0px 0px 0px 2px red inset' : undefined,
py: 0.25,
+ textDecoration: subVariant === 'strike' ? 'line-through' : undefined,
}}
component={component}
>
diff --git a/libs/gi/ui/src/util/getCalcDisplay.tsx b/libs/gi/ui/src/util/getCalcDisplay.tsx
index 531740096d..fe83a3fb08 100644
--- a/libs/gi/ui/src/util/getCalcDisplay.tsx
+++ b/libs/gi/ui/src/util/getCalcDisplay.tsx
@@ -13,6 +13,7 @@ import {
import { Translate } from '@genshin-optimizer/gi/i18n'
import type { CalcResult } from '@genshin-optimizer/gi/uidata'
import type { Info, InfoExtra, KeyMapPrefix } from '@genshin-optimizer/gi/wr'
+import { Typography } from '@mui/material'
import { useContext, type ReactNode } from 'react'
import { SillyContext } from '../context'
import { resolveInfo } from './resolveInfo'
@@ -220,11 +221,16 @@ function computeFormulaDisplay(
components.filter((c) => c)
result.formula = (
- <>
+
{components.map((x, i) => (
{x}
))}
- >
+
)
return result
diff --git a/libs/gi/wr/src/type.d.ts b/libs/gi/wr/src/type.d.ts
index be2489e22d..d81ef12c9d 100644
--- a/libs/gi/wr/src/type.d.ts
+++ b/libs/gi/wr/src/type.d.ts
@@ -48,7 +48,7 @@ export type Info = {
prefix?: KeyMapPrefix
source?: CharacterSheetKey | WeaponKey | ArtifactSetKey
variant?: InfoVariant
- subVariant?: InfoVariant
+ subVariant?: InfoVariant | 'strike'
asConst?: true
pivot?: true
fixed?: number
@@ -179,7 +179,7 @@ interface DynamicNumInput {
[key: string]: DisplaySub
}
conditional?: NodeData
- teamBuff?: Input & { tally?: NodeData }
+ teamBuff?: Input & { tally?: NodeData }
}
export interface NodeData {
[key: string]: typeof key extends 'operation' ? never : NodeData | T
From 7efea3782304b199c0cd269b481e2d4933108aac Mon Sep 17 00:00:00 2001
From: Van Nguyen <36019388+nguyentvan7@users.noreply.github.com>
Date: Sun, 5 Jan 2025 19:18:30 -0700
Subject: [PATCH 2/6] Add non-stacking buffs for NO4
---
.../src/Artifacts/NoblesseOblige/index.tsx | 21 +++++++++++++---
libs/gi/sheets/src/SheetUtil.tsx | 25 ++++++++++++++++++-
libs/gi/wr/src/formula.ts | 3 +++
3 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/libs/gi/sheets/src/Artifacts/NoblesseOblige/index.tsx b/libs/gi/sheets/src/Artifacts/NoblesseOblige/index.tsx
index 874d8a1215..1d1b6b0144 100644
--- a/libs/gi/sheets/src/Artifacts/NoblesseOblige/index.tsx
+++ b/libs/gi/sheets/src/Artifacts/NoblesseOblige/index.tsx
@@ -1,7 +1,13 @@
import type { ArtifactSetKey } from '@genshin-optimizer/gi/consts'
import type { Data } from '@genshin-optimizer/gi/wr'
-import { equal, greaterEq, input, percent } from '@genshin-optimizer/gi/wr'
-import { cond, st, stg } from '../../SheetUtil'
+import {
+ equalStr,
+ greaterEq,
+ greaterEqStr,
+ input,
+ percent,
+} from '@genshin-optimizer/gi/wr'
+import { cond, nonStackBuff, st, stg } from '../../SheetUtil'
import { ArtifactSheet, setHeaderTemplate } from '../ArtifactSheet'
import type { SetEffectSheet } from '../IArtifactSheet'
import { dataObjForArtifactSheet } from '../dataUtil'
@@ -12,11 +18,12 @@ const setHeader = setHeaderTemplate(key)
const set2 = greaterEq(input.artSet.NoblesseOblige, 2, percent(0.2))
const [condSet4Path, condSet4] = cond(key, 'set4')
-const set4 = greaterEq(
+const set4TallyWrite = greaterEqStr(
input.artSet.NoblesseOblige,
4,
- equal(condSet4, 'on', percent(0.2))
+ equalStr(condSet4, 'on', input.charKey)
)
+const [set4, set4Inactive] = nonStackBuff('no4', 'atk_', percent(0.2))
export const data: Data = dataObjForArtifactSheet(key, {
premod: {
@@ -26,6 +33,9 @@ export const data: Data = dataObjForArtifactSheet(key, {
premod: {
atk_: set4,
},
+ tally: {
+ no4: set4TallyWrite,
+ },
},
})
@@ -45,6 +55,9 @@ const sheet: SetEffectSheet = {
{
node: set4,
},
+ {
+ node: set4Inactive,
+ },
{
text: stg('duration'),
value: 12,
diff --git a/libs/gi/sheets/src/SheetUtil.tsx b/libs/gi/sheets/src/SheetUtil.tsx
index cc3105ade2..842202b7cb 100644
--- a/libs/gi/sheets/src/SheetUtil.tsx
+++ b/libs/gi/sheets/src/SheetUtil.tsx
@@ -5,12 +5,20 @@ import type {
WeaponKey,
} from '@genshin-optimizer/gi/consts'
import { Translate } from '@genshin-optimizer/gi/i18n'
-import type { Info, NumNode, ReadNode, StrNode } from '@genshin-optimizer/gi/wr'
+import type {
+ Info,
+ NonStackBuff,
+ NumNode,
+ ReadNode,
+ StrNode,
+} from '@genshin-optimizer/gi/wr'
import {
customStringRead,
equal,
infoMut,
input,
+ tally,
+ unequal,
} from '@genshin-optimizer/gi/wr'
import type { ReactNode } from 'react'
@@ -80,3 +88,18 @@ export function activeCharBuff(
equal(input.activeCharKey, buffTargetKey, node),
]
}
+
+export function nonStackBuff(
+ buffName: NonStackBuff,
+ path: string,
+ buffNode: NumNode
+) {
+ return [
+ equal(tally[buffName], input.charKey, buffNode),
+ unequal(tally[buffName], input.charKey, buffNode, {
+ path,
+ isTeamBuff: true,
+ subVariant: 'strike',
+ }),
+ ]
+}
diff --git a/libs/gi/wr/src/formula.ts b/libs/gi/wr/src/formula.ts
index 3f0a59bb94..5e22edfa36 100644
--- a/libs/gi/wr/src/formula.ts
+++ b/libs/gi/wr/src/formula.ts
@@ -46,6 +46,8 @@ const asConst = true as const,
const allElements = allElementWithPhyKeys
const allTalents = ['auto', 'skill', 'burst'] as const
+const allNonstackBuffs = ['no4'] as const
+export type NonStackBuff = (typeof allNonstackBuffs)[number]
const allMoves = [
'normal',
'charged',
@@ -578,6 +580,7 @@ const _tally = setReadNodeKeys(
{
...objKeyMap([...allElements, ...allRegionKeys], (_) => read('add')),
maxEleMas: read('max'),
+ ...objKeyMap(allNonstackBuffs, () => stringRead('small')),
},
['tally']
)
From 52c56f991b738d767dcb803262dcefc86e4a8eb0 Mon Sep 17 00:00:00 2001
From: Van Nguyen <36019388+nguyentvan7@users.noreply.github.com>
Date: Thu, 9 Jan 2025 15:23:35 -0700
Subject: [PATCH 3/6] Modify strikethrough to be a separate info field
---
libs/gi/sheets/src/SheetUtil.tsx | 2 +-
libs/gi/ui/src/components/FieldDisplay.tsx | 4 ++--
libs/gi/ui/src/util/getCalcDisplay.tsx | 2 +-
libs/gi/wr/src/type.d.ts | 3 ++-
4 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/libs/gi/sheets/src/SheetUtil.tsx b/libs/gi/sheets/src/SheetUtil.tsx
index 842202b7cb..4cdfcc6888 100644
--- a/libs/gi/sheets/src/SheetUtil.tsx
+++ b/libs/gi/sheets/src/SheetUtil.tsx
@@ -99,7 +99,7 @@ export function nonStackBuff(
unequal(tally[buffName], input.charKey, buffNode, {
path,
isTeamBuff: true,
- subVariant: 'strike',
+ strikethrough: true,
}),
]
}
diff --git a/libs/gi/ui/src/components/FieldDisplay.tsx b/libs/gi/ui/src/components/FieldDisplay.tsx
index f4ec763dbd..78e6b2c45b 100644
--- a/libs/gi/ui/src/components/FieldDisplay.tsx
+++ b/libs/gi/ui/src/components/FieldDisplay.tsx
@@ -129,7 +129,7 @@ export function NodeFieldDisplay({
[setFormulaData, data, calcRes]
)
if (!calcRes && !compareCalcRes) return null
- const { multi } = calcRes?.info ?? compareCalcRes?.info ?? {}
+ const { multi, strikethrough } = calcRes?.info ?? compareCalcRes?.info ?? {}
const multiDisplay = multi && {multi}×
const calcValue = calcRes?.value ?? 0
@@ -198,7 +198,7 @@ export function NodeFieldDisplay({
gap: 1,
boxShadow: emphasize ? '0px 0px 0px 2px red inset' : undefined,
py: 0.25,
- textDecoration: subVariant === 'strike' ? 'line-through' : undefined,
+ textDecoration: strikethrough ? 'line-through' : undefined,
}}
component={component}
>
diff --git a/libs/gi/ui/src/util/getCalcDisplay.tsx b/libs/gi/ui/src/util/getCalcDisplay.tsx
index fe83a3fb08..92c452f084 100644
--- a/libs/gi/ui/src/util/getCalcDisplay.tsx
+++ b/libs/gi/ui/src/util/getCalcDisplay.tsx
@@ -224,7 +224,7 @@ function computeFormulaDisplay(
{components.map((x, i) => (
diff --git a/libs/gi/wr/src/type.d.ts b/libs/gi/wr/src/type.d.ts
index d81ef12c9d..12d69bd099 100644
--- a/libs/gi/wr/src/type.d.ts
+++ b/libs/gi/wr/src/type.d.ts
@@ -48,12 +48,13 @@ export type Info = {
prefix?: KeyMapPrefix
source?: CharacterSheetKey | WeaponKey | ArtifactSetKey
variant?: InfoVariant
- subVariant?: InfoVariant | 'strike'
+ subVariant?: InfoVariant
asConst?: true
pivot?: true
fixed?: number
isTeamBuff?: boolean
multi?: number
+ strikethrough?: boolean
}
export type Variant =
| ElementWithPhyKey
From 948b1661a5e03e8639f2be6fb641856f59a7bc03 Mon Sep 17 00:00:00 2001
From: Van Nguyen <36019388+nguyentvan7@users.noreply.github.com>
Date: Thu, 9 Jan 2025 16:39:49 -0700
Subject: [PATCH 4/6] Move nonstacking to its own namespace
---
.../gi/sheets/src/Artifacts/NoblesseOblige/index.tsx | 2 +-
libs/gi/sheets/src/SheetUtil.tsx | 5 +++--
libs/gi/uidata/src/uiData.ts | 3 +++
libs/gi/wr/src/api.ts | 12 +++++++++---
libs/gi/wr/src/formula.ts | 8 ++++++--
libs/gi/wr/src/type.d.ts | 7 +++++--
6 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/libs/gi/sheets/src/Artifacts/NoblesseOblige/index.tsx b/libs/gi/sheets/src/Artifacts/NoblesseOblige/index.tsx
index 1d1b6b0144..0e1f0a033c 100644
--- a/libs/gi/sheets/src/Artifacts/NoblesseOblige/index.tsx
+++ b/libs/gi/sheets/src/Artifacts/NoblesseOblige/index.tsx
@@ -33,7 +33,7 @@ export const data: Data = dataObjForArtifactSheet(key, {
premod: {
atk_: set4,
},
- tally: {
+ nonStacking: {
no4: set4TallyWrite,
},
},
diff --git a/libs/gi/sheets/src/SheetUtil.tsx b/libs/gi/sheets/src/SheetUtil.tsx
index 4cdfcc6888..7db643351e 100644
--- a/libs/gi/sheets/src/SheetUtil.tsx
+++ b/libs/gi/sheets/src/SheetUtil.tsx
@@ -17,6 +17,7 @@ import {
equal,
infoMut,
input,
+ nonStacking,
tally,
unequal,
} from '@genshin-optimizer/gi/wr'
@@ -95,8 +96,8 @@ export function nonStackBuff(
buffNode: NumNode
) {
return [
- equal(tally[buffName], input.charKey, buffNode),
- unequal(tally[buffName], input.charKey, buffNode, {
+ equal(nonStacking[buffName], input.charKey, buffNode),
+ unequal(nonStacking[buffName], input.charKey, buffNode, {
path,
isTeamBuff: true,
strikethrough: true,
diff --git a/libs/gi/uidata/src/uiData.ts b/libs/gi/uidata/src/uiData.ts
index 14914244c6..23203ddd04 100644
--- a/libs/gi/uidata/src/uiData.ts
+++ b/libs/gi/uidata/src/uiData.ts
@@ -29,6 +29,7 @@ import {
deepNodeClone,
input,
mergeData,
+ nonStacking,
resetData,
setReadNodeKeys,
tally,
@@ -537,6 +538,8 @@ export function uiDataForTeam(
const newNode = customRead(path)
if (path[0] === 'teamBuff' && path[1] === 'tally')
newNode.accu = objPathValue(tally, path.slice(2))?.accu
+ if (path[0] === 'teamBuff' && path[1] === 'nonStacking')
+ newNode.accu = objPathValue(nonStacking, path.slice(2))?.accu
layeredAssignment(customReadNodes, path, newNode)
return newNode
}
diff --git a/libs/gi/wr/src/api.ts b/libs/gi/wr/src/api.ts
index 70adcce29a..f69ef98f25 100644
--- a/libs/gi/wr/src/api.ts
+++ b/libs/gi/wr/src/api.ts
@@ -21,7 +21,7 @@ import type {
} from '@genshin-optimizer/gi/db'
import type { ICharacter } from '@genshin-optimizer/gi/good'
import { getMainStatValue } from '@genshin-optimizer/gi/util'
-import { input, tally } from './formula'
+import { input, nonStacking, tally } from './formula'
import type { Data, Info, NumNode, ReadNode, StrNode } from './type'
import { constant, data, infoMut, none, percent, prod, sum } from './utils'
@@ -41,7 +41,7 @@ export function inferInfoMut(data: Data, source?: Info['source']): Data {
| undefined
if (reference)
x.info = { ...x.info, ...reference.info, prefix: undefined, source }
- else if (path[0] !== 'tally')
+ else if (path[0] !== 'tally' && path[0] !== 'nonStacking')
console.error(
`Detect ${source} buff into non-existant key path ${path}`
)
@@ -246,7 +246,13 @@ export function mergeData(data: Data[]): Data {
if (data.length <= 1) return data[0]
if (data[0].operation) {
if (path[0] === 'teamBuff') path = path.slice(1)
- const base = path[0] === 'tally' ? ((path = path.slice(1)), tally) : input
+ const base =
+ path[0] === 'tally'
+ ? tally
+ : path[0] === 'nonStacking'
+ ? nonStacking
+ : input
+ if (path[0] === 'tally' || path[0] === 'nonStacking') path = path.slice(1)
/*eslint prefer-const: ["error", {"destructuring": "all"}]*/
let { accu, type } =
(objPathValue(base, path) as ReadNode | undefined) ??
diff --git a/libs/gi/wr/src/formula.ts b/libs/gi/wr/src/formula.ts
index 5e22edfa36..246e72c32f 100644
--- a/libs/gi/wr/src/formula.ts
+++ b/libs/gi/wr/src/formula.ts
@@ -580,7 +580,6 @@ const _tally = setReadNodeKeys(
{
...objKeyMap([...allElements, ...allRegionKeys], (_) => read('add')),
maxEleMas: read('max'),
- ...objKeyMap(allNonstackBuffs, () => stringRead('small')),
},
['tally']
)
@@ -590,6 +589,11 @@ const tally = {
ele: sum(...allElements.map((ele) => min(_tally[ele], 1))),
}
+const nonStacking = setReadNodeKeys(
+ objKeyMap(allNonstackBuffs, () => stringRead('small')),
+ ['nonStacking']
+)
+
/**
* List of `input` nodes, rearranged to conform to the needs of the
* UI code. This is a separate list so that the evolution of the UIs
@@ -607,4 +611,4 @@ export const infusionNode = stringPrio(
input.infusion.overridableSelf
)
-export { common, customBonus, input, tally, target, uiInput }
+export { common, customBonus, input, nonStacking, tally, target, uiInput }
diff --git a/libs/gi/wr/src/type.d.ts b/libs/gi/wr/src/type.d.ts
index 12d69bd099..5e90c35b6f 100644
--- a/libs/gi/wr/src/type.d.ts
+++ b/libs/gi/wr/src/type.d.ts
@@ -9,7 +9,7 @@ import type {
AmplifyingReactionsKey,
TransformativeReactionsKey,
} from '@genshin-optimizer/gi/keymap'
-import type { input, uiInput } from './formula'
+import type { input, NonStackBuff, uiInput } from './formula'
export type NumNode =
| ComputeNode
@@ -180,7 +180,10 @@ interface DynamicNumInput {
[key: string]: DisplaySub
}
conditional?: NodeData
- teamBuff?: Input & { tally?: NodeData }
+ teamBuff?: Input & {
+ tally?: NodeData
+ nonStacking?: Record
+ }
}
export interface NodeData {
[key: string]: typeof key extends 'operation' ? never : NodeData | T
From 6b01687393cc65adcaa077cd8229732934101b9b Mon Sep 17 00:00:00 2001
From: Van Nguyen <36019388+nguyentvan7@users.noreply.github.com>
Date: Thu, 9 Jan 2025 16:40:13 -0700
Subject: [PATCH 5/6] Fix format
---
libs/gi/ui/src/util/getCalcDisplay.tsx | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libs/gi/ui/src/util/getCalcDisplay.tsx b/libs/gi/ui/src/util/getCalcDisplay.tsx
index 92c452f084..67a1dbf775 100644
--- a/libs/gi/ui/src/util/getCalcDisplay.tsx
+++ b/libs/gi/ui/src/util/getCalcDisplay.tsx
@@ -223,8 +223,7 @@ function computeFormulaDisplay(
result.formula = (
{components.map((x, i) => (
From 96b0cbbb146629ac2c5128f2f3293625b56594cf Mon Sep 17 00:00:00 2001
From: Van Nguyen <36019388+nguyentvan7@users.noreply.github.com>
Date: Thu, 9 Jan 2025 19:10:09 -0700
Subject: [PATCH 6/6] Fix format
---
libs/gi/sheets/src/SheetUtil.tsx | 1 -
1 file changed, 1 deletion(-)
diff --git a/libs/gi/sheets/src/SheetUtil.tsx b/libs/gi/sheets/src/SheetUtil.tsx
index 7db643351e..6341840c66 100644
--- a/libs/gi/sheets/src/SheetUtil.tsx
+++ b/libs/gi/sheets/src/SheetUtil.tsx
@@ -18,7 +18,6 @@ import {
infoMut,
input,
nonStacking,
- tally,
unequal,
} from '@genshin-optimizer/gi/wr'
import type { ReactNode } from 'react'