diff --git a/src/features/challenges/challenge.tsx b/src/features/challenges/challenge.tsx index 6f760ee..16e97d1 100644 --- a/src/features/challenges/challenge.tsx +++ b/src/features/challenges/challenge.tsx @@ -25,7 +25,7 @@ import { ProcessedComputable } from "util/computed"; import { createLazyProxy } from "util/proxies"; -import { computed, Ref, unref } from "vue"; +import { computed, Ref, unref, watch, WatchStopHandle } from "vue"; export const ChallengeType = Symbol("ChallengeType"); @@ -62,6 +62,7 @@ export interface BaseChallenge { maxed: Ref; active: PersistentRef; toggle: VoidFunction; + complete: (remainInChallenge?: boolean) => void; type: typeof ChallengeType; [Component]: typeof ChallengeComponent; [GatherProps]: () => Record; @@ -87,7 +88,7 @@ export type GenericChallenge = Replace< { visibility: ProcessedComputable; canStart: ProcessedComputable; - canComplete: ProcessedComputable; + canComplete: ProcessedComputable; completionLimit: ProcessedComputable; mark: ProcessedComputable; } @@ -134,11 +135,7 @@ export function createChallenge( challenge.toggle = function () { const genericChallenge = challenge as GenericChallenge; if (genericChallenge.active.value) { - if ( - genericChallenge.canComplete && - unref(genericChallenge.canComplete) && - !genericChallenge.maxed.value - ) { + if (unref(genericChallenge.canComplete) && !genericChallenge.maxed.value) { let completions: boolean | DecimalSource = unref(genericChallenge.canComplete); if (typeof completions === "boolean") { completions = 1; @@ -158,6 +155,30 @@ export function createChallenge( genericChallenge.onEnter?.(); } }; + challenge.complete = function (remainInChallenge?: boolean) { + const genericChallenge = challenge as GenericChallenge; + let completions: boolean | DecimalSource = unref(genericChallenge.canComplete); + if ( + genericChallenge.active.value && + completions !== false && + (completions === true || Decimal.neq(0, completions)) && + !genericChallenge.maxed.value + ) { + if (typeof completions === "boolean") { + completions = 1; + } + genericChallenge.completions.value = Decimal.min( + Decimal.add(genericChallenge.completions.value, completions), + unref(genericChallenge.completionLimit) + ); + genericChallenge.onComplete?.(); + if (remainInChallenge !== true) { + genericChallenge.active.value = false; + genericChallenge.onExit?.(); + genericChallenge.reset?.reset(); + } + } + }; processComputable(challenge as T, "visibility"); setDefault(challenge, "visibility", Visibility.Visible); const visibility = challenge.visibility as ProcessedComputable;