Register

GM Tools: Encounter Forge

An Add-on Module for Foundry Virtual Tabletop

Author: Elemor Project: Source Foundry Versions 12 to 14 (Verified 14) Last Updated 17 hours, 42 minutes ago

GM Tools: Encounter Forge

 

Encounter Forge is a Foundry VTT (v12-v14) module for D&D 5e that builds brand-new, balanced NPCs on demand, sized to your party, not a generic XP table or basic CR.

Instead of pulling a stat block from a compendium and hoping the CR math works out, Encounter Forge assembles a creature from a chassis, traits, actions, and (optionally) spells, then tunes its HP, AC, and damage toward the difficulty you asked for. The estimate is built from party HP and damage per round, so it can't account for tactics, terrain, control effects, or what your party has left in the tank. Read the creature before you run it.

Status: Actively developed. Foundry v12-v14, dnd5e system 4.0+ (verified on 5.3.3 and 6.0.5).


Why Encounter Forge is different

image

Most CR generators (and most homebrew stat blocks) work backwards from the Dungeon Master's Guide CR/XP tables: pick a CR, look up its "expected" HP and damage, and build (or pull) a creature around those numbers. The problem is that those tables assume a "standard" party, and most parties aren't standard. A CR 5 monster can be a joke or a TPK depending on who's sitting at the table.

Encounter Forge flips that process around:

  1. It estimates your party's actual damage output and durability, either generically from player count/level, or (with Calibrate to Party) from the real PCs' HP, AC, saves, and levels.
  2. It uses your chosen difficulty (Easy/Medium/Hard/Deadly) to compute an encounter envelope, the total HP and DPR (Damage Per Round) the enemy side needs, as a whole, to make that fight play out the way that difficulty implies.
  3. It splits that envelope across however many enemies you asked for (or amplifies it for a Solo Boss).
  4. Then it picks a CR, but only to decide what kind of creature this is (its chassis, traits, actions, spell tier, AC baseline). The CR does not set the creature's final HP or damage.
  5. Finally, it tunes the assembled creature's HP, AC, and damage output to hit its slice of the envelope exactly, so the finished NPC actually performs the way the difficulty setting promised (give or take).

In short: a "Hard" fight with two generated enemies and a "Hard" fight with four generated enemies should both feel like a Hard fight for your specific table, just split up differently. That's not something CR-table-driven generators do well enough, because they're matching a number on a chart, not your party, and not by output.


Not an AI generator - and works fully offline

Encounter Forge contains/requires no AI and no language model. Every creature is assembled procedurally from local JSON content pools (chassis archetypes, traits, actions, spells, names) using deterministic math you can read in plain JavaScript. There's nothing to configure, no API key, no tokens, and nothing about your world or your party is ever sent anywhere. Generating a creature needs no internet connection at all (other than being online to play obviously). The only network request is the update check, which asks GitHub if there's a newer release. It sends nothing else, and there's no setting to turn it off yet. The difficulty targets are deterministic from the same inputs, and the creature built to hit them varies (actions, traits, etc are randomizes via the pool of said items, so that differs or fights would be boring).


Features

image


The Math

This section is a summary, see the Wiki for the full breakdown with worked examples.

1. Party estimate

A party estimate is { dpr, hp }:

2. The encounter envelope

Each difficulty maps to a target "rounds to defeat the enemy" and "rounds the enemy needs to threaten the party":

Difficulty Rounds to Defeat Rounds to Threaten Outlook
Easy 2 6 Easy
Medium 3 5.4 Manageable
Hard 4 4.4 Risky
Deadly 5 3.5 Dangerous
groupHP  = party.dpr * roundsToDefeat
groupDPR = (party.hp / roundsToThreaten) * economyFactor
 

economyFactor is a small multiplier (1 + 0.04 * (enemyCount - 1), capped at 1.2) that accounts for more attackers contributing slightly more total damage per round. Both totals are then divided by the enemy count to get each creature's HP/DPR target. Solo Boss further multiplies its single creature's targets by HP x1.5 / DPR x1.3.

3. Picking a flavor CR

The per-creature HP/DPR target is matched against a CR baseline table to find the closest CR. That CR drives only the chassis stat tier, trait/action/spell availability, and AC/save-DC baseline, it is not the creature's final HP or DPR.

4. Calibration pass

Every generated creature is then tuned to hit its envelope target exactly:

The result: the pre-generation readout and the post-generation results should track closely, regardless of party size, level, enemy count, or Solo Boss status.

5. Precision Damage Scaling (optional)

A world setting (dprFirstDamage, Boolean, default off) changes how action dice counts are assigned during creature assembly. In the default tier-based path, each action uses a fixed dice formula per tier (example, a multi-hit melee action always uses its tier 3 formula at CR 5-7, regardless of the creature's actual DPR target). When enabled, dice counts are instead derived from the per-creature DPR target values: the engine extracts the die size from the action's damage_fallback and computes how many dice of that size are needed to hit the target DPR. Calibration (step 4) still runs afterward and closes any gap. The effect is a closer ceiling on high-variance attacks. An action at tier 3 uses the number of dice appropriate for that creature's budget, not a tier-baked maximum. Intended for playtesting balance comparisons so I can get input on the better approach; leave off for the standard v 1.0 path if you prefer.

6. Combat Intensity Calibration (optional)

image

image

A world setting (combatIntensity, integer -3 to +3, default 0) scales the roundsToThreaten target before the envelope is computed:

adjustedRoundsToThreaten = roundsToThreaten / (1 + offset * 0.12)
 

Positive offset = shorter drain time = enemies built to hit harder. Negative = longer drain = softer enemies. roundsToDefeat is never changed. Set from Module Settings -> Combat Intensity Calibration; changes take effect immediately for the next generation.


Installation

  1. In Foundry's Add-on Modules tab, click Install Module.

  2. Paste the manifest URL:

    https://github.com/ElemorSeru/encounter-forge/releases/latest/download/module.json
    
     
  3. Enable GM Tools: Encounter Forge in your world's module list.

Or find it on the Foundry package list: GM Tools: Encounter Forge


Quick Start

image

  1. Open your Actors sidebar tab, you'll see a new Generate button (wizard hat icon) in the header.
  2. Set your party size/level (or enable Calibrate to Party and pick actors), pick a difficulty, theme, and number of enemies.
  3. Watch the live readout to see the projected outlook before you commit.
  4. Click Generate. New NPC actor(s) appear in your Actors directory, ready to drag onto a scene. Dumped into the root, or into a specific folder if you set one in the module settings.
  5. Review the results summary to see how the actual creature(s) compare to the initial projection.

Custom Content

imageimage

Add your own homebrew feats, weapons, and spells to the randomization pools without editing JSON:

  1. Open a feat, weapon, or spell item's sheet and click the export icon (file with an arrow icon) in the window header (nex to the uuid, close, etc buttons).
  2. Fill in the export dialog information: category/type, CR range or spell tier, theme tags, chassis affinity, damage, etc. Hover the info icons next to each field for an explanation of what it affects.
  3. Click Export. The item is now part of your randomization pools.
  4. Edit the original item any time from the Custom Content manager, then use ReSync (from the same export dialog, or the Custom Content manager) to pull its latest description and stats into the entry.
  5. Open the Custom Content manager from the Actors sidebar (list icon) or Module Settings -> Custom Content to enable/disable, ReSync, or delete entries (and to Export/Import your whole custom content pool as a JSON file for sharing homebrew between worlds).

See the Wiki for the full field-by-field reference.


For Developers / Module Integrations

Encounter Forge exposes game.modules.get("encounter-forge").api with generate(), openDialog(), and openDialogFor(overrides) for generating creatures from your own module, plus encounterForge.generationStarted, encounterForge.creatureCreated, and encounterForge.encounterComplete hooks for reacting to generation.

The API also exposes exportCustomContent() and importCustomContent(payload), the same machinery behind the Custom Content manager's Export/Import buttons. If your module ships its own bestiary, item pack, or homebrew content, you can bundle an Encounter Forge content pack (JSON) alongside it and call importCustomContent() to drop those traits, actions, and spells straight into the randomization pools, no manual setup for the GM. This works well both ways: a lore/compendium module can feed Encounter Forge new content, and Encounter Forge's openDialogFor() can hand a freshly generated NPC straight back to that module's UI.

If you're building a module that could pair well with Encounter Forge, feel free to reach out, I'd be happy to help with integration or cross-promote.

Full API reference, options tables, hook payloads, and code samples live in the Wiki.


Screenshots

image

image


Roadmap

Have a feature request or found a balance edge case? Open an issue on GitHub or drop a note on Patreon. See links below.


About

Built and maintained by Elemor.

If you find this useful and want to support continued development, the Patreon link above is the best way to do that.

Bug reports and feature requests are welcome via the Issues tab.

Supported Game Systems

  1. Dungeons & Dragons Fifth Edition

    Latest Version: Version 6.0.6 Last Updated 1 week, 5 days ago

Categories

Available Versions

  1. Version v2.3.0

    17 hours, 42 minutes ago
    Foundry Version 12.328 - 14 (Verified 14) Manifest URL Read Notes
  2. Version v2.2.1

    2 months, 2 weeks ago
    Foundry Version 12.328 - 14 (Verified 14) Manifest URL Read Notes
  3. Version v2.2.0

    2 months, 3 weeks ago
    Foundry Version 12 - 14 (Verified 14) Manifest URL Read Notes
  4. Version v2.1.0

    3 months, 1 week ago
    Foundry Version 12 - 14 (Verified 14) Manifest URL Read Notes
  5. Version v2.0.0

    3 months, 2 weeks ago
    Foundry Version 12 - 14 (Verified 14) Manifest URL Read Notes
  6. Version 1.0.0

    4 months ago
    Foundry Version 12 - 12 (Verified 12) Manifest URL Read Notes