Register

Effective Tray NG

An Add-on Module for Foundry Virtual Tabletop

Author: alterNERDtive Project Source Foundry Versions 13 to 13.999 (Verified 13.351) Last Updated 1 week, 2 days ago

Effective Tray NG (for D&D Fifth Edition)

Please don’t upload to GitHub

latest release Foundry v13 D&D 5e 5.2 Discord

A module for D&D5e on Foundry VTT that allows players to make full use of the effects and damage trays, instead of restricting them to DM only.

Based on Effective Tray by @etiquettestartshere.

Effects Tray

Allows users to use the effect tray as much or as little as wanted by the GM, up to and including transferal to targets they do not own. User ability to transfer effects to and from any target is on by default.

Damage Tray

Allows users to use the damage tray for selected tokens that they own, and for targeted tokens (either that they own, or ones they don’t own with a setting). User ability to use the damage tray is on by default, but unless the relevant setting is selected, they cannot damage targets.

Settings

Additional Features


Technical Details

Scope: This module modifies the system’s damage and effect application trays in chat messages using libWrapper to allows all users, not just GMs or the originating user, to apply effects and damage. Since regular users cannot directly affect unowned tokens, the module communicates changes via socket to an active GM client.

License: GPLv3. Original code base by etiquettestartshere: MIT.

Additional Info: Some code has been adapted from dnd5e, particularly the extension of the tray custom html elements, and unifying module and system logic for collapsing or expanding trays.

ko-fi

API

Now includes three helper functions exposed in the global scope under effectiv, effectiv.applyEffect, effectiv.applyDamage and effective.partitionTargets. These functions have not been heavily tested and are included now in the hopes that, if someone wants to use them, they will also test them for issues.

applyEffect, a helper function to allow users to apply effects. It allows users to apply effects via macro (or other module), and can take a variety of types of data when doing so, allowing effect data to be passed as the full ActiveEffect document, an effect Uuid, or an object (note that passing it as an object will not interact with refreshing duration or deleting effects of same origin, as determined by module setting, because creating an effect from an object will have its own unique origin). Similarly, this function allows target data to be passed as an array of Uuids, a single Uuid, an array of Tokens, or a Set, as game.user.targets.

This helper also allows the use of the other things the effects tray does, primarily flagging effects with spellLevel, or any other arbitrary flags (via effectData), and making an effect dependent on a concentration effect (so it will be deleted when the concentration effect is). If concentration is used, because it passed as an ID, you must also pass the Uuid or Actor document of the actor the concentration effect is on.

/**
 * Helper function to allow for macros or other applications to apply effects to owned and unowned targets.
 * @param {string|object|ActiveEffect5e} effect            The effect to apply.
 * @param {Set<Token5e>|Token5e[]|string[]|string} targets Targeted tokens.
 * @param {object} [options]
 * @param {object} [options.effectData]                    A generic data object, which typically handles the level the originating spell was cast at, 
 *                                                         if it originated from a spell, if any. Use flags like { "flags.dnd5e.spellLevel": 1 }.
 * @param {string} [options.concentration]                 The ID (not Uuid) of the concentration effect this effect is dependent on, if any.
 * @param {string|Actor5e} [options.caster]                The Uuid or Actor5e document of the actor that cast the spell that requires concentration, if any.
 */
async function applyEffect(
  effect, 
  targets, 
  { effectData: null, concentration: null, caster: null } = {}
)
/* in use...*/
effectiv.applyEffect(
  effect, 
  targets, 
  { effectData: null, concentration: null, caster: null } = {}
)

applyDamage, helper function to allow users to apply damage. This function has been tested not at all and is included as a courtesy. Personally I find the way damage information must be structured to respect resistances, etc is too much of a mess to test this even a single time, but if someone really wants to do this over a socket but didn’t write their own socket handler for it…here you go. Full, extensive documentation of the array that must be created is in scripts/api.mjs, copied directly from dnd5e, with the exception that socket transmission requires the sets to be arrays. Unlike applyEffect, this applies no damage via the requesting client, and so is basically only meant for damaging unowned targets. Users wishing to apply damage to owned targets should simply use the system’s Actor#applyDamage.

/**
 * The below documentation is from the system's damage application method, except all Sets are arrays.
 * Please see the system's documentation for a complete understanding of this method, as this helper is only
 * provided as a courtesy.
 * 
 * Description of a source of damage. 
 *
 * @typedef {object} DamageDescription
 * @property {number} value              Amount of damage.
 * @property {string} type               Type of damage.
 * @property {Array<string>} properties  Physical properties that affect damage application.
 * @property {object} [active]
 * @property {number} [active.multiplier]      Final calculated multiplier.
 * @property {boolean} [active.modifications]  Did modification affect this description?
 * @property {boolean} [active.resistance]     Did resistance affect this description?
 * @property {boolean} [active.vulnerability]  Did vulnerability affect this description?
 * @property {boolean} [active.immunity]       Did immunity affect this description?
 */

/**
 * Options for damage application.
 *
 * @typedef {object} DamageApplicationOptions
 * @property {boolean|Array<string>} [downgrade]  Should this actor's resistances and immunities be downgraded by one
 *                                                step? A Array of damage types to be downgraded or `true` to downgrade
 *                                                all damage types.
 * @property {number} [multiplier=1]         Amount by which to multiply all damage.
 * @property {object|boolean} [ignore]       Array to `true` to ignore all damage modifiers. If Array to an object, then
 *                                           values can either be `true` to indicate that the all modifications of
 *                                           that type should be ignored, or a Array of specific damage types for which
 *                                           it should be ignored.
 * @property {boolean|Array<string>} [ignore.immunity]       Should this actor's damage immunity be ignored?
 * @property {boolean|Array<string>} [ignore.resistance]     Should this actor's damage resistance be ignored?
 * @property {boolean|Array<string>} [ignore.vulnerability]  Should this actor's damage vulnerability be ignored?
 * @property {boolean|Array<string>} [ignore.modification]   Should this actor's damage modification be ignored?
 * @property {boolean} [invertHealing=true]  Automatically invert healing types to it heals, rather than damages.
 * @property {"damage"|"healing"} [only]     Apply only damage or healing parts. Untyped rolls will always be applied.
 */

/**
 * Apply a certain amount of damage or healing to the health pool for Actor
 * @param {DamageDescription[]|number} damages     Damages to apply.
 * @param {DamageApplicationOptions} [options={}]  Damage application options.
 * @returns {Promise<Actor5e>}                     A Promise which resolves once the damage has been applied.
 */

/**
 * Helper function to allow for macros or other applications to apply damage via socket request.
 * @param {Array} damage Array of damage objects; see above.
 * @param {Array} opts   Object of options (which may inlude arrays); see above.
 * @param {string} id    Uuid of the target.
 */
async function applyDamage(damage = [], opts = {}, id)
/* in use...*/
effectiv.applyDamage(damage = [], opts = {}, id)

partitionTargets, a function similar to foundry’s Array#partition but specifically designed to handle game.user.targets, a set, or an array of tokens. It sorts them into two arrays, the first array containing tokens that the user owns, and the second array containing those token’s document.uuids. This can be useful for determining what information needs to be sent over sockets. I have no idea why anyone would use this function, but here it is.

/**
 * Sort tokens into owned and unowned categories.
 * @param {Set|Token[]} targets The set or array of tokens to be sorted.
 * @returns {Array}           An Array of length two, the elements of which are the partitioned pieces of the original.
 */
function partitionTargets(targets)
/* in use...*/
effectiv.partitionTargets(targets)

Hooks

Now includes two hooks, effectiv.preApplyEffect and effectiv.applyEffect. The former allows the data of the first parameter to be modified and explicitly returning false will prevent the effect from being applied. The later passes the same information in its final state upon application.

These hooks have not been extensively tested.

/**
 * Hook called before the effect is completed and applied.  
 * @param {object} effectData            The effect data object before application. This object can be mutated.
 * @param {Actor5e} actor                The actor to create the effect on.
 * @param {ActiveEffect5e} concentration The concentration effect on which the effect will be dependent, if it requires concentration.
 */
Hooks.call("effectiv.preApplyEffect", effectData, actor, concentration);
/**
 * Hook called before the effect is completed and applied. Same as above except for effectData.
 * @param {object} effectData            The effect data object.
 * @param {Actor5e} actor                The actor to create the effect on.
 * @param {ActiveEffect5e} concentration The concentration effect on which the effect will be dependent, if it requires concentration.
 */
Hooks.callAll("effectiv.applyEffect", effectData, actor, concentration);

Supported Game Systems

  1. Dungeons & Dragons Fifth Edition

    Latest Version: Version 5.2.5 Last Updated 4 days, 18 hours ago

Categories

Available Versions

  1. Version 13.351.5.2.4.2

    1 week, 2 days ago
    Foundry Version 13 - 13.999 (Verified 13.351) Manifest URL Read Notes
  2. Version 13.350-5.1.10-1

    2 months, 3 weeks ago
    Foundry Version 13 - 13.999 (Verified 13.350) Manifest URL Read Notes
  3. Version 13.348-5.1.5-1

    4 months, 2 weeks ago
    Foundry Version 13 - 13.999 (Verified 13.348) Manifest URL Read Notes
  4. Version 5.1.3

    4 months, 2 weeks ago
    Foundry Version 13.348 - 13.999 (Verified 13.348) Manifest URL Read Notes
  5. Version 5.1.2

    4 months, 3 weeks ago
    Foundry Version 13.348 - 13.999 (Verified 13.348) Manifest URL Read Notes
  6. Version 5.1.1

    4 months, 3 weeks ago
    Foundry Version 13.348 - 13.999 (Verified 13.348) Manifest URL Read Notes