forked from profectus/Profectus
Changed how conversion gain modifiers work, so nextAt will be correct
This commit is contained in:
parent
84ed880533
commit
f40765e4de
1 changed files with 78 additions and 43 deletions
|
@ -1,7 +1,10 @@
|
||||||
import { GenericLayer } from "game/layers";
|
import { GenericLayer } from "game/layers";
|
||||||
import Decimal, { DecimalSource } from "util/bignum";
|
import Decimal, { DecimalSource } from "util/bignum";
|
||||||
|
import { isFunction } from "util/common";
|
||||||
import {
|
import {
|
||||||
Computable,
|
Computable,
|
||||||
|
convertComputable,
|
||||||
|
DoNotCache,
|
||||||
GetComputableTypeWithDefault,
|
GetComputableTypeWithDefault,
|
||||||
processComputable,
|
processComputable,
|
||||||
ProcessedComputable
|
ProcessedComputable
|
||||||
|
@ -20,7 +23,7 @@ export interface ConversionOptions {
|
||||||
buyMax?: Computable<boolean>;
|
buyMax?: Computable<boolean>;
|
||||||
roundUpCost?: Computable<boolean>;
|
roundUpCost?: Computable<boolean>;
|
||||||
convert?: VoidFunction;
|
convert?: VoidFunction;
|
||||||
modifyGainAmount?: (gain: DecimalSource) => DecimalSource;
|
gainModifier?: GainModifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BaseConversion {
|
export interface BaseConversion {
|
||||||
|
@ -47,6 +50,11 @@ export type GenericConversion = Replace<
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
export interface GainModifier {
|
||||||
|
apply: (gain: DecimalSource) => DecimalSource;
|
||||||
|
revert: (gain: DecimalSource) => DecimalSource;
|
||||||
|
}
|
||||||
|
|
||||||
export function createConversion<T extends ConversionOptions>(
|
export function createConversion<T extends ConversionOptions>(
|
||||||
optionsFunc: () => T & ThisType<Conversion<T>>
|
optionsFunc: () => T & ThisType<Conversion<T>>
|
||||||
): Conversion<T> {
|
): Conversion<T> {
|
||||||
|
@ -54,25 +62,33 @@ export function createConversion<T extends ConversionOptions>(
|
||||||
const conversion: T = optionsFunc();
|
const conversion: T = optionsFunc();
|
||||||
|
|
||||||
if (conversion.currentGain == null) {
|
if (conversion.currentGain == null) {
|
||||||
conversion.currentGain = computed(() =>
|
conversion.currentGain = computed(() => {
|
||||||
conversion.scaling.currentGain(conversion as GenericConversion)
|
let gain = conversion.gainModifier
|
||||||
);
|
? conversion.gainModifier.apply(
|
||||||
|
conversion.scaling.currentGain(conversion as GenericConversion)
|
||||||
|
)
|
||||||
|
: conversion.scaling.currentGain(conversion as GenericConversion);
|
||||||
|
gain = Decimal.floor(gain).max(0);
|
||||||
|
|
||||||
|
if (!conversion.buyMax) {
|
||||||
|
gain = gain.min(1);
|
||||||
|
}
|
||||||
|
return gain;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (conversion.nextAt == null) {
|
if (conversion.nextAt == null) {
|
||||||
conversion.nextAt = computed(() =>
|
conversion.nextAt = computed(() => {
|
||||||
conversion.scaling.nextAt(conversion as GenericConversion)
|
let next = conversion.scaling.nextAt(conversion as GenericConversion);
|
||||||
);
|
if (conversion.roundUpCost) next = Decimal.ceil(next);
|
||||||
|
return next;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conversion.convert == null) {
|
if (conversion.convert == null) {
|
||||||
conversion.convert = function () {
|
conversion.convert = function () {
|
||||||
conversion.gainResource.value = Decimal.add(
|
conversion.gainResource.value = Decimal.add(
|
||||||
conversion.gainResource.value,
|
conversion.gainResource.value,
|
||||||
conversion.modifyGainAmount
|
unref((conversion as GenericConversion).currentGain)
|
||||||
? conversion.modifyGainAmount(
|
|
||||||
unref((conversion as GenericConversion).currentGain)
|
|
||||||
)
|
|
||||||
: unref((conversion as GenericConversion).currentGain)
|
|
||||||
);
|
);
|
||||||
// TODO just subtract cost?
|
// TODO just subtract cost?
|
||||||
conversion.baseResource.value = 0;
|
conversion.baseResource.value = 0;
|
||||||
|
@ -107,25 +123,17 @@ export function createLinearScaling(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let gain = Decimal.sub(conversion.baseResource.value, unref(base))
|
return Decimal.sub(conversion.baseResource.value, unref(base))
|
||||||
.sub(1)
|
.sub(1)
|
||||||
.times(unref(coefficient))
|
.times(unref(coefficient))
|
||||||
.add(1)
|
.add(1);
|
||||||
.floor()
|
|
||||||
.max(0);
|
|
||||||
|
|
||||||
if (!conversion.buyMax) {
|
|
||||||
gain = gain.min(1);
|
|
||||||
}
|
|
||||||
return gain;
|
|
||||||
},
|
},
|
||||||
nextAt(conversion) {
|
nextAt(conversion) {
|
||||||
let next = Decimal.add(unref(conversion.currentGain), 1)
|
let next: DecimalSource = Decimal.add(unref(conversion.currentGain), 1);
|
||||||
.times(unref(coefficient))
|
if (conversion.gainModifier) {
|
||||||
.add(unref(base))
|
next = conversion.gainModifier.revert(next);
|
||||||
.max(unref(base));
|
}
|
||||||
if (conversion.roundUpCost) next = next.ceil();
|
return Decimal.times(next, unref(coefficient)).add(unref(base)).max(unref(base));
|
||||||
return next;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -138,27 +146,21 @@ export function createPolynomialScaling(
|
||||||
): ScalingFunction {
|
): ScalingFunction {
|
||||||
return {
|
return {
|
||||||
currentGain(conversion) {
|
currentGain(conversion) {
|
||||||
let gain = Decimal.div(conversion.baseResource.value, unref(base))
|
const gain = Decimal.div(conversion.baseResource.value, unref(base)).pow(
|
||||||
.pow(unref(exponent))
|
unref(exponent)
|
||||||
.floor()
|
);
|
||||||
.max(0);
|
|
||||||
|
|
||||||
if (gain.isNan()) {
|
if (gain.isNan()) {
|
||||||
return new Decimal(0);
|
return new Decimal(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!conversion.buyMax) {
|
|
||||||
gain = gain.min(1);
|
|
||||||
}
|
|
||||||
return gain;
|
return gain;
|
||||||
},
|
},
|
||||||
nextAt(conversion) {
|
nextAt(conversion) {
|
||||||
let next = Decimal.add(unref(conversion.currentGain), 1)
|
let next: DecimalSource = Decimal.add(unref(conversion.currentGain), 1);
|
||||||
.root(unref(exponent))
|
if (conversion.gainModifier) {
|
||||||
.times(unref(base))
|
next = conversion.gainModifier.revert(next);
|
||||||
.max(unref(base));
|
}
|
||||||
if (conversion.roundUpCost) next = next.ceil();
|
return Decimal.root(next, unref(exponent)).times(unref(base)).max(unref(base));
|
||||||
return next;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -188,8 +190,10 @@ export function createIndependentConversion<S extends ConversionOptions>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
setDefault(conversion, "convert", function () {
|
setDefault(conversion, "convert", function () {
|
||||||
conversion.gainResource.value = conversion.modifyGainAmount
|
conversion.gainResource.value = conversion.gainModifier
|
||||||
? conversion.modifyGainAmount(unref((conversion as GenericConversion).currentGain))
|
? conversion.gainModifier.apply(
|
||||||
|
unref((conversion as GenericConversion).currentGain)
|
||||||
|
)
|
||||||
: unref((conversion as GenericConversion).currentGain);
|
: unref((conversion as GenericConversion).currentGain);
|
||||||
// TODO just subtract cost?
|
// TODO just subtract cost?
|
||||||
// Maybe by adding a cost function to scaling and nextAt just calls the cost function
|
// Maybe by adding a cost function to scaling and nextAt just calls the cost function
|
||||||
|
@ -250,3 +254,34 @@ export function addHardcap(
|
||||||
currentGain: conversion => Decimal.min(scaling.currentGain(conversion), unref(cap))
|
currentGain: conversion => Decimal.min(scaling.currentGain(conversion), unref(cap))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createAdditiveModifier(addend: Computable<DecimalSource>): GainModifier {
|
||||||
|
const processedAddend = convertComputable(addend);
|
||||||
|
return {
|
||||||
|
apply: gain => Decimal.add(gain, unref(processedAddend)),
|
||||||
|
revert: gain => Decimal.sub(gain, unref(processedAddend))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createMultiplicativeModifier(multiplier: Computable<DecimalSource>): GainModifier {
|
||||||
|
const processedMultiplier = convertComputable(multiplier);
|
||||||
|
return {
|
||||||
|
apply: gain => Decimal.times(gain, unref(processedMultiplier)),
|
||||||
|
revert: gain => Decimal.div(gain, unref(processedMultiplier))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createExponentialModifier(exponent: Computable<DecimalSource>): GainModifier {
|
||||||
|
const processedExponent = convertComputable(exponent);
|
||||||
|
return {
|
||||||
|
apply: gain => Decimal.pow(gain, unref(processedExponent)),
|
||||||
|
revert: gain => Decimal.root(gain, unref(processedExponent))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createSequentialModifier(...modifiers: GainModifier[]): GainModifier {
|
||||||
|
return {
|
||||||
|
apply: gain => modifiers.reduce((gain, modifier) => modifier.apply(gain), gain),
|
||||||
|
revert: gain => modifiers.reduceRight((gain, modifier) => modifier.revert(gain), gain)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue