ForgeKit
Dependency-free dev-tooling for Outward BepInEx mods: file-driven dev command loop, self-test harness, on-screen toasts, player-ready lifecycle wait, embedded/override table loaders, and a shared dev-verb pack (movement/combat/skill/status probes).
| Date uploaded | a day ago |
| Version | 0.4.0 |
| Download link | CeruleanCutlass-ForgeKit-0.4.0.zip |
| Downloads | 41 |
| Dependency string | CeruleanCutlass-ForgeKit-0.4.0 |
This mod requires the following mods to function
README
ForgeKit
📖 Full documentation: ForgeKit wiki page
Dependency-free dev-tooling library for people writing BepInEx 5 mods for Outward: Definitive Edition. It doesn't add anything a player sees on its own — it's the plumbing several other mods (CompanionKit, SpawnKit, and more) build on, and other modders are welcome to build on it too.
Requires: BepInEx 5 (Outward's Mono branch — see Compatibility below). No SideLoader, no Harmony, no other mod dependency.
What's in it
| Piece | What it gives you |
|---|---|
CommandChannel + CommandRegistry |
A file-driven dev command loop: write a verb into BepInEx/config/<yourmod>_cmd.txt, it runs on the next poll (unscaled time, so it still fires while the game is paused). Unknown verb or help lists everything registered. It runs on unscaled time, so it still fires while the game is paused. |
SelfTestHarness |
The [SELFTEST] BEGIN / PASS: / FAIL: / SKIP: / DONE pass= fail= skip= report shape — wire up Check(name, condition) / CheckIf(canRun, …) calls and get one consistent, greppable self-test report (skips are unrunnable-here, not failures). |
Notify |
An on-screen info toast for the player, mirrored to the log. |
Lifecycle |
WhenPlayerReady — a coroutine that waits past the game's void/staging coordinates before your mod starts touching the player, plus IsSanePosition for the same check inline. |
TableLoader<T> / EmbeddedRes |
Embedded-default-plus-config-override text/texture tables: ship a sane default inside your DLL, let players override it by dropping a file in BepInEx/config/. |
Installing (for players)
Drop the ForgeKit folder into BepInEx/plugins/. It has no effect by itself — install it
because another mod you're using declares it as a dependency.
Using it (for modders)
<!-- your .csproj -->
<ProjectReference Include="path\to\ForgeKit\ForgeKit.csproj" Private="false" />
[BepInPlugin(GUID, NAME, VERSION)]
[BepInDependency(ForgeKit.Plugin.GUID)]
public class Plugin : BaseUnityPlugin
{
private CommandRegistry _commands;
private CommandChannel _channel;
void Awake()
{
_commands = new CommandRegistry(Logger);
_commands.Register("hello", "hello — logs a greeting.", args => Logger.LogMessage("Hi!"));
_channel = new CommandChannel("YourMod_cmd.txt", Logger, _commands);
}
void Update() => _channel.Tick();
}
Private="false" matters — it stops MSBuild from copying a second ForgeKit.dll into your
mod's own output folder. The kit ships from its own BepInEx/plugins/ForgeKit/ folder; your
mod just references it and declares the dependency so BepInEx loads it first.
Configuration
ForgeKit has no configuration file of its own — it provides the command channel and
config-table helpers that consuming mods use. The dev command loop reads a per-consumer file at
BepInEx/config/<Mod>_cmd.txt (e.g. BepInEx/config/YourMod_cmd.txt), and TableLoader<T> lets a
consumer ship an embedded default table overridable by a file the player drops in BepInEx/config/.
Any settings live in the consuming mod's own cobalt.<name>.cfg, not here.
Compatibility
Outward must be on its Mono Steam beta branch, not the default IL2CPP build — like every
BepInEx 5 mod for this game. If your game runs but no BepInEx mods load and there's no crash log,
this is almost always why (Properties → Betas → select mono in Steam).
License
Apache License 2.0 — see LICENSE in the repository root. You may use, modify, and redistribute
this kit (including in commercial mods) provided you keep the copyright/license notice; see the
license text for the full terms.
CHANGELOG
ForgeKit changelog
0.4.0 — 2026-07-30
- Cap all-status build-up resistance below the engine's refusal sentinel
- Review fixes: the shared kits must not enforce OUR id allocation
- Draw every custom id from the community-allocated pool (87000-87999)
- Wire the test-automation tooling wave: Containers+Resilience CommonVerbs domains, caravanreroll rows, ForgeKit 0.4.0, ledger/STATUS, limits survey
- Merge lane 3: container/caravan queue-unblocker verbs + review fixes (scavengesim reachability honesty, quest-event disclosure, reopen gate typing, pristine-state skip)
- Lane 3 review fixes: honesty gates on the container + scavenge-sim verbs
- Merge lane 2: session resilience (unstick/LoadGate/goto hardening) + review fixes (Done precedence, sawLoading acceptance, latch decoupling)
- Merge lane 1: ForgeKit command-script runner (script/scriptcancel/scriptstatus) + review fixes (waitloaded stale-flag acceptance rule, NaN rejection, pump-gap wording)
- Review fixes F2/F3/F4-F5/F6: watchdog pre-load window, granular refusal, comment truth, latch ownership
- Review fixes: waitloaded stale-TRUE trap, NaN waits, pump-gap misblame
- Concurrent-session work committed as-is: grantstatus [force] + StatusApplyGate (DoT thread) + 2026-07-29/30 live-session testplan results
- Session resilience:
unstickverb,[LOADGATE]watchdog, hardenedgoto - Lane 3: container + caravan queue-unblocker verbs
- Add
scriptrunner: one command line, several verbs, real time between steps - Hyena/Pearlbird tuning wave: HAO taunt, gifts, bone relic, feed rule