Change buyMax to maximize on repeatables, and make requirements report ability to maximize
Also fixes up some of the requirements tests that weren't actually asserting
This commit is contained in:
parent
4fb2d90dbb
commit
dcb3bc949d
2 changed files with 37 additions and 39 deletions
|
@ -11,7 +11,12 @@ import {
|
|||
import { createLazyProxy } from "util/proxies";
|
||||
import { joinJSX, renderJSX } from "util/vue";
|
||||
import { computed, unref } from "vue";
|
||||
import Formula, { calculateCost, calculateMaxAffordable, GenericFormula } from "./formulas";
|
||||
import Formula, {
|
||||
calculateCost,
|
||||
calculateMaxAffordable,
|
||||
GenericFormula,
|
||||
InvertibleFormula
|
||||
} from "./formulas";
|
||||
|
||||
/**
|
||||
* An object that can be used to describe a requirement to perform some purchase or other action.
|
||||
|
@ -39,9 +44,9 @@ export interface Requirement {
|
|||
*/
|
||||
requiresPay: ProcessedComputable<boolean>;
|
||||
/**
|
||||
* Whether or not this requirement can have multiple levels of requirements that can be completed at once.
|
||||
* Whether or not this requirement can have multiple levels of requirements that can be met at once. Requirement is assumed to not have multiple levels if this property not present.
|
||||
*/
|
||||
buyMax?: ProcessedComputable<boolean>;
|
||||
canMaximize?: ProcessedComputable<boolean>;
|
||||
/**
|
||||
* Perform any effects to the game state that should happen when the requirement gets triggered.
|
||||
* @param amount The amount of levels of requirements to pay for.
|
||||
|
@ -61,7 +66,7 @@ export interface CostRequirementOptions {
|
|||
*/
|
||||
resource: Resource;
|
||||
/**
|
||||
* The amount of {@link resource} that must be met for this requirement. You can pass a formula, in which case {@link buyMax} will work out of the box (assuming its invertible and, for more accurate calculations, its integral is invertible). If you don't pass a formula then you can still support buyMax by passing a custom {@link pay} function.
|
||||
* The amount of {@link resource} that must be met for this requirement. You can pass a formula, in which case maximizing will work out of the box (assuming its invertible and, for more accurate calculations, its integral is invertible). If you don't pass a formula then you can still support maximizing by passing a custom {@link pay} function.
|
||||
*/
|
||||
cost: Computable<DecimalSource> | GenericFormula;
|
||||
/**
|
||||
|
@ -72,19 +77,14 @@ export interface CostRequirementOptions {
|
|||
* Pass-through to {@link Requirement.requiresPay}. If not set to false, the default {@link pay} function will remove {@link cost} from {@link resource}.
|
||||
*/
|
||||
requiresPay?: Computable<boolean>;
|
||||
/**
|
||||
* Pass-through to {@link Requirement.buyMax}.
|
||||
* @see {@link cost} for restrictions on buying max support.
|
||||
*/
|
||||
buyMax?: Computable<boolean>;
|
||||
/**
|
||||
* When calculating multiple levels to be handled at once, whether it should consider resources used for each level as spent. Setting this to false causes calculations to be faster with larger numbers and supports more math functions.
|
||||
* @see {Formula}
|
||||
*/
|
||||
spendResources?: Computable<boolean>;
|
||||
/**
|
||||
* Pass-through to {@link Requirement.pay}. May be required for buying max support.
|
||||
* @see {@link cost} for restrictions on buying max support.
|
||||
* Pass-through to {@link Requirement.pay}. May be required for maximizing support.
|
||||
* @see {@link cost} for restrictions on maximizing support.
|
||||
*/
|
||||
pay?: (amount?: DecimalSource) => void;
|
||||
}
|
||||
|
@ -159,16 +159,12 @@ export function createCostRequirement<T extends CostRequirementOptions>(
|
|||
: unref(req.cost as ProcessedComputable<DecimalSource>);
|
||||
req.resource.value = Decimal.sub(req.resource.value, cost).max(0);
|
||||
});
|
||||
processComputable(req as T, "buyMax");
|
||||
|
||||
if (
|
||||
"buyMax" in req &&
|
||||
req.buyMax !== false &&
|
||||
req.cost instanceof Formula &&
|
||||
req.cost.isInvertible()
|
||||
) {
|
||||
req.canMaximize = req.cost instanceof Formula && req.cost.isInvertible();
|
||||
|
||||
if (req.canMaximize) {
|
||||
req.requirementMet = calculateMaxAffordable(
|
||||
req.cost,
|
||||
req.cost as InvertibleFormula,
|
||||
req.resource,
|
||||
unref(req.spendResources as ProcessedComputable<boolean> | undefined) ?? true
|
||||
);
|
||||
|
@ -244,6 +240,8 @@ export function maxRequirementsMet(requirements: Requirements): DecimalSource {
|
|||
const reqsMet = unref(requirements.requirementMet);
|
||||
if (typeof reqsMet === "boolean") {
|
||||
return reqsMet ? Infinity : 0;
|
||||
} else if (Decimal.gt(reqsMet, 1) && unref(requirements.canMaximize) !== true) {
|
||||
return 1;
|
||||
}
|
||||
return reqsMet;
|
||||
}
|
||||
|
|
|
@ -27,23 +27,23 @@ describe("Creating cost requirement", () => {
|
|||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
test("resource pass-through", () => (requirement as any).resource === resource);
|
||||
test("resource pass-through", () => expect((requirement as any).resource).toBe(resource));
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
test("cost pass-through", () => (requirement as any).cost === 10);
|
||||
test("cost pass-through", () => expect((requirement as any).cost).toBe(10));
|
||||
|
||||
test("partialDisplay exists", () =>
|
||||
requirement.partialDisplay != null && typeof requirement.partialDisplay === "function");
|
||||
test("display exists", () =>
|
||||
requirement.display != null && typeof requirement.display === "function");
|
||||
test("pay exists", () => requirement.pay != null && typeof requirement.pay === "function");
|
||||
test("requirementMet exists", () =>
|
||||
requirement.requirementMet != null && isRef(requirement.requirementMet));
|
||||
test("is visible", () => requirement.visibility === Visibility.Visible);
|
||||
test("requires pay", () => requirement.requiresPay === true);
|
||||
expect(typeof requirement.partialDisplay).toBe("function"));
|
||||
test("display exists", () => expect(typeof requirement.display).toBe("function"));
|
||||
test("pay exists", () => expect(typeof requirement.pay).toBe("function"));
|
||||
test("requirementMet exists", () => {
|
||||
expect(requirement.requirementMet).not.toBeNull();
|
||||
expect(isRef(requirement.requirementMet)).toBe(true);
|
||||
});
|
||||
test("is visible", () => expect(requirement.visibility).toBe(Visibility.Visible));
|
||||
test("requires pay", () => expect(requirement.requiresPay).toBe(true));
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
test("spends resources", () => (requirement as any).spendResources !== false);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
test("does not buy max", () => (requirement as any).buyMax !== true);
|
||||
test("spends resources", () => expect((requirement as any).spendResources).toBe(true));
|
||||
test("cannot maximize", () => expect(unref(requirement.canMaximize)).toBe(false));
|
||||
});
|
||||
|
||||
describe("Fully customized", () => {
|
||||
|
@ -56,7 +56,7 @@ describe("Creating cost requirement", () => {
|
|||
cost: 10,
|
||||
visibility: Visibility.None,
|
||||
requiresPay: false,
|
||||
buyMax: true,
|
||||
maximize: true,
|
||||
spendResources: false,
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
pay() {}
|
||||
|
@ -67,12 +67,12 @@ describe("Creating cost requirement", () => {
|
|||
requirement.pay != null &&
|
||||
typeof requirement.pay === "function" &&
|
||||
requirement.pay.length === 1);
|
||||
test("is not visible", () => requirement.visibility === Visibility.None);
|
||||
test("does not require pay", () => requirement.requiresPay === false);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
test("does not spend resources", () => (requirement as any).spendResources);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
test("buys max", () => (requirement as any).buyMax);
|
||||
test("is not visible", () => expect(requirement.visibility).toBe(Visibility.None));
|
||||
test("does not require pay", () => expect(requirement.requiresPay).toBe(false));
|
||||
test("does not spend resources", () =>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
expect((requirement as any).spendResources).toBe(false));
|
||||
test("can maximize", () => expect(unref(requirement.canMaximize)).toBe(true));
|
||||
});
|
||||
|
||||
test("Requirement met when meeting the cost", () => {
|
||||
|
|
Loading…
Reference in a new issue