SC - Simple Sockets
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:
https://github.com/Shattered-Codex/sc-simple-sockets/releases/latest/download/module.jsonAfter installing:
- Enable SC - Simple Sockets in your world.
- Open Configure Settings > Module Settings > SC - Simple Sockets.
- Decide which item types can receive sockets.
- Decide which loot subtypes count as gems.
- Create or import a few gem items and test the socket flow.
Compatibility:
- Foundry VTT
v13andv14 - 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.

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 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
weaponandequipment - 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.

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.

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

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.

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:
- Open a compatible host item.
- Open the Sockets tab.
- Add one or more empty slots.
- Drag the gem into an empty socket.

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.

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:
gem?.name?.toLowerCase().includes("ruby")return gem?.name?.toLowerCase().includes("ruby");The module automatically wraps plain expressions in return (...), so both forms work.
Available variables in the condition context:
gemorgemItem: the gem being insertedhostItemoritem: the item that owns the socketactor: the actor that owns the host item, if anyuser: the current Foundry userslot: a cloned snapshot of the current slot dataslotConfig: the normalized slot config objectslotIndex: the zero-based index of the slotsource: the original drag/drop source snapshot when availablegetProperty,hasProperty,deepClone: Foundry utility helpers
Basic Examples
Allow only gems whose name contains Ruby:
gem?.name?.toLowerCase().includes("ruby")Allow only gems whose name starts with Perfect:
gem?.name?.startsWith("Perfect")Allow only gems whose subtype is exactly gem:
getProperty(gem, "system.type.value") === "gem"Allow only gems that are marked magical:
getProperty(gem, "system.properties.mgc") === trueSlot and Context Examples
Allow only on the first socket of the item:
slotIndex === 0Allow only if the item belongs to an actor:
Boolean(actor)Allow only for character-owned items:
actor?.type === "character"Gem Restriction Examples
Allow only gems that are rare or higher using the item's native rarity field:
return ["rare", "veryRare", "legendary", "artifact"].includes(
getProperty(gem, "system.rarity")
);Allow only red-themed gems by name:
["ruby", "bloodstone", "crimson"].some((term) =>
gem?.name?.toLowerCase().includes(term)
)Allow only gems with an image path from a specific folder:
gem?.img?.includes("/assets/gems/")Allow only gems that add extra damage:
const damageEntries = getProperty(gem, "flags.sc-simple-sockets.gemDamage") ?? [];
Array.isArray(damageEntries) && damageEntries.length > 0Combined Examples
Accept only in the second socket and only for gems with a custom loot subtype of rune:
slotIndex === 1 &&
getProperty(gem, "system.type.value") === "rune"Accept only ruby-like gems on the first socket:
slotIndex === 0 &&
gem?.name?.toLowerCase().includes("ruby")Accept only if the empty socket description contains a keyword:
slotConfig?.description?.toLowerCase().includes("fire")Safe Patterns
Prefer optional chaining and explicit property reads:
gem?.name?.toLowerCase().includes("sapphire")Use getProperty for deep paths that may not exist:
getProperty(gem, "flags.world.element") === "lightning"Return booleans, not objects or text:
return gem?.name?.toLowerCase().includes("sapphire");Common Mistakes
This fails because assignment is not a comparison:
gem.name = "Ruby"This is brittle because it assumes the path always exists:
gem.flags.world.rarity === "rare"Prefer:
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.

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:
game.modules.get("sc-simple-sockets")?.apiUseful methods:
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):
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 errorspromptSlotConfig: opens a slot-settings dialog before the socket is createdslotConfig: 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 namedescription: text shown while the socket is empty; once a gem is inserted, the gem description takes precedencecondition: JavaScript rule that decides whether a dropped gem is allowed in that slot; it uses the same context and syntax described in Slot Conditioncolor: empty-slot tint color as a hex string such as#C44D24; invalid values are ignoredhidden: 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:
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:
sc-simple-sockets.socketAdded
sc-simple-sockets.socketRemovedIf 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
containeris intentionally excluded from the socketable item-type picker