Objetivo: escribir recetas de B42 entendiendo cada parte del craftRecipe, hacer que convivan con los ítems de otros mods, y crear una estación de trabajo propia (una entity con CraftBench).
1. Anatomía de un craftRecipe
La receta del Completo Italiano de Tocomples Food, uno de nuestros mods (tomCompleItaliano/.../scripts/recipes/CompletoItaliano.txt):
craftRecipe MakeCompletoItaliano
{
timedAction = Making, ← animación y sonido mientras se fabrica
time = 60, ← duración (ticks de la acción)
Tags = InHandCraft;Cooking, ← DÓNDE se puede hacer y en qué pestaña sale
category = Cooking, ← categoría en la ventana de crafteo
xpAward = Cooking:3, ← experiencia que da
inputs
{
item 1 [CompleteItaliano.PanCompleto;Base.BunsHotdog_single] flags[InheritFoodAge;ItemCount],
item 1 [CompleteItaliano.Vienesa;Base.Hotdog_single] flags[InheritFoodAge;ItemCount],
item 1 [CompleteItaliano.Palta;Base.Avocado] flags[InheritFoodAge;ItemCount],
item 1 [Base.Tomato] flags[InheritFoodAge;ItemCount],
item 2 [Base.MayonnaiseFull],
}
outputs
{
item 1 CompleteItaliano.CompletoItaliano,
}
}Campos de la receta (contados en scripts/generated/recipes/)
| Campo | Para qué | Ejemplo |
|---|---|---|
timedAction | Qué acción se reproduce | Making, SawLogs, BuildWallHammer |
time | Duración | 60 |
Tags | Dónde se hace: InHandCraft (en la mano, 241 recetas), AnySurfaceCraft (sobre una superficie, 381), CanBeDoneFromFloor, CanBeDoneInDark; o el nombre de una estación (sección 4) | Tags = AnySurfaceCraft;CanBeDoneFromFloor |
category | Pestaña en la ventana de crafteo | Carpentry, Cooking |
xpAward | XP por habilidad | Woodwork:5 |
SkillRequired | Nivel mínimo | Masonry:2 (297 recetas) |
NeedToBeLearn | Hay que aprenderla (libro, revista, investigar) | true |
AutoLearnAny / AutoLearnAll | Se aprende sola al llegar a un nivel | AutoLearnAny = Maintenance:10 |
AllowBatchCraft | Permite fabricar varias de una vez | true |
OnCreate / OnTest | Código que corre al terminar / para validar | RecipeCodeOnCreate.minorCondition |
MetaRecipe | Agrupa variantes de la misma receta para aprenderlas juntas | base:makebonearmor |
2. Las líneas de inputs y outputs
Formato general:
item <cantidad> <qué> [mode:...] [flags[...]] [mappers[...]]Qué ítem acepta:
- Lista explícita:
[Base.Log]o[Base.Dogbane;Base.HempScutched](cualquiera de la lista). - Por tag:
tags[base:saw;base:crudesaw]→ cualquier ítem con alguno de esos tags. Prefiere esto (módulo 02, sección 4). - Cantidad variable:
item variable[1:20] [Base.Basil](el secador de hierbas acepta de 1 a 20).
Qué le pasa al ítem (mode:):
| Modo | Qué hace | Usos en el juego |
|---|---|---|
| (sin modo) | Se consume | la mayoría |
mode:keep | Se usa pero no se gasta: es una herramienta | 1.502 |
mode:destroy | El ítem desaparece entero (ejercicio: lee 3 recetas del juego con mode:destroy y escribe en qué se diferencia de consumirlo) | 244 |
mode:mixture | Para fluidos que se mezclan | 26 |
Flags más usados (con cuántas veces aparecen en el juego):
| Flag | Qué hace |
|---|---|
MayDegradeLight (1.016), MayDegradeVeryLight (170), MayDegrade (39) | La herramienta puede perder condición al usarla |
Prop1, Prop2 | Qué ítem se ve en la mano derecha / izquierda durante la animación |
IsNotDull (219), SharpnessCheck (67) | La herramienta tiene que tener filo |
ItemCount (185) | Cuenta unidades del ítem, no "usos" |
DontRecordInput (104) | No queda registrado en el resultado |
InheritCondition (87), InheritFoodAge (46), InheritColor (34) | El resultado hereda condición / frescura / color del ingrediente |
NoBrokenItems (29) | No acepta ítems rotos |
IsEmpty, NotFull | Para contenedores de líquido |
Fluidos (agua, gasolina, tinte) no son ítems: van con -fluid:
-fluid 1.0 [Petrol],
-fluid 10.0 categories[Water] mode:mixture,itemMapper: un resultado según el ingrediente
Cuando el resultado depende de qué entró (recipes_carpentry.txt, SawLongStick):
inputs { item 1 [Base.LongStick;Base.Sapling] flags[Prop2;InheritCondition] mappers[StickMapper], ... }
outputs { item 2 mapper:StickMapper, }
itemMapper StickMapper
{
Base.WoodenStick2 = Base.LongStick, ← resultado = ingrediente
Base.TreeBranch2 = Base.Sapling,
default = Base.WoodenStick2,
}3. Cómo se aprende una receta
Hay cuatro caminos, y conviene saber cuál usas antes de diseñar:
- Siempre conocida: sin
NeedToBeLearn. - Por lectura: el ítem (revista, libro) tiene
LearnedRecipes = NombreRecetaen su script. - Investigando: un ítem con
Researchablerecipes = NombreReceta; clic derecho → Investigar (así aprendes el encendedor improvisado del estropajo de acero). - Por nivel:
AutoLearnAny = Habilidad:N.
Tocomples Food usa el camino 2: RevistaCompletos tiene LearnedRecipes = MakeCompleto;MakeCompletoDinamico;... (14 recetas) y OnCreate = ItemCodeOnCreate.onCreateRecipeMagazine, igual que las revistas del juego.
4. Entidades y estaciones
En B42 los objetos que se construyen en el mundo (telares, hornos, paredes) son entity. Una entidad junta componentes:
entity SimpleLoom ← entities/agricultural/workstations/entity_simple_loom.txt
{
component UiConfig { xuiSkin = default, entityStyle = ES_SimpleLoom, uiEnabled = true, }
component CraftBench { Recipes = Weaving, } ← es una estación: hace las recetas con Tags = Weaving
component SpriteConfig { face S { layer { row = crafted_04_81, row = crafted_04_80, } } ... }
component CraftRecipe { ... inputs { item 1 tags[base:hammer] mode:keep ..., item 4 [Base.Log], ... } }
↑ cómo se CONSTRUYE el telar
}La conexión estación ↔ recetas es por nombre: CraftBench { Recipes = Weaving } y las recetas con Tags = Weaving (en entity_simple_loom_craftRecipe.txt). Estaciones del juego: WoodCharcoal, Weaving, PotteryWheel, DryingRackHerb, DryingRackGrain, TanLeather, Stone_Quern, SpinningWheel, Toaster...
SpriteConfig dice qué sprites del mapa (tiles) usa cada orientación: una entidad propia necesita tiles propios o reutilizar los del juego (los nombres como crafted_04_81 son tiles de los .pack de tiles).
5. ¿Dónde está el código de OnCreate?
Busca RecipeCodeOnCreate.minorCondition (31 recetas lo usan) en _juego/lua/. No vas a encontrar la definición: solo llamadas como RecipeCodeOnTest.cutFish(item, nil) en server/Fishing/. Eso significa que RecipeCodeOnCreate vive en Java y está expuesto a Lua. Es el primer caso del curso donde la respuesta no está en media/: en el módulo 08 lo abres en el .jar.
Ejercicios
Ejercicio 3.1 · Receta compatible
Receta CursoLab.HacerSopaipillas: harina + agua + aceite (o manteca) → 4 sopaipillas (las del ejercicio 2.1). Requisitos:
- usa tags o listas que acepten variantes del juego (busca qué tags tienen la harina y el aceite),
- necesita una superficie (no en la mano),
- da XP de cocina,
- las sopaipillas heredan la frescura de la harina.
Listo cuando: la receta sale en la ventana de crafteo con ingredientes del juego y el resultado tiene la frescura correcta.
Ejercicio 3.2 · Herramienta que se gasta
Haz que el DestornilladorChino del ejercicio 2.2 se desgaste rápido en tu receta pero normal en las del juego. ¿Dónde vive la decisión de desgaste: en el ítem o en la receta? Escríbelo en una frase.
Ejercicio 3.3 · Receta que hay que aprender
Crea una revista CursoLab.RevistaSopaipillas que enseñe la receta 3.1 y marca la receta con NeedToBeLearn = true.
Listo cuando: con un personaje nuevo la receta no aparece; después de leer la revista, sí.
Ejercicio 3.4 · Mapper
Receta "Rellenar": un pan (Base.Bread o el PanCompleto de Tocomples Food) + un relleno → un pan relleno distinto según el pan que usaste. Usa un itemMapper.
Ejercicio 3.5 · Una estación propia
Crea la entidad CursoLab.FreidoraSopaipillas:
- se construye con martillo + clavos + una olla, usando sprites del juego (busca un tile de cocina que sirva),
- tiene
CraftBench { Recipes = CursoLabFreidora }, - la receta 3.1 pasa a hacerse solo en la freidora.
Listo cuando: construyes la freidora, haces clic derecho en ella y la receta aparece ahí y ya no en el inventario.
Desafío 3
Escribe pzrecipes.py: dado un ítem (Base.Log), lista todas las recetas que lo usan (directo o por tag) y las que lo producen, con el archivo y la línea. Es exactamente el cruce que hace la ficha por ítem del sitio (wenopal.work/referencia/items/): intenta hacerlo sin mirar, después compara.
Anterior: 02 · Scripts: ítems · Siguiente: 04 · Texturas e íconos