forked from profectus/Profectus
Renamed buyables to repeatables
This commit is contained in:
parent
8987c0c69f
commit
ccb8e76eaf
1 changed files with 74 additions and 68 deletions
|
@ -25,9 +25,9 @@ import { coerceComponent, isCoercableComponent } from "util/vue";
|
||||||
import type { Ref } from "vue";
|
import type { Ref } from "vue";
|
||||||
import { computed, unref } from "vue";
|
import { computed, unref } from "vue";
|
||||||
|
|
||||||
export const BuyableType = Symbol("Buyable");
|
export const RepeatableType = Symbol("Repeatable");
|
||||||
|
|
||||||
export type BuyableDisplay =
|
export type RepeatableDisplay =
|
||||||
| CoercableComponent
|
| CoercableComponent
|
||||||
| {
|
| {
|
||||||
title?: CoercableComponent;
|
title?: CoercableComponent;
|
||||||
|
@ -36,7 +36,7 @@ export type BuyableDisplay =
|
||||||
showAmount?: boolean;
|
showAmount?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface BuyableOptions {
|
export interface RepeatableOptions {
|
||||||
visibility?: Computable<Visibility>;
|
visibility?: Computable<Visibility>;
|
||||||
requirements: Requirements;
|
requirements: Requirements;
|
||||||
purchaseLimit?: Computable<DecimalSource>;
|
purchaseLimit?: Computable<DecimalSource>;
|
||||||
|
@ -46,24 +46,24 @@ export interface BuyableOptions {
|
||||||
mark?: Computable<boolean | string>;
|
mark?: Computable<boolean | string>;
|
||||||
small?: Computable<boolean>;
|
small?: Computable<boolean>;
|
||||||
buyMax?: Computable<boolean>;
|
buyMax?: Computable<boolean>;
|
||||||
display?: Computable<BuyableDisplay>;
|
display?: Computable<RepeatableDisplay>;
|
||||||
onPurchase?: VoidFunction;
|
onPurchase?: VoidFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BaseBuyable {
|
export interface BaseRepeatable {
|
||||||
id: string;
|
id: string;
|
||||||
amount: Persistent<DecimalSource>;
|
amount: Persistent<DecimalSource>;
|
||||||
maxed: Ref<boolean>;
|
maxed: Ref<boolean>;
|
||||||
canClick: ProcessedComputable<boolean>;
|
canClick: ProcessedComputable<boolean>;
|
||||||
onClick: VoidFunction;
|
onClick: VoidFunction;
|
||||||
purchase: VoidFunction;
|
purchase: VoidFunction;
|
||||||
type: typeof BuyableType;
|
type: typeof RepeatableType;
|
||||||
[Component]: typeof ClickableComponent;
|
[Component]: typeof ClickableComponent;
|
||||||
[GatherProps]: () => Record<string, unknown>;
|
[GatherProps]: () => Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Buyable<T extends BuyableOptions> = Replace<
|
export type Repeatable<T extends RepeatableOptions> = Replace<
|
||||||
T & BaseBuyable,
|
T & BaseRepeatable,
|
||||||
{
|
{
|
||||||
visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>;
|
visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>;
|
||||||
requirements: GetComputableType<T["requirements"]>;
|
requirements: GetComputableType<T["requirements"]>;
|
||||||
|
@ -77,90 +77,96 @@ export type Buyable<T extends BuyableOptions> = Replace<
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type GenericBuyable = Replace<
|
export type GenericRepeatable = Replace<
|
||||||
Buyable<BuyableOptions>,
|
Repeatable<RepeatableOptions>,
|
||||||
{
|
{
|
||||||
visibility: ProcessedComputable<Visibility>;
|
visibility: ProcessedComputable<Visibility>;
|
||||||
purchaseLimit: ProcessedComputable<DecimalSource>;
|
purchaseLimit: ProcessedComputable<DecimalSource>;
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export function createBuyable<T extends BuyableOptions>(
|
export function createRepeatable<T extends RepeatableOptions>(
|
||||||
optionsFunc: OptionsFunc<T, BaseBuyable, GenericBuyable>
|
optionsFunc: OptionsFunc<T, BaseRepeatable, GenericRepeatable>
|
||||||
): Buyable<T> {
|
): Repeatable<T> {
|
||||||
const amount = persistent<DecimalSource>(0);
|
const amount = persistent<DecimalSource>(0);
|
||||||
return createLazyProxy(() => {
|
return createLazyProxy(() => {
|
||||||
const buyable = optionsFunc();
|
const repeatable = optionsFunc();
|
||||||
|
|
||||||
buyable.id = getUniqueID("buyable-");
|
repeatable.id = getUniqueID("repeatable-");
|
||||||
buyable.type = BuyableType;
|
repeatable.type = RepeatableType;
|
||||||
buyable[Component] = ClickableComponent;
|
repeatable[Component] = ClickableComponent;
|
||||||
|
|
||||||
buyable.amount = amount;
|
repeatable.amount = amount;
|
||||||
buyable.amount[DefaultValue] = buyable.initialValue ?? 0;
|
repeatable.amount[DefaultValue] = repeatable.initialValue ?? 0;
|
||||||
|
|
||||||
const limitRequirement = {
|
const limitRequirement = {
|
||||||
requirementMet: computed(() =>
|
requirementMet: computed(() =>
|
||||||
Decimal.sub(
|
Decimal.sub(
|
||||||
unref((buyable as GenericBuyable).purchaseLimit),
|
unref((repeatable as GenericRepeatable).purchaseLimit),
|
||||||
(buyable as GenericBuyable).amount.value
|
(repeatable as GenericRepeatable).amount.value
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
requiresPay: false,
|
requiresPay: false,
|
||||||
visibility: Visibility.None
|
visibility: Visibility.None
|
||||||
} as const;
|
} as const;
|
||||||
const visibilityRequirement = createVisibilityRequirement(buyable as GenericBuyable);
|
const visibilityRequirement = createVisibilityRequirement(repeatable as GenericRepeatable);
|
||||||
if (isArray(buyable.requirements)) {
|
if (isArray(repeatable.requirements)) {
|
||||||
buyable.requirements.unshift(visibilityRequirement);
|
repeatable.requirements.unshift(visibilityRequirement);
|
||||||
buyable.requirements.push(limitRequirement);
|
repeatable.requirements.push(limitRequirement);
|
||||||
} else {
|
} else {
|
||||||
buyable.requirements = [visibilityRequirement, buyable.requirements, limitRequirement];
|
repeatable.requirements = [
|
||||||
|
visibilityRequirement,
|
||||||
|
repeatable.requirements,
|
||||||
|
limitRequirement
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
buyable.maxed = computed(() =>
|
repeatable.maxed = computed(() =>
|
||||||
Decimal.gte(
|
Decimal.gte(
|
||||||
(buyable as GenericBuyable).amount.value,
|
(repeatable as GenericRepeatable).amount.value,
|
||||||
unref((buyable as GenericBuyable).purchaseLimit)
|
unref((repeatable as GenericRepeatable).purchaseLimit)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
processComputable(buyable as T, "classes");
|
processComputable(repeatable as T, "classes");
|
||||||
const classes = buyable.classes as ProcessedComputable<Record<string, boolean>> | undefined;
|
const classes = repeatable.classes as
|
||||||
buyable.classes = computed(() => {
|
| ProcessedComputable<Record<string, boolean>>
|
||||||
|
| undefined;
|
||||||
|
repeatable.classes = computed(() => {
|
||||||
const currClasses = unref(classes) || {};
|
const currClasses = unref(classes) || {};
|
||||||
if ((buyable as GenericBuyable).maxed.value) {
|
if ((repeatable as GenericRepeatable).maxed.value) {
|
||||||
currClasses.bought = true;
|
currClasses.bought = true;
|
||||||
}
|
}
|
||||||
return currClasses;
|
return currClasses;
|
||||||
});
|
});
|
||||||
buyable.canClick = computed(() => requirementsMet(buyable.requirements));
|
repeatable.canClick = computed(() => requirementsMet(repeatable.requirements));
|
||||||
buyable.onClick = buyable.purchase =
|
repeatable.onClick = repeatable.purchase =
|
||||||
buyable.onClick ??
|
repeatable.onClick ??
|
||||||
buyable.purchase ??
|
repeatable.purchase ??
|
||||||
function (this: GenericBuyable) {
|
function (this: GenericRepeatable) {
|
||||||
const genericBuyable = buyable as GenericBuyable;
|
const genericRepeatable = repeatable as GenericRepeatable;
|
||||||
if (!unref(genericBuyable.canClick)) {
|
if (!unref(genericRepeatable.canClick)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
payRequirements(
|
payRequirements(
|
||||||
buyable.requirements,
|
repeatable.requirements,
|
||||||
unref(genericBuyable.buyMax)
|
unref(genericRepeatable.buyMax)
|
||||||
? maxRequirementsMet(genericBuyable.requirements)
|
? maxRequirementsMet(genericRepeatable.requirements)
|
||||||
: 1
|
: 1
|
||||||
);
|
);
|
||||||
genericBuyable.amount.value = Decimal.add(genericBuyable.amount.value, 1);
|
genericRepeatable.amount.value = Decimal.add(genericRepeatable.amount.value, 1);
|
||||||
genericBuyable.onPurchase?.();
|
genericRepeatable.onPurchase?.();
|
||||||
};
|
};
|
||||||
processComputable(buyable as T, "display");
|
processComputable(repeatable as T, "display");
|
||||||
const display = buyable.display;
|
const display = repeatable.display;
|
||||||
buyable.display = jsx(() => {
|
repeatable.display = jsx(() => {
|
||||||
// TODO once processComputable types correctly, remove this "as X"
|
// TODO once processComputable types correctly, remove this "as X"
|
||||||
const currDisplay = unref(display) as BuyableDisplay;
|
const currDisplay = unref(display) as RepeatableDisplay;
|
||||||
if (isCoercableComponent(currDisplay)) {
|
if (isCoercableComponent(currDisplay)) {
|
||||||
const CurrDisplay = coerceComponent(currDisplay);
|
const CurrDisplay = coerceComponent(currDisplay);
|
||||||
return <CurrDisplay />;
|
return <CurrDisplay />;
|
||||||
}
|
}
|
||||||
if (currDisplay != null) {
|
if (currDisplay != null) {
|
||||||
const genericBuyable = buyable as GenericBuyable;
|
const genericRepeatable = repeatable as GenericRepeatable;
|
||||||
const Title = coerceComponent(currDisplay.title ?? "", "h3");
|
const Title = coerceComponent(currDisplay.title ?? "", "h3");
|
||||||
const Description = coerceComponent(currDisplay.description ?? "");
|
const Description = coerceComponent(currDisplay.description ?? "");
|
||||||
const EffectDisplay = coerceComponent(currDisplay.effectDisplay ?? "");
|
const EffectDisplay = coerceComponent(currDisplay.effectDisplay ?? "");
|
||||||
|
@ -176,12 +182,12 @@ export function createBuyable<T extends BuyableOptions>(
|
||||||
{currDisplay.showAmount === false ? null : (
|
{currDisplay.showAmount === false ? null : (
|
||||||
<div>
|
<div>
|
||||||
<br />
|
<br />
|
||||||
{unref(genericBuyable.purchaseLimit) === Decimal.dInf ? (
|
{unref(genericRepeatable.purchaseLimit) === Decimal.dInf ? (
|
||||||
<>Amount: {formatWhole(genericBuyable.amount.value)}</>
|
<>Amount: {formatWhole(genericRepeatable.amount.value)}</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
Amount: {formatWhole(genericBuyable.amount.value)} /{" "}
|
Amount: {formatWhole(genericRepeatable.amount.value)} /{" "}
|
||||||
{formatWhole(unref(genericBuyable.purchaseLimit))}
|
{formatWhole(unref(genericRepeatable.purchaseLimit))}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -192,13 +198,13 @@ export function createBuyable<T extends BuyableOptions>(
|
||||||
Currently: <EffectDisplay />
|
Currently: <EffectDisplay />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{genericBuyable.maxed.value ? null : (
|
{genericRepeatable.maxed.value ? null : (
|
||||||
<div>
|
<div>
|
||||||
<br />
|
<br />
|
||||||
{displayRequirements(
|
{displayRequirements(
|
||||||
genericBuyable.requirements,
|
genericRepeatable.requirements,
|
||||||
unref(genericBuyable.buyMax)
|
unref(genericRepeatable.buyMax)
|
||||||
? maxRequirementsMet(genericBuyable.requirements)
|
? maxRequirementsMet(genericRepeatable.requirements)
|
||||||
: 1
|
: 1
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -209,16 +215,16 @@ export function createBuyable<T extends BuyableOptions>(
|
||||||
return "";
|
return "";
|
||||||
});
|
});
|
||||||
|
|
||||||
processComputable(buyable as T, "visibility");
|
processComputable(repeatable as T, "visibility");
|
||||||
setDefault(buyable, "visibility", Visibility.Visible);
|
setDefault(repeatable, "visibility", Visibility.Visible);
|
||||||
processComputable(buyable as T, "purchaseLimit");
|
processComputable(repeatable as T, "purchaseLimit");
|
||||||
setDefault(buyable, "purchaseLimit", Decimal.dInf);
|
setDefault(repeatable, "purchaseLimit", Decimal.dInf);
|
||||||
processComputable(buyable as T, "style");
|
processComputable(repeatable as T, "style");
|
||||||
processComputable(buyable as T, "mark");
|
processComputable(repeatable as T, "mark");
|
||||||
processComputable(buyable as T, "small");
|
processComputable(repeatable as T, "small");
|
||||||
processComputable(buyable as T, "buyMax");
|
processComputable(repeatable as T, "buyMax");
|
||||||
|
|
||||||
buyable[GatherProps] = function (this: GenericBuyable) {
|
repeatable[GatherProps] = function (this: GenericRepeatable) {
|
||||||
const { display, visibility, style, classes, onClick, canClick, small, mark, id } =
|
const { display, visibility, style, classes, onClick, canClick, small, mark, id } =
|
||||||
this;
|
this;
|
||||||
return {
|
return {
|
||||||
|
@ -234,6 +240,6 @@ export function createBuyable<T extends BuyableOptions>(
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
return buyable as unknown as Buyable<T>;
|
return repeatable as unknown as Repeatable<T>;
|
||||||
});
|
});
|
||||||
}
|
}
|
Loading…
Reference in a new issue