Modern crafting system for Ruby / Pokémon SDK projects
Fully configurable JSON recipes + advanced unlock logic + UI integration
-
Dowload Crafting.psdkplug
-
Place the plugin in your project/scripts:
Crafting.psdkplug -
Run this command at the root of your project:
.\psdk --util=plugin load -
Configure crafting settings:
Data/configs/crafting_config.json
GamePlay.open_craft_system_uiYou can call this from:
- Events
- NPC interactions
- Menus
- Scripts
All crafting data is defined in:
Data/configs/crafting_config.json
You can define custom recipe categories:
"categories": [
{ "all": 3 },
{ "ball": 4 },
{ "medical": 5 },
{ "tm": 6 }
]| Field | Required | Description |
|---|---|---|
| category_name | ✅ | Internal symbol used by recipes |
| index_csv | ✅ | CSV/UI index reference |
You can add unlimited categories.
Example:
{ "legendary": 7 }Then assign it inside a recipe:
"category": "legendary""poke_ball": {
"ingredients": {
"red_apricorn": 2
},
"result": "poke_ball",
"quantity": 1,
"category": "ball",
"unlock_condition": {
"type": "manual",
"value": true
}
}| Field | Required | Type | Description |
|---|---|---|---|
| ingredients | ✅ | Object | Required items |
| result | ✅ | String | Crafted item |
| quantity | ✅ | Integer | Amount produced |
| category | ✅ | String | Recipe category |
| unlock_condition | ✅ | Object | Unlock logic |
Every recipe must have an unlock condition defined.
{
"type": "switch",
"id": 12
}| Field | Required | Type | Description |
|---|---|---|---|
| type | ✅ | String | Condition type |
| id | ✅ | Integer | Switch ID |
{
"type": "variable",
"id": 5,
"value": 10
}| Field | Required | Type | Description |
|---|---|---|---|
| type | ✅ | String | Condition type |
| id | ✅ | Integer | Variable ID |
| value | ✅ | Integer | Required value |
{
"type": "quest",
"id": 3
}| Field | Required | Type | Description |
|---|---|---|---|
| type | ✅ | String | Condition type |
| id | ✅ | Integer | Quest ID |
{
"type": "recipe",
"key": "poke_ball_basic"
}| Field | Required | Type | Description |
|---|---|---|---|
| type | ✅ | String | Condition type |
| key | ✅ | String | Recipe key |
{
"type": "item",
"item": "hammer_tool",
"quantity": 1
}| Field | Required | Type | Description |
|---|---|---|---|
| type | ✅ | String | Condition type |
| item | ✅ | String | Item name |
| quantity | ✅ | Integer | Required quantity |
{
"type": "manual",
"value": true
}| Field | Required | Type | Description |
|---|---|---|---|
| type | ✅ | String | Condition type |
| value | ✅ | Boolean | Initial unlock state |
Usage:
"value": true→ Recipe is unlocked by default"value": false→ Recipe is locked by default
Controlled dynamically with:
CraftSystem.unlock(:recipe_key)
CraftSystem.lock(:recipe_key)Use manual unlock for recipes that should be available from the start or controlled via scripts/events.
{
"operator": "and",
"conditions": []
}All conditions must be met.
{
"operator": "or",
"conditions": []
}At least one condition must be met.
{
"operator": "not",
"conditions": []
}Inverts the condition result.
| Field | Required | Type | Description |
|---|---|---|---|
| operator | ✅ | String | Logic type (and/or/not) |
| conditions | ✅ | Array | Array of conditions |
Nested operators are fully supported.
"great_ball": {
"ingredients": {
"poke_ball": 1,
"blue_apricorn": 1
},
"result": "great_ball",
"quantity": 1,
"category": "ball",
"unlock_condition": {
"operator": "and",
"conditions": [
{
"type": "switch",
"id": 500
},
{
"type": "variable",
"id": 988,
"value": 3
},
{
"type": "recipe",
"key": "poke_ball"
}
]
}
}This unlocks when:
- Switch 500 is ON AND
- Variable 988 equals 3 AND
- Recipe "poke_ball" is unlocked
Returns all recipes.
CraftSystem.all_recipesCheck if recipe is unlocked.
CraftSystem.unlocked?(:recipe_key)Manually unlock/lock a recipe.
CraftSystem.unlock(:recipe_key)
CraftSystem.lock(:recipe_key)Check if player can craft.
CraftSystem.can_craft?(:recipe_key, amount)Craft a specific amount.
CraftSystem.craft(:recipe_key, amount)Craft maximum possible amount.
CraftSystem.craft_all(:recipe_key)Get maximum craftable amount.
CraftSystem.max_craft(:recipe_key)Get recipe data.
CraftSystem.data_craft(:recipe_key)The system automatically:
- Synchronizes crafting state
- Updates dependent recipes
- Removes invalid states
- Re-evaluates unlock conditions dynamically
- Prevents circular dependency issues
- Always define unlock_condition: Every recipe must have an unlock condition, use
{"type": "manual", "value": true}for default availability - Avoid circular dependencies: Don't make Recipe A depend on Recipe B while Recipe B depends on Recipe A
- Use manual unlocks for tutorials: Control progression with manual unlock/lock
- Keep categories consistent: Use the same category names across recipes
- Use nested operators for advanced progression: Combine AND/OR/NOT for complex unlock logic
{
"categories": [
{ "all": 3 },
{ "ball": 4 },
{ "medical": 5 },
{ "tm": 6 }
],
"data": {
"poke_ball": {
"ingredients": {
"red_apricorn": 2
},
"result": "poke_ball",
"quantity": 1,
"category": "ball",
"unlock_condition": {
"type": "manual",
"value": true
}
},
"great_ball": {
"ingredients": {
"poke_ball": 1,
"blue_apricorn": 1
},
"result": "great_ball",
"quantity": 1,
"category": "ball",
"unlock_condition": {
"operator": "and",
"conditions": [
{
"type": "switch",
"id": 500
},
{
"type": "variable",
"id": 988,
"value": 3
},
{
"type": "recipe",
"key": "poke_ball"
}
]
}
},
"potion": {
"ingredients": {
"tiny_mushroom": 2
},
"result": "potion",
"quantity": 1,
"category": "medical",
"unlock_condition": {
"type": "manual",
"value": false
}
},
"super_potion": {
"ingredients": {
"big_mushroom": 1,
"potion": 1
},
"result": "super_potion",
"quantity": 1,
"category": "medical",
"unlock_condition": {
"type": "recipe",
"key": "potion"
}
}
}
}Important: Every recipe should have an
unlock_condition. Use{"type": "manual", "value": true}for recipes available by default.
Free to use, modify and distribute.
Made with ❤️ for Pokémon SDK & Ruby projects.

