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 host items receive socket slots, and then transfers gem behavior into the host item when a gem is inserted.

What the module currently covers:

  • drag-and-drop gem socketing
  • configurable socketable host item types
  • gem definitions based on loot subtypes
  • automatic transfer of Active Effects
  • automatic mirroring of Activities
  • optional gem combat data in +Details
  • optional named resources with current and maximum charges
  • reusable gem tags for socket conditions
  • activity consumption from one gem, one host item, or a character-wide socket pool
  • per-slot descriptions, tint colors, visibility, and JavaScript conditions
  • socket feedback on item sheets, actor inventories, activity lists, and the damage roll dialog
  • support for the default dnd5e item sheet and Tidy5e Sheet

Compatibility and 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

Compatibility:

  • Foundry VTT v13 and v14
  • system: dnd5e
  • recommended dependency: libWrapper
  • recommended integration: SC More Activities
  • optional sheet integration: Tidy5e Sheet

After installing:

  1. Enable SC - Simple Sockets in your world.
  2. Open Configure Settings > Module Settings > SC - Simple Sockets.
  3. Configure socketable host item types.
  4. Configure which loot subtypes count as gems.
  5. Create or import a few test gems.
  6. Test the workflow on one host item before expanding your content library.

Settings and Setup

Most setup starts in Configure Settings > Module Settings > SC - Simple Sockets.

The settings hub is the entry point for socket rules, socketable item types, gem subtype setup, documentation, and support actions.

Main entries:

  • Socket settings
  • Configure Socketable Item Types
  • Configure Gem Loot Subtypes
  • Configure Custom Loot Subtypes
  • Documentation
  • Support the developer

The dedicated Socket settings window groups the main runtime behavior.

This window controls permissions, socket limits, gem removal behavior, and how the socket UI is presented.

Main rules and display settings:

SettingWhat it controls
Edit Socket PermissionThe minimum Foundry role required to add or remove sockets.
Maximum Number of Sockets per ItemThe socket limit for each item. Use `-1` for unlimited sockets.
Delete Gem on RemovalWhether unsocketing destroys the gem or returns it to inventory by default.
Enable Socket Tab on all itemsWhether every socketable item shows the Sockets tab automatically.
Gem damage layout in roll dialogHow extra gem damage is grouped in the dnd5e damage roll configuration dialog.
Socket tab layoutWhether the Sockets tab uses the default list layout or the grid layout.

The gem damage layout setting currently supports four modes:

  • Group by gem
  • Group by damage type
  • Group by gem type
  • Group by damage type with badges

Socketable host item types are configured separately.

Socketability is controlled globally, so you decide once which item types can receive sockets.

By default, the module allows sockets on:

  • weapon
  • equipment

Gem identification also starts from a global rule.

Loot items are treated as gems when their subtype matches the configured gem subtype list.

By default, a gem is:

  • an item of type loot
  • with subtype gem

If you want alternate gem families such as runes or shards, add custom loot subtypes.

Custom loot subtypes let you extend the gem system without introducing a new Foundry item type.

If Enable Socket Tab on all items is disabled, an eligible item can still opt in from Details.

This per-item toggle matters when you want sockets on selected items only instead of every valid host item.

Build Gems

Gem authoring uses normal dnd5e loot items plus the module's extra controls.

Each gem can define:

  • its accepted loot subtype
  • one or more descriptions
  • Active Effects
  • Activities
  • +Details combat data
  • a Socketed Resource with current and maximum charges
  • reusable Gem Tags
  • Allowed Item Types
Descriptions
A gem can carry standard description content plus a dedicated socket description used after insertion.
1 / 5

Practical gem behavior:

  • gem Active Effects are applied to the host item
  • gem Activities are mirrored to the host item
  • gem +Details data can add extra damage and attack modifiers
  • gem resources can provide charges while the gem is socketed
  • gem tags can be checked by slot conditions without depending on the gem name
  • gem host restrictions are checked before insertion

Gem Tags and Socketed Charges

The fields in this section are optional. Existing gems continue to work without tags or a socketed resource.

Add charges to a gem

A gem can carry a named resource such as energy, battery, or magic. The current and maximum values remain on that gem instead of being copied to the host item or actor.

  1. Open the gem item.
  2. Open +Details.
  3. Under Socketed Resource, enter a short Resource Key such as battery.
  4. Set Current and Maximum.
  5. Optionally enable Destroy when out of charges if consumption should destroy and remove the gem when its last charge is spent.

Configure the resource key, current and maximum charges, optional destruction at zero, and reusable tags in +Details.

The resource is available only while the gem is socketed. If the gem is removed and returned to inventory, it keeps its remaining charges. Setting the current value to 0 manually does not trigger Destroy when out of charges; that option applies when activity consumption drains the gem to zero.

Organize gems with tags

Tags provide stable categories for socket rules. This lets differently named gems share a tag such as fire, poison, healing, or dynamo-battery.

  1. Open the gem's +Details tab.
  2. Add one or more values under Gem Tags.
  3. Open a socket's settings and reference the tag in Slot condition.

Tags are normalized automatically: uppercase becomes lowercase, accents are removed, and spaces become hyphens. For example, Dynamo Battery becomes dynamo-battery.

To accept only gems tagged fire, use:

js
return hasGemTag("fire");

Socket Items

Once your world has valid gems and valid host items, the main socketing workflow is straightforward:

  1. Open a compatible host item.
  2. Open the Sockets tab.
  3. Add one or more empty slots.
  4. Drag a gem into an empty slot.
List layout
The default list layout is more explicit and easier to inspect slot by slot.
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 result depends on the active removal mode:

  • if gem deletion is enabled, the gem is destroyed
  • otherwise the gem is extracted back into inventory

That behavior can come from the global Delete Gem on Removal setting or from a per-slot override.

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

Spend Socketed Charges

Activities can use the Socketed Charges consumption type to spend a gem's resource. In the activity's consumption settings, choose where the charges come from:

FromWhat it spends
Source gem (this activity)Charges from the gem that provided the activity.
Any gem with resourceThe named resource from compatible socketed gems, in slot order.
Specific slotCharges from one socket position on the activity's item.
Gem by nameCharges from socketed gems with that exact name.
Gem name matchesCharges from gems found by a simple name pattern such as `Fire*`.

For compatible target modes, Pool scope controls which host items contribute:

Pool scopeIncluded hosts
Sockets on this itemOnly the item that owns the activity.
Equipped sockets on this characterSocketed items on the same actor whose equipped state is active.
All sockets on this characterEvery socketed item on the same actor, including unequipped items.

Character pools are calculated from the socketed gems; they are not a second balance stored on the actor. Consumption checks the activity's item first, then the actor's other eligible items and their sockets in order. If the complete pool cannot pay the cost, the activity is blocked instead of partially spending it.

The optional SC More Activities integration also provides socket activities for inserting and extracting gems, recharging one gem, or recharging a shared resource pool.

Resource pools
The Sockets tab lists each gem's resource, remaining charges, and destroy-at-zero setting.
1 / 3

Filter host items in a character pool

Host item filter is an optional JavaScript condition on a socket consumption target. It is separate from Slot condition: the slot condition decides whether a gem may be inserted, while the host item filter decides which socketed items may contribute to an activity's charge pool.

The filter receives these useful values:

VariableWhat it represents
`item` or `hostItem`The candidate socketed host item.
`sourceItem`The item that owns the activity.
`actor`The actor that owns the source item and candidate hosts.
`activity`The activity performing the consumption.
`user` and `game`The current Foundry user and game context.
`getProperty` and `hasProperty`Helpers for safely checking nested data paths.

A truthy result includes the candidate host; a falsy result excludes it. Both an expression and a block with return are accepted. Invalid code or a runtime error blocks the entire consumption so charges are not taken from an unintended item.

Host Item Filter Examples

Choose a starting point, then adapt the checked item paths to your world's data.

4 / 4 examples

Use only weapon hosts

Restrict a character pool to socketed weapons and ignore armor or other supported host types.

Example Code
return item?.type === "weapon";

Exclude the activity's own item

Draw from other eligible socketed items on the actor without using charges from the item that owns the activity.

Example Code
return item?.id !== sourceItem?.id;

Match a custom pool group

Use this when both source and host items already carry the same campaign-defined world flag.

Example Code
const group = getProperty(sourceItem, "flags.world.socketPool");
return Boolean(group)
&& getProperty(item, "flags.world.socketPool") === group;

Match the source item's SC Setforge set

With Equipped sockets on this character, include only equipped socket hosts that belong to the same SC Setforge set as the source item.

Example Code
const sourceSet = getProperty(sourceItem, "flags.sc-setforge.setId");
return Boolean(sourceSet)
&& getProperty(item, "flags.sc-setforge.setId") === sourceSet;

Slot Settings and Slot Conditions

Each socket can carry its own configuration instead of behaving like every other slot on the item.

Slot settings
Each slot can store its own name, empty-slot description, tint, visibility, and removal behavior.
1 / 3

Per-slot settings currently include:

SettingWhat it doesNotes
Slot nameOverrides the visible slot name.If left blank, the slot falls back to `Empty` while empty or the gem name while filled.
Hide slotHides the slot from non-GM users.The empty-slot description is also GM-only while the slot is hidden.
Delete gem on removalOverrides the normal gem-removal behavior for that slot.If enabled, removing a gem from that slot deletes it even when the global setting would normally return it.
Slot conditionRuns an extra JavaScript rule before a gem can be inserted.An empty condition means there is no extra slot-specific restriction.
Slot descriptionShows custom text for that slot while it is empty.Once a gem is inserted, the gem's own socket description takes over.
Slot colorApplies a custom tint to the empty socket frame.This is visual only and affects the empty socket state, not the inserted gem.

Slot Condition

Slot condition is the advanced rule field for deciding whether a specific gem can enter a specific socket.

If the field is empty, the slot accepts any gem that already passed the module's normal 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

Both styles work:

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

Available variables:

VariableUse it forNotes
`gem` or `gemItem`Checking the gem being inserted.Use this for name, rarity, flags, or subtype checks.
`gemTags`Reading all normalized tags on the gem.This is an array such as `["fire", "legendary"]`.
`hasGemTag(tag)`Checking one normalized gem tag.Prefer this helper when a rule needs a single stable category.
`hostItem` or `item`Checking the receiving item.Useful when the same gem should behave differently on weapons, armor, or other host items.
`actor`Checking the owning actor.This is most useful when the host item belongs to an actor instead of a world item.
`user`Checking the current Foundry user.Advanced use only. Most socket rules should not depend on the user.
`slot`Inspecting the current slot data.This is a slot snapshot, not the gem document itself.
`slotConfig`Reading the slot's own configured fields.Useful when your logic depends on the slot name, description, color, or flags already stored there.
`slotIndex`Checking which slot is being targeted.This is zero-based, so the first slot is `0`.
`source`Inspecting workflow source data when provided.Advanced use only. This may be `null` depending on how the insertion started.
`getProperty` and `hasProperty`Safely reading deep data paths.Use these when the field may not exist on every gem.
`deepClone`Cloning context data before changing it in custom logic.Most conditions do not need this helper.

Basic Condition Examples

These examples all assume the slot already passed the module's normal checks for gem identity, host compatibility, and socketability.

Example Filters

Search within this example list without affecting the rest of the page.

7 / 7 examples

Require a name fragment

Use this when a slot should accept only gems whose name contains a specific word such as Ruby, Rune, Frost, or Bloodstone.

Example Code
return gem?.name?.includes("Ruby");

Require a gem tag

Use a stable category instead of tying the socket rule to a gem's visible name.

Example Code
return hasGemTag("fire");

Require a specific rarity

Use this when the slot should reserve itself for stronger gems and reject common or uncommon ones.

Example Code
return getProperty(gem, "system.rarity") === "rare";

Require minimum Intelligence

Use this when a gem should only be socketed by an actor with enough Intelligence to handle arcane or technical gems.

Example Code
return (actor?.system?.abilities?.int?.value ?? 0) >= 16;

Require both rarity and name

Use this for curated signature gems where the slot should only accept a named gem family at a specific power tier.

Example Code
return gem?.name?.includes("Ruby") && getProperty(gem, "system.rarity") === "rare";

Require an active effect on the actor

Use this when socketing should only work while the actor is under a specific buff, blessing, stance, or temporary state.

Example Code
return actor?.effects?.some?.((effect) => effect.name === "Arcane Focus" && !effect.disabled);

Require another gem already socketed

Use this when a slot should only unlock after the host item already contains a prerequisite gem.

Example Code
const sockets = getProperty(hostItem, "flags.sc-simple-sockets.sockets") ?? [];
return sockets.some((entry) => (entry?.gem?.name ?? entry?._gemData?.name) === "Ruby");

Writing Tips

  • Start with the simplest rule that solves the slot restriction.
  • Prefer getProperty(...) when a field may not exist on every gem.
  • Use slotIndex for position-based rules and gem for gem-data rules.
  • If a condition becomes hard to read, split the logic into several named checks inside the code block before returning the final result.
  • If the code is invalid or throws an error at runtime, the module blocks the gem and shows a warning instead of failing silently.

UI Feedback

The module surfaces socket state outside the Sockets tab as well.

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

This feedback appears on:

  • the standard dnd5e item sheet
  • Tidy5e Sheet item tabs and descriptions
  • the host item's Sockets tab and Socket Descriptions block, including charge values
  • actor inventory rows
  • item activity lists
  • the damage roll configuration dialog

API and Included Content

The module ships with included content and an exposed API.

Included from module.json:

  • one item compendium with socket-ready gem content
  • one macro compendium for socket workflows

Create Slots with the Included Macro

If you want to add sockets without opening each item sheet first, import a macro from the SC - Simple Sockets Macro compendium.

Current included macro examples include:

  • Add Socket Slot to Item
  • Add Conditional Socket Slot to Item

The standard add-slot workflow uses the same interactive helper exposed by the module API:

  1. Run Add Socket Slot to Item from your hotbar or macro directory.
  2. Click a supported item anywhere in the Foundry UI.
  3. Confirm the prompt to add the new socket.

The workflow shows Click an item to add a socket. Press Esc to cancel. while selection is active.

Use Add Conditional Socket Slot to Item when you want the new slot to start with predefined rules such as a name, description, color, or slot condition.

addSocketInteractive(options) currently accepts these top-level options:

OptionTypeDefaultWhat it does
`notifications``boolean``true`Shows the selection prompt and the success, warning, or error notifications used by the interactive workflow.
`promptSlotConfig``boolean``false`Opens the slot-configuration dialog before the socket is created. If it is disabled, the macro uses `slotConfig` as-is after validation.
`slotConfig``object``{}`Preconfigures the new slot. Use this for default name, description, condition, color, visibility, or gem-removal behavior.
`cursorClass``string`module defaultAdvanced override for the temporary CSS cursor class used while the macro waits for you to click an item.
`renderSheet``boolean``true`Defined in the workflow defaults, but the current add-slot implementation does not read this field directly. No visible effect is confirmed in this path.

options.slotConfig accepts these fields:

FieldTypeDefaultWhat it does
`name``string``""`Sets the slot name. If left empty, the slot falls back to the module's normal empty-slot label.
`description``string``""`Adds the empty-slot description shown before a gem is inserted.
`condition``string``""`Adds the JavaScript slot condition used to decide whether a gem can enter that socket.
`color``string``""`Applies a tint to the empty socket. Valid hex colors are normalized to uppercase `#RRGGBB`.
`hidden``boolean``false`Marks the slot as hidden. This is accepted by the slot config object even though the interactive add-slot dialog does not currently expose a hidden toggle.
`deleteGemOnRemoval``boolean``false`Makes this slot delete its gem when unsocketed, overriding the global removal behavior for that slot.

Example: create a slot that always deletes its gem when the gem is removed:

js
await game.modules.get("sc-simple-sockets")?.api?.macro?.addSocketInteractive({
  notifications: true,
  slotConfig: {
    deleteGemOnRemoval: true
  }
});

Because promptSlotConfig defaults to false, this version uses the provided slotConfig directly after validation.

The module API lives at:

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

Current API surfaces:

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?.sockets?.hasItemGemTag(itemOrUuid, tag)
game.modules.get("sc-simple-sockets")?.api?.sockets?.removeGem(itemOrUuid, slotIndex)
game.modules.get("sc-simple-sockets")?.api?.sockets?.removeGemKeepingItem(itemOrUuid, slotIndex)
 
game.modules.get("sc-simple-sockets")?.api?.macro?.addSocketInteractive(options)
game.modules.get("sc-simple-sockets")?.api?.macro?.extractGemInteractive(options)
game.modules.get("sc-simple-sockets")?.api?.macro?.selectItemForSocket(options)
game.modules.get("sc-simple-sockets")?.api?.macro?.removeGemWithoutDeleting(itemOrUuid, slotIndex)

The socket API also exposes these hook names:

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

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

Troubleshooting and Notes

Useful current behaviors and limits:

  • gems are still normal loot items, so gem identity starts from loot subtype rules instead of a new item type
  • container is intentionally excluded from the socketable item-type picker
  • if global socket-tab visibility is disabled, items that already have sockets keep their local socket-tab access
  • gems with the same resource key contribute to one calculated pool; the host item and actor do not store a duplicate charge balance
  • manually setting a gem to zero charges does not trigger Destroy when out of charges
  • Source gem and Specific slot consumption stay on the activity's own item even when a character-wide scope is selected
  • invalid slot-condition code blocks the gem and shows a warning instead of failing silently
  • invalid Host item filter code blocks the entire consumption instead of falling back to a broader pool
  • replacing a gem removes the previous gem's transferred effects and mirrored activities before applying the new one

Troubleshooting checks:

  • if an item cannot receive sockets, verify its type is enabled in Configure Socketable Item Types
  • if an item is not recognized as a gem, verify its loot subtype is included in Configure Gem Loot Subtypes
  • if the Sockets tab is missing, check the global Enable Socket Tab on all items setting and then the per-item Enable Socket Tab toggle in Details
  • if a gem is rejected by one slot only, inspect that slot's Slot condition
  • if a gem does not contribute charges, verify that Resource Key is not blank and that the activity uses the same key
  • if a character pool misses an item, verify the selected Pool scope; the equipped scope only includes items currently marked as equipped
  • if filtered consumption finds no charges, check Host item filter separately from the socket's Slot condition
  • if gem damage looks confusing in the roll dialog, change Gem damage layout in roll dialog and compare the four layouts
  • if you need deeper debugging, enable Debug trace logging in module settings and inspect the browser console

Client-side notes:

  • the module can show an automatic What's New popup after updates
  • Hide automatic What's New popup until next update controls whether that popup stays hidden after you acknowledge it