-
Notifications
You must be signed in to change notification settings - Fork 10
Custom Daily
You can create custom dailies for your world the same way the built-in dailies are made, it works similar to a foundry macro, the code you enter in the text field of the Register Custom Dailies
menu represents the inside of an asynchronous function that must return a Daily
object.
Some comments on the daily object
return {
/**
* REQUIRED
* The unique key for your custom daily, those are isolated from the
* built-in daily keys.
*/
key: "my-custom-daily",
/**
* CONDITIONALLY REQUIRED
* This will completely remove the daily from the actor if it returns false.
* NOTE: required if no 'items' are provided.
*/
condition: (actor) => true,
/**
* CONDITIONALLY REQUIRED
* An array of slug + uuid to identify which embedded items need to be
* retrieved from the character, the 'required' flag makes an item mandatory
* for the functionment of the daily.
* An 'items' object parameter is forwarded in all the functions of the daily.
* NOTE: required if no 'condition' is provided.
*/
items: [
{
slug: "item",
uuid: "Compendium.xxx.Item.xxx",
required: true,
},
],
/**
* OPTIONAL
* Can be a string or a function that returns a string.
* NOTE: because the item was 'required', we are sure that it exists on the
* character and can be accessed without doing extra check.
*/
label: (actor, items) => items.item.name,
/**
* OPTIONAL
* Called in the first stage of the daily and returns an object of arbitrary
* data that will be forwarded to the 'rows' and 'process' functions
* as 'custom' argument.
* This is useful if want to avoid recomputing the same data twice.
*/
prepare: (actor, items) => {
return {
uselessVariable: "plop",
};
},
/**
* REQUIRED
* This is where you define the different rows that appears in the interface.
* It returns an array of 'DailyRow' of the different available types.
* A 'rows' object parameter is forwarded to the 'process' function, its
* content depends on the row type.
* NOTE: 'select' and 'random' rows with an empty 'options' array will be
* removed.
* NOTE: if only one row is provided, it will appear at the top of the daily
* interface with the other single row dailies and its label will be the
* daily label instead of the row label.
*/
rows: (actor, items, custom) => {
const options = [
{ value: "no", label: "" },
{ value: "yes", label: items.item.name },
];
return [
{
type: "select",
slug: "selection",
label: custom.uselessVariable,
options: options,
},
];
},
/**
* REQUIRED
* This is the part that actually modify the character, helper functions are
* provided to both avoid making dozens of updates on the character and
* to let the module handle redundant and important mechanics of the daily,
* these paired with the 'utils' functions should cover most of what a
* custom daily needs.
*/
process: ({ actor, rows, messages, addItem }) => {},
/**
* OPTIONAL
* Called during 'Rest for the Night' to cleanup things that the module
* can't handle itself.
* This function should rarely be needed if you use the provided
* helpers in the 'process', since the module will automatically revert
* anything it did when using those.
* NOTE: to give some perspective, the only built-in daily that needs to use
* this is the 'familiar' one because it needs to remove the abilities on
* the familiar actor.
*/
rest: ({ actor, removeItem }) => {},
/**
* OPTIONAL
* Use to register daily specifig configs.
* Those will appear in the `Config` menu of the daily preparation interface.
* Returns an array of input related configs
*/
config: (actor) => {
return [
{
type: "checkbox",
/**
* input element name attribute
*/
name: "my-config",
/**
* OPTIONAL
*/
value: true,
label: "My Module Config",
},
];
},
/**
* OPTIONAL
* Called during the daily preparation process right after all the items
* from all the dailies were added to the character and before the items update/delete happen.
* You can use the same helpers than in the `process` function except the ones that add items
* or rules to the character.
*/
afterItemAdded: ({ addedItems, setExtraFlags }) => {
const myFlag = addedItems.filter((item) => item.id);
setExtraFlags({ myFlag });
},
};
Note
All the functions in the daily can be asynchronous.
In the context of the custom daily function are exposed the following
This object contains tons of function helpers used to create the built-in dailies (and more) making the most common tasks taken inside a daily easier, you can find the source for all the utility functions here.
This function creates a daily object to allow the character to temporarily improve the proficiency of a skill (or create a lore skill), this is used to create the Ageless Spirit
,
Ancient Memories
and Flexible Studies
dailies, you can find its source here
This function creates a daily object to allow the character to temporarily gain a lore skill, this is used to create the Quick Study
daily, you can find its source here
This function creates a daily object to allow the character to gain a temporary language, this is used to create the Ancestral Linguistics
and
Bort's Blessing
dailies, you can find its source here
This function creates a daily object to allow the character to gain a temporary resistance, this is used to create the Elementalist Dedication
and Ganzi Heritage
dailies, you can find its source here
This function creates a daily object to allow the character to create temporary spell scrolls based on a series of 3 feats and its level, this is used to create the Scroll Esoterica
and Basic Scroll Cache
dailies, you can find its source here
Modules can register their own custom dailies without having to add them to the world setting, dailies need to be registered after the init
hook, to do so you need to use
game.modules.get("pf2e-dailies")?.api.registerCustomDailies(dailies: Daily[])
Because custom dailies are normally just strings representing the inside of an asynchronous function, they can have parameters injected in their context, the most useful being utils
which is used in almost all stages of a daily; The dailies registered with registerCustomDailies
being actual daily objects, they cannot enjoy that same convenience and need to look for it in the API
game.modules.get("pf2e-dailies")?.api.utils;