diff --git a/src/components/common/modifiers.css b/src/components/common/modifiers.css new file mode 100644 index 0000000..646d0c0 --- /dev/null +++ b/src/components/common/modifiers.css @@ -0,0 +1,12 @@ +.modifier-container { + display: flex; +} + +.modifier-amount { + flex-basis: 100px; + flex-shrink: 0; +} + +.modifier-description { + flex-grow: 1; +} diff --git a/src/game/modifiers.ts b/src/game/modifiers.ts deleted file mode 100644 index 1584c7b..0000000 --- a/src/game/modifiers.ts +++ /dev/null @@ -1,76 +0,0 @@ -import Decimal, { DecimalSource, format } from "util/bignum"; -import { Computable, convertComputable, ProcessedComputable } from "util/computed"; -import { computed, unref } from "vue"; - -export interface Modifier { - apply: (gain: DecimalSource) => DecimalSource; - revert: (gain: DecimalSource) => DecimalSource; - enabled: ProcessedComputable; - description?: ProcessedComputable; -} - -export function createAdditiveModifier( - addend: Computable, - description?: string, - enabled?: Computable -): Modifier { - const processedAddend = convertComputable(addend); - const processedEnabled = convertComputable(enabled == null ? true : enabled); - return { - apply: gain => Decimal.add(gain, unref(processedAddend)), - revert: gain => Decimal.sub(gain, unref(processedAddend)), - enabled: processedEnabled, - description: computed(() => `+${format(unref(processedAddend))} ${description}`) - }; -} - -export function createMultiplicativeModifier( - multiplier: Computable, - description?: string, - enabled?: Computable -): Modifier { - const processedMultiplier = convertComputable(multiplier); - const processedEnabled = convertComputable(enabled == null ? true : enabled); - return { - apply: gain => Decimal.times(gain, unref(processedMultiplier)), - revert: gain => Decimal.div(gain, unref(processedMultiplier)), - enabled: processedEnabled, - description: computed(() => `x${format(unref(processedMultiplier))} ${description}`) - }; -} - -export function createExponentialModifier( - exponent: Computable, - description?: string, - enabled?: Computable -): Modifier { - const processedExponent = convertComputable(exponent); - const processedEnabled = convertComputable(enabled == null ? true : enabled); - return { - apply: gain => Decimal.pow(gain, unref(processedExponent)), - revert: gain => Decimal.root(gain, unref(processedExponent)), - enabled: processedEnabled, - description: computed(() => `^${format(unref(processedExponent))} ${description}`) - }; -} - -export function createSequentialModifier(...modifiers: Modifier[]): Modifier { - return { - apply: gain => - modifiers - .filter(m => unref(m.enabled)) - .reduce((gain, modifier) => modifier.apply(gain), gain), - revert: gain => - modifiers - .filter(m => unref(m.enabled)) - .reduceRight((gain, modifier) => modifier.revert(gain), gain), - enabled: computed(() => modifiers.filter(m => unref(m.enabled)).length > 0), - description: computed(() => { - return modifiers - .filter(m => unref(m.enabled)) - .map(m => unref(m.description)) - .filter(d => d) - .join("\n"); - }) - }; -} diff --git a/src/game/modifiers.tsx b/src/game/modifiers.tsx new file mode 100644 index 0000000..532473f --- /dev/null +++ b/src/game/modifiers.tsx @@ -0,0 +1,115 @@ +import { CoercableComponent, jsx } from "features/feature"; +import Decimal, { DecimalSource, format } from "util/bignum"; +import { Computable, convertComputable, ProcessedComputable } from "util/computed"; +import { renderJSX } from "util/vue"; +import { computed, unref } from "vue"; +import "components/common/modifiers.css"; + +export interface Modifier { + apply: (gain: DecimalSource) => DecimalSource; + revert: (gain: DecimalSource) => DecimalSource; + enabled: ProcessedComputable; + description?: ProcessedComputable; +} + +export function createAdditiveModifier( + addend: Computable, + description?: Computable, + enabled?: Computable +): Modifier { + const processedAddend = convertComputable(addend); + const processedDescription = convertComputable(description); + const processedEnabled = convertComputable(enabled == null ? true : enabled); + return { + apply: gain => Decimal.add(gain, unref(processedAddend)), + revert: gain => Decimal.sub(gain, unref(processedAddend)), + enabled: processedEnabled, + description: jsx(() => ( +
+ +{format(unref(processedAddend))} + {unref(processedDescription) ? ( + + {/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */} + {renderJSX(unref(processedDescription)!)} + + ) : null} +
+ )) + }; +} + +export function createMultiplicativeModifier( + multiplier: Computable, + description?: Computable, + enabled?: Computable +): Modifier { + const processedMultiplier = convertComputable(multiplier); + const processedDescription = convertComputable(description); + const processedEnabled = convertComputable(enabled == null ? true : enabled); + return { + apply: gain => Decimal.times(gain, unref(processedMultiplier)), + revert: gain => Decimal.div(gain, unref(processedMultiplier)), + enabled: processedEnabled, + description: jsx(() => ( +
+ x{format(unref(processedMultiplier))} + {unref(processedDescription) ? ( + + {/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */} + {renderJSX(unref(processedDescription)!)} + + ) : null} +
+ )) + }; +} + +export function createExponentialModifier( + exponent: Computable, + description?: Computable, + enabled?: Computable +): Modifier { + const processedExponent = convertComputable(exponent); + const processedDescription = convertComputable(description); + const processedEnabled = convertComputable(enabled == null ? true : enabled); + return { + apply: gain => Decimal.pow(gain, unref(processedExponent)), + revert: gain => Decimal.root(gain, unref(processedExponent)), + enabled: processedEnabled, + description: jsx(() => ( +
+ ^{format(unref(processedExponent))} + {unref(processedDescription) ? ( + + {/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */} + {renderJSX(unref(processedDescription)!)} + + ) : null} +
+ )) + }; +} + +export function createSequentialModifier(...modifiers: Modifier[]): Required { + return { + apply: gain => + modifiers + .filter(m => unref(m.enabled)) + .reduce((gain, modifier) => modifier.apply(gain), gain), + revert: gain => + modifiers + .filter(m => unref(m.enabled)) + .reduceRight((gain, modifier) => modifier.revert(gain), gain), + enabled: computed(() => modifiers.filter(m => unref(m.enabled)).length > 0), + description: jsx(() => ( + <> + {( + modifiers + .filter(m => unref(m.enabled)) + .map(m => unref(m.description)) + .filter(d => d) as CoercableComponent[] + ).map(renderJSX)} + + )) + }; +}