godot-inventory-system
Expert blueprint for inventory systems (Diablo, Resident Evil, Minecraft) covering slot-based containers, stacking logic, weight limits, equipment systems, and drag-drop UI. Use when building RPG inventories, survival item management, or loot systems. Keywords inventory, slot, stack, equipment, crafting, item, Resource, drag-drop.
What this skill does
# Inventory System
Slot management, stacking logic, and resource-based items define robust inventory systems.
## Available Scripts
### [inventory_item_resource.gd](scripts/inventory_item_resource.gd)
Base Resource for all inventory items, allowing for serialized `.tres` item databases.
### [item_slot_data.gd](scripts/item_slot_data.gd)
Reactive data structure for a single inventory slot, broadcasting changes to the UI.
### [inventory_data_resource.gd](scripts/inventory_data_resource.gd)
Centralized Resource for managing inventory arrays, stacking logic, and empty slot finding.
### [inventory_ui_controller.gd](scripts/inventory_ui_controller.gd)
Grid-based UI controller that maps `InventoryData` to visual slots using the "Reactive UI" pattern.
### [drag_and_drop_slot.gd](scripts/drag_and_drop_slot.gd)
Native Godot drag-and-drop implementation for moving and swapping inventory items.
### [item_database_loader.gd](scripts/item_database_loader.gd)
Global registry pattern to efficiently load and lookup items by unique ID strings.
### [inventory_persistence.gd](scripts/inventory_persistence.gd)
Expert logic for serializing and deserializing complex inventory structures to disk.
### [consumable_item_logic.gd](scripts/consumable_item_logic.gd)
Extension pattern for implementing specific item behaviors (Potions, Food) via inheritance.
### [loot_table_resource.gd](scripts/loot_table_resource.gd)
Data-driven loot distribution definition for random drops and chest contents.
### [item_pickup_node.gd](scripts/item_pickup_node.gd)
World-space bridge for converting physical 2D/3D pickups into inventory data.
## NEVER Do in Inventory Systems
- **NEVER use Nodes for items** — `Item extends Node` leads to massive SceneTree bloat and memory leaks. Always use `Item extends Resource` for lightweight data [20].
- **NEVER attempt to add items without checking stack limits** — Adding to an inventory without pre-scanning for existing stacks causes item duplication or loss [21].
- **NEVER allow the UI to modify the Inventory Data directly** — If UI code clears a slot without notifying the data model, you'll get desyncs and ghost items [22].
- **NEVER use `float` for item quantities** — Floating point errors (e.g. 0.9999 instead of 1) will break your "equal to zero" checks. Stick to `int` for counts [23].
- **NEVER add items before validating weight or volume capacity** — Moving validation check *after* adding the item makes it impossible to prevent over-encumbrance [24].
- **NEVER emit signals for every single item inside a batch operation** — Adding 50 items = 50 UI updates. Emit a single `inventory_updated` signal after the loop completes [25].
- **NEVER hardcode item references in scripts** — Use a String ID and a central `ItemDatabase` to look up resources. This is CRITICAL for save system compatibility.
- **NEVER ignore `is_instance_valid()` when accessing item icons** — If a slot's item is null, trying to access `.icon` will crash the UI.
- **NEVER use complex Array logic in the UI** — The UI should only "reflect" the data. All sorting, stacking, and filtering logic belongs in the `InventoryData` resource.
- **NEVER create new `Resource` instances inside a `_process()` loop** — Pre-instantiate your inventory slots or reuse existing ones to prevent allocation spikes.
---
## Core Architecture
```gdscript
# item.gd (Resource)
class_name Item
extends Resource
@export var id: String
@export var display_name: String
@export var icon: Texture2D
@export var max_stack: int = 1
@export var weight: float = 0.0
@export_multiline var description: String
```
## Inventory Manager
```gdscript
# inventory.gd
class_name Inventory
extends Resource
signal item_added(item: Item, amount: int)
signal item_removed(item: Item, amount: int)
signal inventory_changed
@export var slots: Array[InventorySlot] = []
@export var max_slots: int = 20
@export var max_weight: float = 100.0
func _init() -> void:
slots.resize(max_slots)
for i in max_slots:
slots[i] = InventorySlot.new()
func add_item(item: Item, amount: int = 1) -> bool:
var remaining := amount
# Try stacking first
if item.max_stack > 1:
for slot in slots:
if slot.item == item and slot.amount < item.max_stack:
var space := item.max_stack - slot.amount
var to_add := mini(space, remaining)
slot.amount += to_add
remaining -= to_add
if remaining <= 0:
item_added.emit(item, amount)
inventory_changed.emit()
return true
# Add to empty slots
while remaining > 0:
var empty_slot := find_empty_slot()
if empty_slot == null:
return false # Inventory full
var to_add := mini(item.max_stack, remaining)
empty_slot.item = item
empty_slot.amount = to_add
remaining -= to_add
item_added.emit(item, amount)
inventory_changed.emit()
return true
func remove_item(item: Item, amount: int = 1) -> bool:
var remaining := amount
for slot in slots:
if slot.item == item:
var to_remove := mini(slot.amount, remaining)
slot.amount -= to_remove
remaining -= to_remove
if slot.amount <= 0:
slot.clear()
if remaining <= 0:
item_removed.emit(item, amount)
inventory_changed.emit()
return true
return false # Not enough items
func has_item(item: Item, amount: int = 1) -> bool:
var count := 0
for slot in slots:
if slot.item == item:
count += slot.amount
return count >= amount
func find_empty_slot() -> InventorySlot:
for slot in slots:
if slot.is_empty():
return slot
return null
func get_total_weight() -> float:
var total := 0.0
for slot in slots:
if slot.item:
total += slot.item.weight * slot.amount
return total
```
## Inventory Slot
```gdscript
# inventory_slot.gd
class_name InventorySlot
extends Resource
signal slot_changed
var item: Item = null
var amount: int = 0
func is_empty() -> bool:
return item == null
func clear() -> void:
item = null
amount = 0
slot_changed.emit()
```
## Equipment System
```gdscript
# equipment.gd
class_name Equipment
extends Resource
signal equipment_changed(slot: String, item: Item)
@export var weapon: Item = null
@export var armor: Item = null
@export var accessory: Item = null
func equip(slot: String, item: Item) -> Item:
var old_item: Item = null
match slot:
"weapon":
old_item = weapon
weapon = item
"armor":
old_item = armor
armor = item
"accessory":
old_item = accessory
accessory = item
equipment_changed.emit(slot, item)
return old_item
func unequip(slot: String) -> Item:
return equip(slot, null)
func get_total_stats() -> Dictionary:
var stats := {
"attack": 0,
"defense": 0,
"speed": 0
}
for item in [weapon, armor, accessory]:
if item and item.has("stats"):
for key in item.stats:
stats[key] += item.stats[key]
return stats
```
## UI Integration
```gdscript
# inventory_ui.gd
extends Control
@onready var grid := $GridContainer
var inventory: Inventory
func _ready() -> void:
inventory.inventory_changed.connect(refresh_ui)
refresh_ui()
func refresh_ui() -> void:
# Clear existing
for child in grid.get_children():
child.queue_free()
# Create slot UI
for slot in inventory.slots:
var slot_ui := InventorySlotUI.new()
slot_ui.setup(slot)
grid.add_child(slot_ui)
```
## Crafting Integration
```gdscript
# crafting_recipe.gd
class_name CraftingRecipe
extends ResourRelated in Design
contribute
IncludedLocal-only OSS contribution command center. Auto-refreshes the user's in-flight PR and issue state on invoke so conversations start with full context — no need to brief Claude on what's in flight. Helps the user find issues to contribute to on GitHub, builds per-repo dossiers of what each upstream expects (CLA, DCO, branch convention, AI policy, draft-first, review bots, issue templates), runs deterministic gates before any external action so AI-assisted contributions don't reach maintainers as slop. State is markdown-only: candidate files at ~/.contribute-system/candidates/, repo dossiers at ~/.contribute-system/research/, append-only event log at ~/.contribute-system/log.jsonl. No database, no cloud calls. Use when the user asks about their PRs / issues / contributions, wants to find new work to take on, claim an issue, build/refresh a repo's dossier, or draft a Design Issue or PR. Trigger with "/contribute", "what's my PR status", "find a contribution", "claim issue X", "draft a Design Issue for Y", "refresh dossier for Z".
architectural-analysis
IncludedUser-triggered deep architectural analysis of a codebase or scoped subtree across eight modes — information architecture, data flow, integration points, UI surfaces, interaction patterns, data model, control flow, and failure modes. This skill should be used when the user asks to "diagram this codebase," "map the architecture," "show the data flow," "give me an ERD," "trace control flow," "find the integration points," "verify the layout pattern," "audit the UX architecture," or any similar request whose primary deliverable is mermaid diagrams plus cited reports under docs/architecture/. Dispatches haiku/sonnet sub-agents in parallel for per-mode exploration, then verifies every citation mechanically before any node lands in a diagram. Not for one-off prose explanations of code (use code-explanation) or for high-level system design from scratch (use system-design).
mcp
IncludedModel Context Protocol (MCP) server development and tool management. Languages: Python, TypeScript. Capabilities: build MCP servers, integrate external APIs, discover/execute MCP tools, manage multi-server configs, design agent-centric tools. Actions: create, build, integrate, discover, execute, configure MCP servers/tools. Keywords: MCP, Model Context Protocol, MCP server, MCP tool, stdio transport, SSE transport, tool discovery, resource provider, prompt template, external API integration, Gemini CLI MCP, Claude MCP, agent tools, tool execution, server config. Use when: building MCP servers, integrating external APIs as MCP tools, discovering available MCP tools, executing MCP capabilities, configuring multi-server setups, designing tools for AI agents.
react-native-skia
IncludedDesign, build, debug, and optimise high-polish animated graphics in React Native or Expo using @shopify/react-native-skia, Reanimated, and Gesture Handler. Use when the user wants canvas-driven UI, shaders, paths, rich text, image filters, sprite fields, Skottie, video frames, snapshots, web CanvasKit setup, or performance tuning for custom motion-heavy elements such as loaders, hero art, cards, charts, progress indicators, particle systems, or gesture-driven surfaces. Also use when the user asks for fluid, glow, glass, blob, parallax, 60fps/120fps, or GPU-friendly animated effects in React Native, even if they do not explicitly say "Skia". Do not use for ordinary form/layout work with standard views.
plaid
IncludedProduct Led AI Development — guides founders from idea to launched product. Six capabilities: Idea (discover a product idea), Validate (pressure-test the idea against fatal flaws, problem reality, competition, and 2-week MVP feasibility), Plan (vision intake + document generation), Design (translate image references into a design.md spec), Launch (go-to-market strategy), and Build (roadmap execution). Use when someone says "PLAID", "plaid idea", "help me find an idea", "product idea", "idea from my business", "idea from my expertise", "plaid validate", "validate my idea", "pressure-test", "is this idea good", "find fatal flaws", "validate the problem", "plan a product", "define my vision", "generate a PRD", "product strategy", "plaid design", "design from image", "translate image to design", "create design.md", "extract design tokens", "plaid launch", "go-to-market", "launch plan", "GTM strategy", "launch playbook", "plaid build", "build the app", "start building", or "execute the roadmap".
nextjs-framer-motion-animations
IncludedAdds production-safe Motion for React or Framer Motion animations to Next.js apps, including reveal, hover and tap micro-interactions, whileInView, stagger, AnimatePresence, layout and layoutId transitions, reorder, scroll-linked UI, and lightweight route-content transitions. Use when the user asks to add, refactor, or debug Motion or Framer Motion in App Router or Pages Router codebases, especially around server/client boundaries, reduced motion, LazyMotion, bundle size, hydration, or route transitions. Avoid for GSAP-style timelines, WebGL or 3D scenes, heavy scroll storytelling, or CSS-only effects unless Motion is explicitly requested.