Recently, I’ve been running my long standing D&D 5e game using Foundry VTT and trying to expand/improve my combat encounters through automation. I have a fight coming up where the boss has a very specific regeneration ability that heals him 10% of his total health at the start of each of his turns until he takes fire damage. Looking around at the various modules I already had installed I figured this was possible, I just wasn’t sure of the specifics. After some research I’ve settled on three modules that are essential to getthing this effect to work:

The first step was obviously to create a new item in Foundry with the “Feature” type since this property was going to be inherent to the creature. After picking out an item and adding some description text I headed straight for the “Effects” tab. Since this is a passive buff I went down to “Passive Effects” and clicked “Add” to create my super awesome new effect. Unfortunately, this is where the problems started.

Under “Duration” I selected the “Start of each turn” option for “Macro Repeat” and added a special duration of expiring when the character takes fire damage. Seems simple, right? The issue came at the “Effects” tab and figuring out what combination of attribute, mode, and value were needed to get things to actually work. Originally I tried an “ADD” to the property attributes.hp.value and while I was able to get the 10% health increase by writing some JS in the value field, I wasn’t able to get the effect to repeat. When testing the creature would get a flat 10% heal when the feature was added and lose it when it was removed, not get healed each turn.

After a lot of poking around, I struck upon the solution…the “Macro” portion of the “Macro Repeat” option was more specific than I originally had assumed. I had taken it to mean the entire effect was the “macro” while it meant specifically a defined Foundry macro it was trying to run! This changed my effect to be using the attribute macro.execute, a mode of Custom, and a value of baerdan.effects.regenerate. The macro JS is shown below and can be named anything, I just picked a namespace-esq title to make it easier to sort/organize my macros.

/******************************************************************************
 * baerdan.effects.regenerate
 *
 * This macro does a percentage based heal on any actor it is run against, up
 * to their max defined health. As far as I know it only works for actors with
 * linked tokens. This means things like big bosses or other singleton critters,
 * not any old mook in the fight.
 *
 * I mostly use this through Dynamic Active Effects (DAE) which automatically
 * passes a range selector (eg. "each"), then any user defined parameters
 * (eg. heal percentage), and finally an object containing info on the calling
 * token. In context, this is the reason for the somewhat "magic" array offsets
 * used later to grab values.
 *
 * You can adjust the heal rate by providing an integer percentage that you want
 * the creature to heal per execution of the macro as the first parameter to the
 * macro in the DAE effect. If the parameter is omitted the default is 10% of
 * max HP per execution.
 *****************************************************************************/

let heal_percent = (typeof args[1] === "number") ? (args[1]/100) : 0.1;
if (actor != null) {
  const actor_data = actor.data.data;
  let heal = Math.floor(actor.data.attributes.hp.max * heal_percent);
  let hp = Math.min(actor_data.attributes.hp.value + heal, actor_data.attributes.hp.max);
  await actor.update({"data.attributes.hp.value": hp});
}

In writing the JS I learned two additional bits of information. First, you must include the actor != null check to avoid nasty error messages when you attach this item to a character sheet that doesn’t currently have a token on the battlefield. Second, you can update properties on the actor object until you’re blue in the face but they won’t actually be persistent until you set them with a call to await actor.update(). The await portion is to make the call asyncronous, I guess to avoid blocking the UI while it runs. So there you have it, a scary monster ability which will keep it healing as your party tries to beat it down.