Shattered Codex

Wiki

Modules/SC - Simple Sockets

SC - Simple Sockets

Foundry v13-v14System D&D 5eFree

SC - Simple Sockets

Overview

SC - Simple Sockets adds a socket workflow to D&D 5e items in Foundry.

The module treats configured loot items as gems, lets compatible items receive socket slots, and then transfers the gem's functionality into the host item when it is socketed.

What the module focuses on:

  • drag-and-drop socketing for supported item types
  • gem definitions based on loot subtypes
  • automatic transfer of Active Effects
  • automatic mirroring of Activities
  • optional gem combat data such as extra damage, attack bonus, and crit rules
  • per-slot descriptions, colors, and custom conditions
  • inventory, sheet, tooltip, and roll-dialog feedback
  • support for the default dnd5e item sheet and Tidy5e Sheet

Installation

This module is free.

Install it through Foundry with this manifest URL:

code
https://github.com/Shattered-Codex/sc-simple-sockets/releases/latest/download/module.json

After installing:

  1. Enable SC - Simple Sockets in your world.
  2. Open Configure Settings > Module Settings > SC - Simple Sockets.
  3. Decide which item types can receive sockets.
  4. Decide which loot subtypes count as gems.
  5. Create or import a few gem items and test the socket flow.

Compatibility:

  • Foundry VTT v13 and v14
  • system: dnd5e
  • recommended: libWrapper
  • optional sheet support: Tidy5e Sheet

Settings and Rules

The module settings are split between a settings hub and focused configuration windows.

SC - Simple Sockets settings hub

The settings hub acts as the entry point for socket rules, socketable item types, gem subtype setup, and support links.

The main settings surface exposes:

  • Configure socket settings
  • Configure Socketable Item Types
  • Configure Gem Loot Subtypes
  • Configure Custom Loot Subtypes

Socket settings window

Socket rules that affect permissions, limits, gem removal behavior, roll-dialog layout, and whether the tab is shown globally are grouped into one dedicated form.

Important defaults and controls:

  • Socketable Item Types defaults to weapon and equipment
  • Gem Loot Subtypes defaults to gem
  • Edit Socket Permission controls who may add or remove sockets
  • Maximum Number of Sockets per Item defaults to 6
  • Delete Gem on Removal decides whether removed gems return to inventory or are destroyed
  • Gem damage layout in roll dialog groups gem damage separately in the damage dialog
  • Socket tab layout switches between list and grid views
  • Enable Socket Tab on all items controls whether socketable items always show the tab

If the global socket-tab toggle is disabled, the item can still enable the tab locally in Details.

Per-item socket-tab toggle in Details

This item-level toggle matters when you do not want every supported item to expose sockets automatically.

Building Gems

A gem is identified by rule, not by a special item type.

By default, a gem is:

  • an item of type loot
  • with a loot subtype included in the configured gem subtype list

You can keep the default gem subtype or extend the system with custom loot subtypes.

Socketable item type selection

Socketability is defined globally, so the host item categories are controlled in one place instead of per item template.

Custom loot subtype configuration

Custom subtype support lets you create alternate gem families such as runes, shards, fragments, or any other loot-based category your world needs.

Gem authoring is split across normal dnd5e tabs plus the module's custom fields.

Gem description panels with description, socket description, unidentified description, and chat description
Gem descriptions
Gems can carry multiple description layers, including a dedicated socket description used after the gem is inserted.
1 / 5

Practical gem behavior:

  • if the gem has Active Effects, they are applied to the host item
  • if the gem has Activities, they are copied to the host item
  • if the gem has +Details, its extra damage and combat modifiers affect eligible actions
  • if the gem stores allowed item types, invalid hosts are blocked before insertion

Socketing Items

Once you have a valid host item and a valid gem, the workflow is straightforward:

  1. Open a compatible host item.
  2. Open the Sockets tab.
  3. Add one or more empty slots.
  4. Drag the gem into an empty socket.
Sockets tab in list layout with an empty slot
List layout
The default list layout is more explicit and makes each socket row easier to inspect or configure.
1 / 3

At insertion time, the module validates:

  • whether the dropped item is a configured gem
  • whether the host item type is socketable
  • whether the gem allows that host item type or subtype
  • whether the slot's custom condition accepts the gem

When a gem is removed, the module:

  • removes the transferred Active Effects
  • removes the mirrored Activities
  • returns the gem to inventory or deletes it, depending on settings

Holding Shift while removing a gem or slot skips the confirmation prompt.

Slot Configuration

Each slot can be configured independently, so sockets do not have to be identical.

Socket slot settings window with host item, gem inspection, description, and color controls
Slot settings
A slot can store its own name, empty-slot description, tint color, and inspection links for the host item and current gem.
1 / 3

Per-slot configuration supports:

  • Slot name
  • Slot description
  • Slot color
  • Slot condition
  • Inspect Gem
  • Open Host Item

Description precedence is important:

  • if the slot is empty, the slot description is shown
  • if the slot contains a gem, the gem description takes over

For detailed condition examples, see Slot Condition.

Slot Condition

Slot condition is the advanced rule field that decides whether a gem is allowed into a specific socket.

If the field is empty, the socket accepts any gem that already passed the normal module checks.

If the field contains code:

  • a truthy result allows the gem
  • a falsy result blocks the gem
  • invalid code or runtime errors also block the gem and show a warning

The condition runner accepts either style:

js
gem?.name?.toLowerCase().includes("ruby")
js
return gem?.name?.toLowerCase().includes("ruby");

The module automatically wraps plain expressions in return (...), so both forms work.

Available variables in the condition context:

  • gem or gemItem: the gem being inserted
  • hostItem or item: the item that owns the socket
  • actor: the actor that owns the host item, if any
  • user: the current Foundry user
  • slot: a cloned snapshot of the current slot data
  • slotConfig: the normalized slot config object
  • slotIndex: the zero-based index of the slot
  • source: the original drag/drop source snapshot when available
  • getProperty, hasProperty, deepClone: Foundry utility helpers

Basic Examples

Allow only gems whose name contains Ruby:

js
gem?.name?.toLowerCase().includes("ruby")

Allow only gems whose name starts with Perfect:

js
gem?.name?.startsWith("Perfect")

Allow only gems whose subtype is exactly gem:

js
getProperty(gem, "system.type.value") === "gem"

Allow only gems that are marked magical:

js
getProperty(gem, "system.properties.mgc") === true

Slot and Context Examples

Allow only on the first socket of the item:

js
slotIndex === 0

Allow only if the item belongs to an actor:

js
Boolean(actor)

Allow only for character-owned items:

js
actor?.type === "character"

Gem Restriction Examples

Allow only gems that are rare or higher using the item's native rarity field:

js
return ["rare", "veryRare", "legendary", "artifact"].includes(
  getProperty(gem, "system.rarity")
);

Allow only red-themed gems by name:

js
["ruby", "bloodstone", "crimson"].some((term) =>
  gem?.name?.toLowerCase().includes(term)
)

Allow only gems with an image path from a specific folder:

js
gem?.img?.includes("/assets/gems/")

Allow only gems that add extra damage:

js
const damageEntries = getProperty(gem, "flags.sc-simple-sockets.gemDamage") ?? [];
Array.isArray(damageEntries) && damageEntries.length > 0

Combined Examples

Accept only in the second socket and only for gems with a custom loot subtype of rune:

js
slotIndex === 1 &&
getProperty(gem, "system.type.value") === "rune"

Accept only ruby-like gems on the first socket:

js
slotIndex === 0 &&
gem?.name?.toLowerCase().includes("ruby")

Accept only if the empty socket description contains a keyword:

js
slotConfig?.description?.toLowerCase().includes("fire")

Safe Patterns

Prefer optional chaining and explicit property reads:

js
gem?.name?.toLowerCase().includes("sapphire")

Use getProperty for deep paths that may not exist:

js
getProperty(gem, "flags.world.element") === "lightning"

Return booleans, not objects or text:

js
return gem?.name?.toLowerCase().includes("sapphire");

Common Mistakes

This fails because assignment is not a comparison:

js
gem.name = "Ruby"

This is brittle because it assumes the path always exists:

js
gem.flags.world.rarity === "rare"

Prefer:

js
getProperty(gem, "flags.world.rarity") === "rare"

If you are building complex rules, start with a simple expression first, test it, then add more clauses gradually. That makes it much easier to see which part is blocking the gem.

UI Feedback

The module does not stop at the item sheet. It also adds practical feedback to other play surfaces.

Socket Descriptions block on an item sheet
Socket descriptions
Item sheets gain a Socket Descriptions block that can show empty-slot descriptions or the inserted gem's description and send entries to chat.
1 / 4

Automation and Content

The module includes both packaged content and automation hooks.

Included compendiums from module.json:

  • SC - Gems item compendium
  • SC - Gems Macros macro compendium

The exposed API lives at:

js
game.modules.get("sc-simple-sockets")?.api

Useful methods:

js
game.modules.get("sc-simple-sockets")?.api?.sockets?.getItemSlots(itemOrUuid)
game.modules.get("sc-simple-sockets")?.api?.sockets?.getItemGems(itemOrUuid)
game.modules.get("sc-simple-sockets")?.api?.macro?.addSocketInteractive(options)
game.modules.get("sc-simple-sockets")?.api?.macro?.selectItemForSocket(options)

If you want a macro to create sockets with prefilled rules, descriptions, and labels, use addSocketInteractive(options):

js
await game.modules.get("sc-simple-sockets")?.api?.macro?.addSocketInteractive({
  notifications: true,
  promptSlotConfig: true,
  slotConfig: {
    name: "Runeword Socket",
    description: "Only accepts runes from your curated list.",
    condition: "return gem?.type === 'loot' && gem?.name?.includes('Rune');",
    color: "#C44D24"
  }
});

Macro options:

  • notifications: shows the built-in Foundry notifications during item selection, validation, cancellation, and errors
  • promptSlotConfig: opens a slot-settings dialog before the socket is created
  • slotConfig: provides the default slot configuration that will be applied to the new socket

When promptSlotConfig is enabled, the dialog lets you edit name, description, condition, and color. If a field is left blank, the configured default value from slotConfig is used instead.

Supported slotConfig fields:

  • name: label shown for the socket instead of the generic empty-slot name
  • description: text shown while the socket is empty; once a gem is inserted, the gem description takes precedence
  • condition: JavaScript rule that decides whether a dropped gem is allowed in that slot; it uses the same context and syntax described in Slot Condition
  • color: empty-slot tint color as a hex string such as #C44D24; invalid values are ignored
  • hidden: optional boolean that hides the socket from non-GM users; this can be preset in the macro even though the interactive prompt does not expose it

Example with a hidden preset slot:

js
await game.modules.get("sc-simple-sockets")?.api?.macro?.addSocketInteractive({
  notifications: true,
  slotConfig: {
    name: "GM-only Debug Socket",
    hidden: true,
    condition: "return user?.isGM === true;"
  }
});

Useful hooks:

js
sc-simple-sockets.socketAdded
sc-simple-sockets.socketRemoved

If you want ready-made content instead of building every gem by hand, see SC - More Gems.

Notes

Some practical constraints and behaviors matter:

  • gems are still normal item documents, so their logic starts from loot subtype rules rather than a new item type
  • a host item can still show the Sockets tab if it already has sockets, even when global tab visibility is off
  • invalid slot-condition code blocks the gem and shows a warning instead of silently failing
  • replacing a gem removes the previous slot's transferred effects and activities before applying the new gem
  • container is intentionally excluded from the socketable item-type picker