Skip to content

Commit

Permalink
Add support for disabling special resource renewal
Browse files Browse the repository at this point in the history
  • Loading branch information
CarlosFdez committed Feb 2, 2025
1 parent d4de304 commit da54434
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 9 deletions.
16 changes: 8 additions & 8 deletions src/module/actor/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -577,15 +577,15 @@ class ActorPF2e<TParent extends TokenDocumentPF2e | null = TokenDocumentPF2e | n
commitData.itemUpdates.push(...spellcastingRecharge.itemUpdates);
commitData.affected.spellSlots = spellcastingRecharge.itemUpdates.length > 0;
}
}

// Restore special resources
for (const resource of Object.values(this.synthetics.resources)) {
const updates = await resource.update(resource.max, { save: false, checkLevel: true });
commitData.itemCreates.push(...updates.itemCreates);
commitData.itemUpdates.push(...updates.itemUpdates);
if (updates.itemCreates.length || updates.itemUpdates.length) {
commitData.affected.resources.push(resource.slug);
}
// Restore special resources based on elapsed time
for (const resource of Object.values(this.synthetics.resources)) {
const updates = await resource.renewUses(elapsed);
commitData.itemCreates.push(...updates.itemCreates);
commitData.itemUpdates.push(...updates.itemUpdates);
if (updates.itemCreates.length || updates.itemUpdates.length) {
commitData.affected.resources.push(resource.slug);
}
}

Expand Down
18 changes: 18 additions & 0 deletions src/module/rules/rule-element/special-resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { applyActorUpdate } from "@actor/helpers.ts";
import type { ActorCommitData } from "@actor/types.ts";
import { ItemProxyPF2e, PhysicalItemPF2e } from "@item";
import type { PhysicalItemSource } from "@item/base/data/index.ts";
import { StrictChoicesField } from "@system/schema-data-fields.ts";
import { sluggify } from "@util";
import { createBatchRuleElementUpdate } from "../helpers.ts";
import { RuleElementPF2e, type RuleElementOptions } from "./base.ts";
Expand Down Expand Up @@ -44,6 +45,12 @@ class SpecialResourceRuleElement extends RuleElementPF2e<SpecialResourceSchema>
label: "PF2E.UUID.Label",
}),
level: new ResolvableValueField({ required: false, nullable: true, initial: null }),
renew: new StrictChoicesField({
required: false,
nullable: false,
choices: ["daily", false],
initial: "daily",
}),
};
}

Expand Down Expand Up @@ -96,6 +103,14 @@ class SpecialResourceRuleElement extends RuleElementPF2e<SpecialResourceSchema>
}
}

/** Returns data that when applied updates this resources uses based on renewal rules */
async renewUses(duration: "turn" | "round" | "day"): Promise<ActorCommitData> {
if (duration === "day" && this.renew !== false) {
return this.update(this.max, { save: false, checkLevel: true });
}
return { actorUpdates: null, itemCreates: [], itemUpdates: [] };
}

/** If an item uuid is specified, create it when this resource is first attached */
override async preCreate({ tempItems, pendingItems }: RuleElementPF2e.PreCreateParams): Promise<void> {
if (!this.test()) return;
Expand Down Expand Up @@ -209,6 +224,7 @@ type SpecialResourceSource = RuleElementSource & {
max?: unknown;
itemUUID?: unknown;
level?: unknown;
renew?: unknown;
};

type SpecialResourceSchema = RuleElementSchema & {
Expand All @@ -220,6 +236,8 @@ type SpecialResourceSchema = RuleElementSchema & {
itemUUID: fields.DocumentUUIDField<ItemUUID, false, false, false>;
/** If itemUUID exists, determines the level of the granted item */
level: ResolvableValueField<false, true, true>;
/** Determines if the resource is rewnewable. Defaults to "daily" */
renew: StrictChoicesField<false | "daily", false, false>;
};

interface SpecialResourceUpdateOptions {
Expand Down
26 changes: 25 additions & 1 deletion src/module/system/schema-data-fields.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Predicate, PredicateStatement, RawPredicate, StatementValidator } from "@system/predication.ts";
import { SlugCamel, sluggify } from "@util";
import { SlugCamel, objectHasKey, sluggify } from "@util";
import * as R from "remeda";
import type DataModel from "types/foundry/common/abstract/data.d.ts";
import type {
Expand Down Expand Up @@ -164,6 +164,29 @@ class StrictObjectField<
}
}

/** A field that allows nothing except for the provided choices */
class StrictChoicesField<
TChoices extends JSONValue,
TRequired extends boolean = true,
TNullable extends boolean = false,
THasInitial extends boolean = true,
> extends fields.DataField<TChoices, TChoices, TRequired, TNullable, THasInitial> {
protected override _cast(value: unknown): unknown {
return value;
}

protected override _validateType(value: unknown): void {
if (this.options.nullable && value === null) return;

const choices =
this.options.choices instanceof Function ? this.options.choices() : (this.options.choices ?? []);
const isValid = Array.isArray(choices) ? choices.includes(value) : objectHasKey(choices, value);
if (!isValid) {
throw new Error(`${value} is not a valid choice`);
}
}
}

class DataUnionField<
TField extends DataField,
TRequired extends boolean = boolean,
Expand Down Expand Up @@ -515,6 +538,7 @@ export {
SlugField,
StrictArrayField,
StrictBooleanField,
StrictChoicesField,
StrictNumberField,
StrictObjectField,
StrictSchemaField,
Expand Down

0 comments on commit da54434

Please sign in to comment.