Usando mods
Dónde está la carpeta de mods
Abre Mods desde el menú principal. La ruta está escrita en la parte superior de la pantalla, con un botón al lado que abre la carpeta en tu administrador de archivos.
Está al lado de tus partidas guardadas, y es la misma carpeta ya sea que estés instalando el mod de otra persona o escribiendo el tuyo propio. No se lee nada mientras el juego se está ejecutando, por lo que no importa si el juego está abierto mientras mueves archivos.
Instalar un mod
A es una carpeta con mod.json en la parte superior. La mayoría de las descargas se encuentran en esa carpeta dentro de un zip.
| 1. Extráelo | Para que la carpeta que contiene mod.json esté directamente dentro de la carpeta de mods. Un zip que se extrae a northern_reach/northern_reach/mod.json tiene un nivel demasiado profundo y el juego no lo verá. |
| 2. Reinicia el juego | Los paquetes se leen al inicio. No hay instalación en caliente. |
| 3. Enciéndelo | Abre Mod y usa el interruptor. Una carpeta copiada se encuentra y se deja desactivada: nada se carga simplemente al aparecer en una carpeta. |
| 4. Reiniciar de nuevo | La línea dice Activo: reinicie para cargar hasta que lo haga. Luego dice Cargado. |
Un mod que copias permanece desactivado hasta que tú lo dices. El juego rechaza ejecutables sin lugar a dudas, pero un paquete de datos aún puede cambiar precios, artículos y personas de formas que no solicitaste, y uno que aparece solo dentro de un juego que ya se está ejecutando es un problema que nadie quiere diagnosticar. Entonces el juego pregunta. Es un reinicio adicional la primera vez y nunca más para ese paquete.
No hay iniciador, no hay ningún archivo de orden de carga para editar y no hay nada que grabar. El orden de carga es un número dentro de cada paquete, elegido por su autor.
Empieza una partida nueva para un paquete que añada personas, lugares o misiones. Una partida guardada que ya está en curso conserva el mundo con el que fue creada. Los paquetes que solo cambian números, imágenes o color se ven en una partida ya iniciada. Los archivos de audio y fuentes se validan, pero ninguna superficie de paquete en ejecución los consume todavía.
¿Se ha cargado?
Mod, en el menú principal. Cada paquete encontrado va en una línea, con un estado de una palabra: cargado, deshabilitado, no válido, en conflicto, requiere otra modificación, ignorado.
Un mod también puede apagarse solo y dice por qué. El interruptor que colocas se aplica al paquete en el que lo colocas, no a su nombre en la carpeta. Los mods son elegidos por los autores y no hay nada que los coordine, por lo que dos mods no relacionados, ambos llamados northern_reach, son un accidente común y sin esto, el segundo heredaría el cambio del primero. Si el mod bajo una identificación no es el que había activado, la línea lo dice: este no es el mod que activó. Actualizar un mod existente preserva su cambio; borrarlo y copiar otro no.
Si eres el autor de un mod y ves esa línea en tu paquete, tienes una colisión de identificación con el mod de otra persona. Elija una identificación menos obvia.
Dos de esas palabras se refieren a un reinicio que usted debe, no al paquete. Activo: reiniciar para cargar significa que lo activaste y nadie lo ha leído todavía; Desactivado: reiniciar para descargar significa lo contrario y su contenido seguirá en el juego hasta que reinicies. Son palabras separadas a propósito: una pantalla que dice "Cargado" en el momento en que accionas un interruptor te enviaría a buscar en el mundo algo que aún no está ahí.
Cuando el estado no está "cargado", la línea siguiente te indica por qué, en el idioma en el que estás jugando y sin identificadores, no escribiste: qué archivo el juego se niega a ejecutar, qué paquete falta, qué versión quiere. A continuación, lo que hizo el contenido del paquete: cuántas entradas ingresaron, cuántas fueron rechazadas. Mostrar detalles abre el resto, es decir, los identificadores y la regla exacta que rompió cada récord rechazado.
| en la pantalla | en el informe | Qué significa |
|---|---|---|
| Cargado | active | Cargable, sin obstáculos. |
| Inválido | invalid | El manifiesto trae scripts bloqueados o archivos ejecutables. |
| Requiere otro mod | skipped_missing_dependency | Una dependencia declarada está ausente o deshabilitada. |
| Requiere otro mod | skipped_incompatible_dependency | Una dependencia declarada está fuera de su rango. |
| Ignorado | incompatible | El mod apunta a una versión más reciente del juego. |
| Contradictorio | conflict | Dos mods cargables apuntan a la misma identificación de sobrescritura (permanecen cargables; gana load_order, ambos informados). |
| Desactivado | disabled | Lo apagaste o nunca lo encendiste. Los paquetes son de elección libre: colocar uno en la carpeta lo instala y no lo enciende. |
| Activado: reinicia para cargar | — | Lo activaste y nadie lo ha leído todavía. Su contenido no estará en el juego hasta que reinicies. |
| Desactivado: reinicia para descargar | — | Lo apagaste y todavía está cargado. Su contenido permanece en el juego hasta que reinicies. |
Dos líneas comparten una palabra a propósito: Requiere otro mod Es el mismo problema para un jugador, ya sea que falte el paquete que necesita o tenga la versión incorrecta, y la línea a continuación dice cuál. Y cuando dos paquetes reclaman el mismo registro, el que tiene el load_order más alto escribe el último y gana, pero una adquisición que nadie declaró es un error, no una nota. Se informan ambas líneas, y la línea del perdedor nombra al ganador, y el ganador aún se calcula en lugar de dejarse al azar: un rechazo no tiene por qué ser también un lanzamiento de moneda. Cuando dos mods quieren lo mismo explica cómo declarar uno a propósito.
"Subido" todavía no significa que puedas verlo en el mundo. Para eso, lee los conteos debajo de la línea y Ahora encuéntralo en el juego te indica dónde aparece cada tipo de cosa.
Los recuentos siempre suman. Se aplican camas, se rechazan más, se reemplazan más por otro mod, se esperan más sus propias condiciones, y las dos últimas son nominadas en lugar de quedarse en un vacío. Un registro que otro paquete escribe en último lugar no se rechaza, porque no tiene nada de malo, y ni siquiera se aplica, porque eso no es lo que guardó el juego. Es la diferencia entre leer una línea y pasar una tarde buscando un error en un archivo que no tiene ninguno. Mostrar detalles indica qué registro y qué paquete lo tiene ahora.
Un número está al lado de esa suma en lugar de dentro: archivos que nadie ha leído. Un archivo cuya familia no está en content_types nunca se ha abierto, por lo que no hay ningún registro para contar y no hay forma de saber cuántos hay en él. Es un recuento de archivos, no de registros, y es exactamente por eso que no puede ser un sexto término: la suma comienza desde leer, y estos nunca han sido leídos.
Antes de pedir ayuda a alguien
Abra Mod y presione Copiar informe. Pega todo en tu mensaje y luego di lo que esperabas.
Texto simple, listo para un foro, un mensaje de Discord o un informe de error: la compilación en la que estás, la carpeta de mods, cada paquete con su versión, su orden de carga y estado, el motivo de cada rechazo, los recuentos para cada tipo de contenido y qué paquete ganó cada batalla.
the report the Mods screen copies
Bonemark mod report
game build: 0.0.0-dev
mods folder: C:/Users/you/AppData/Roaming/Godot/app_userdata/Bonemark/mods
packages: 2 found, 1 loaded
PACKAGES
northern_reach v0.1.0 order 100 active
goods: 12 read, 12 applied, 0 rejected
winter_roads unreadable manifest
- game_version must not be empty
CONTENT (1 families: 12 read, 12 applied, 0 rejected)
goods: 12 read, 12 applied, 0 rejectedNueve de cada diez veces la respuesta está en el bloque y nadie tiene que hacerte una sola pregunta primero. No lee nada fuera de la carpeta de mods, no cambia nada y no contiene información personal.
Está en inglés incluso cuando juegas en otro idioma. Esto es intencional: es posible que la persona que lo ayuda no lea el suyo, y todos los datos que contiene (identificaciones, versiones, recuentos) siguen siendo los mismos en todos los idiomas.
quitar uno
Elimina su carpeta y reinicia. La desinstalación está toda aquí.
Nada tuyo se elimina junto con él. Un guardado mantiene los identificadores que ya no puede resolver, los marca y devuelve cosas si se reinstala el paquete. Una sesión que no puede entender una partida guardada ni siquiera la sobrescribe: el archivo original permanece exactamente como estaba y es la diferencia entre una tarde perdida y un juego perdido. Guardados es el informe completo.
Si el juego deja de ejecutarse después de instalar algo, la salida no necesita el juego. Abre la carpeta de mods y quita lo último que agregaste. Los paquetes solo se pueden leer desde esa carpeta, por lo que una carpeta que no está ahí es un paquete que no se puede cargar y el siguiente arranque es el mismo que antes. No necesita un menú que funcione, una consola o un inicio para hacer esto.
Incluso el juego lo intenta por sí solo: Si el juego no comienza es un número limitado de intentos y luego regresa sin ningún paquete cargado, pero ese es el cinturón, y mover la carpeta son los tirantes.
Comienza aquí
Lo que puedes construir hoy
Ahora, sin pedir permiso a nadie: bienes y comerciantes, objetos, personas y sus posiciones, edificios y sus servicios, lugares del mapa, conversaciones, escenas, planes de misión, mapas dibujados en Tiled, imágenes y color, y todas sus palabras en siete idiomas. Los archivos de audio y fuentes se comprueban y se leen, pero sus superficies de paquete todavía no los consumen; la tabla de estados lo dice claramente en vez de llamarlos listos. Todas las familias son la lista medida, y su estado sale de la compilación, no de una promesa.
Todavía no, y Lo que aún no puedes hacer explica cada caso: la familia quests, audio de paquete, fuentes de paquete, conversiones totales empaquetadas y un paquete que sea una función en lugar de contenido.
Nunca, debido a la elección del proyecto: código. Sin scripts, sin escenas, sin archivos de recursos, nada para que se ejecute el juego. Esto es lo que hace que sea seguro descargar el mod de un extraño, y no es una fase por la que esté pasando el proyecto. Lo que un mod nunca puede hacer.
Tiempo para lo primero que puedes ver en el juego: Aproximadamente diez minutos, la mayor parte dedicados a buscar la carpeta. Un mod en diez minutos está completo y la espada al final es real.
Lo que no puedes hacer todavía y por qué
Está escrito aquí, cerca del principio, en vez de dejarlo para descubrirlo al final. Esto es lo que la compilación valida sin ponerlo todavía en una superficie de paquete para el jugador, además de lo que no es contenido de paquete.
| Qué | Por qué no | cambiará |
|---|---|---|
La familia quests | Se reconoce y verifica y no hay ningún asignador de tiempo de ejecución detrás de él, por lo que un paquete dirigido a él pasa por alto todas las comprobaciones y no instala nada. En su lugar, escribe Tus misiones: quest_plans es una familia viva y eso es lo que realmente dice el juego. | Sí, cuando el mapeador es público. |
| Audio de paquete | Los descriptores y archivos de audio se validan y se leen, pero ninguna superficie en ejecución consume todavía una señal de audio del paquete; un mod puede incluir sonido que permanezca en silencio. | Sí |
| Fuentes de paquete | Los descriptores de fuentes y la cobertura de idiomas se validan, pero ningún tema en ejecución consume todavía una fuente del paquete. | Sí |
| Un paquete de conversión total | La construcción comprende el manifiesto y trae consigo el accesorio Ashen Reach. Lo que falta es el flujo de trabajo empaquetado para los creadores, no el mecanismo. Una conversión total. | Sí |
| Un paquete que es una característica | Decidido en su totalidad y ninguna familia lo lleva, por lo que ningún cartel puede pedirlo. Cada familia lo enumera entre las cosas que aún no tienen una carpeta. | Sí |
| Lo que sea que se haga | No vendrá una capa de secuencias de comandos. El manifiesto lleva un tipo de paquete que envía comportamiento, lo único que podría autorizar su ejecución lo rechaza, no hay ningún sandbox detrás y un paquete que lo declara hoy es rechazado. Lo que un mod nunca puede hacer. | No |
Una mecánica que el juego nunca ha tenido es la cuarta fila con otro sombrero. La espada que golpea más fuerte es un número y es tuya; un arma que dispara un rayo necesita las reglas del rayo, y las reglas son códigos que alguien escribe y prueba.
¿Qué es un mod?
Una carpeta de archivos de texto. No escribes código. Escribes listas de cosas que quieres en el juego y el juego las lee cuando comienza.
| Palabra | Qué significa |
|---|---|
| Paquete | Tu mod. Una carpeta con tu nombre. |
| Manifiesto | mod.json, en la parte superior de esa carpeta. ¿Quién eres, qué traes? |
| Registro | Una cosa que añades. Una espada es un récord. |
| Familia | Algo así. Espadas, cascos y pan son todos items. Cada familia tiene su propia carpeta. |
| Identificación | your_package:the_thing: por ejemplo, northern_reach:frost_blade. |
La única regla de la que se sigue todo lo demás: puedes agregar y cambiar datos. No puedes hacer que el juego ejecute código. Eso es lo que hace que descargar un mod sea seguro: lo peor que puede hacer un mod de un extraño es ponerte una espada tonta.
34 familias están listas para usar hoy, entre ellas items, buildings, pois, npc_definitions, vendor_inventories, quest_plans, caravans y perks. Todas las familias forman la tabla completa con lo que hace cada una; Las familias, una por una ofrece sus campos y un registro para copiar.
Elige tu camino
Esta es la tabla de contenidos de toda la guía, donde se escribe cada tema, ya sea que lo estés desarrollando hoy o no. En la parte superior de la Parte 3 hay un segundo índice más corto: son los seis tutoriales, en el orden en que se complementan entre sí. Si estás aquí para hacer algo y no para buscar algo, ve directamente allí.
| Quieres | Ir a |
|---|---|
| Construyendo algo de principio a fin | Empieza desde lo que quieres hacer — los seis tutoriales, solo un paquete |
| Sube un archivo en diez minutos | Un mod en diez minutos |
| Buscar campos para una familia y un ejemplo | Las familias, una a una |
| Mira todo lo que puedes hacer | Cada familia |
| Cambiar algo que ya trae consigo el juego | Cambiar lo que ya tiene el juego |
| Añade tu propio arte, sonido, letras o color. | Imágenes, sonido, letras, color |
| Dibujar un lugar en Tiled | Tus mapas |
| Escribe una misión | Tus misiones |
| Entiende por qué no apareció nada. | No apareció nada |
| Busque un código de error | Cada código de diagnóstico |
| Sepa lo que un mod nunca puede hacer | Lo que un mod nunca puede hacer |
| No rompas la salvación de alguien | Guardados |
| Ponlo donde la gente pueda llevarlo. | Compártelo |
O lo que tienes en mente. Esta guía está organizada en el orden en que se realiza el trabajo (manifiesto, luego validación, luego contenido, luego informe), que es el orden que elegiría alguien que ya conoce el sistema. Los que no lo conocen están pensando quiero agregar un comerciante, y buscan la palabra comerciante:
| estas agregando | Las familias que lo hacen | donde estan escritos |
|---|---|---|
| Comercio y bienes | goods, vendor_inventories, caravans, recipes | Las cosas, el comercio y los números detrás de una pelea |
| Cosas que trae un jugador consigo | items, combat_balance | Las cosas, el comercio y los números detrás de una pelea |
| Gente | npc_definitions, mercenary_templates, noble_houses, relationships, perks, enemy_archetypes, enemy_variants, group_archetypes | Personas, casas y lo que pueden hacer |
| Lugares y edificios | buildings, pois, maps, world_generation | El mundo y los lugares en él |
| Palabras que lee un jugador | locales, dialogue, scenes, lore, mr_lines, quest_plans, quest_metadata, progress | Historia, misiones y las palabras que lee un jugador |
| Cómo se ve y cómo suena. | images, audio, fonts, themes, effects, presentation_bindings, screens | Cómo se ve y suena todo |
| Comandos y dificultades | input_bindings, settings, adaptive | Lo que controla el jugador y lo que lo mira |
Qué necesitas
| El juego | Necesario | Sin Godot, sin compilador, sin pasos de compilación. |
| Un editor de texto que entiende JSON | Necesario | VS Code, Sublime, Notepad++: todo gratis. El Bloc de notas de Windows funciona y no te ayudará. |
| Un editor de pixel art | Sólo por tu arte | Aseprite (~20 €), o gratis: LibreSprite, Piskel, Krita, GIMP. |
| Un editor de audio | Sólo por tu sonido | Audacity. Efectos cortos surgidos de la nada: sfxr, ChipTone. |
| En mosaico | Solo para tus mapas | Gratis. Exportar a .tmj. |
Un editor que colorea JSON te muestra una coma faltante mientras todavía lo estás mirando, en lugar de que el juego te diga más tarde que el archivo era ilegible.
Python y la consola son opcionales. El juego basta: coloca el paquete, reinicia y abre Mods, que indica cada registro rechazado y el motivo. El checkout para autores es público. Quien quiera iterar más rápido o automatizar publicaciones puede clonar el checkout público de Bonemark y ejecutar las herramientas sin conexión en Herramientas sin conexión; los jugadores que instalan un paquete publicado no necesitan Python ni Godot. Ese mismo checkout público contiene el validador y las declaraciones del runtime, por lo que ambas secciones describen una sola cadena de herramientas. Las herramientas usan las mismas declaraciones que el juego — los esquemas de registros y el límite de seguridad tienen una única fuente —, así que responden antes, nunca de otra forma. Una consola de depuración ayuda a inspeccionar un paquete cargado, pero no hace falta para escribir uno.
Crear one
Comienza con lo que quieres hacer
Todo lo que está debajo de esta línea está organizado en el orden en que se realiza el trabajo: cartel, luego archivos, luego familias, luego informes. Es el orden correcto para buscar algo y el orden incorrecto para empezar, porque nadie empieza con un manifiesto. Comienza con Quiero un comerciante.
Luego: elige la frase que se parezca a lo que estás intentando hacer.
| Quieres | Ir a | Cuánto tiempo se tarda |
|---|---|---|
| Añade algo para comprar y vender. | [Un bien para vender](#un bien para vender) | 15 minutos |
| Añade algo que un jugador lleve consigo. | Un artículo para llevar | 10 minutos, después del de arriba |
| Añade una persona que lo venda | Un comerciante que lo posee | 30 minutos |
| Agregar una puerta en un asentamiento | El servicio de un edificio | 20 minutos |
| Añadir un lugar en el mapa mundial | Un lugar en el mapa | 20 minutos |
| Cambiar algo que el juego ya tiene | Cambiar lo que ya existe | 15 minutos |
| Dibuja un mapa, escribe una misión, trae arte. | Tus mapas, Tus misiones, Imágenes, sonido, letras, color | más tiempo, y los tres son familias vivas |
Traiga la familia quests, una conversión total empaquetada o un paquete que sea una característica | Aún no. [Lo que no puedes hacer todavía y por qué](#lo-que-no-puedes-hacer-todavía-y-por qué) da el motivo de cada uno y dice cuáles cambiarán. | — |
| Añade una regla que el juego nunca tuvo. | Nada aquí lo hace y nada lo hará. Lo que un mod nunca puede hacer dice por qué, en un párrafo. | — |
Los seis tutoriales son un solo paquete, construido pieza por pieza: una vela de cera de abejas, el paquete que el jugador lleva consigo, el fabricante de cera que lo vende, la puerta de su tienda, el hoyo detrás de la curtiduría de donde proviene el sebo y, finalmente, una modificación de la vela que ya tenía el juego. Hazlos en orden y termina con un mod que alguien podría descargar. Consiga uno en el medio y funcionará por sí solo.
¿Dónde están los números del juego?
Cada tutorial aquí valora algo nuevo comparándolo con algo que el juego ya vende, porque un número sin nada al lado es una suposición, y una suposición en una economía que comercia entre ciudades no permanece donde la pones.
No puedes abrir los archivos del juego. Sus registros son activos de Godot dentro de la compilación empaquetada: un formato diferente al JSON que escribes, con category = 1 donde tu archivo dice "MANUFACTURED". No hay ninguna carpeta desde la que copiar y descomprimir una no es un flujo de trabajo que nadie deba documentar.
No lo necesitas. El catálogo publica el contenido del juego, generado a partir de esos mismos registros en cada compilación: 270 elementos con su categoría, peso, valor de la moneda y tamaño de la pila, 49 armas, 42 piezas de armadura, 37 ubicaciones. Es la referencia a la que está anclada esta guía, no puede apartarse del juego y el nombre del campo está impreso al lado de cada línea.
Una docena de valores que debes conocer antes de ponerle precio a algo:
| El juego ya se esta vendiendo. | monedas | Y |
|---|---|---|
| Arcilla, piedra, cañas | 1 | el suelo. Cavar o cortar, no hay trabajo en el interior |
| grano, madera | 2 | |
| Vela | 3 | una tarde ligera |
| Lana, pescado, uvas. | 4 | |
| Pan | 6 | la comida de un dia |
| Sal, miel, cuerda. | 8 | |
| Tela (pieza) | 10 | tejido de 2 lana y 1 caña |
| Hierro refinado, pescado salado. | 12 | |
| Pimienta negra | 14 | una importación, y puedes sentirlo |
| cuero, queso | 15 | |
| Vino | 25 | |
| Armas de una mano | 50–300 | la banda, ni un solo valor |
| Armas de dos manos | 150–600 | |
| plato pesado | 500–1500 | El techo de toda la economía. |
Si tu nuevo objeto cuesta más que una armadura de placas, algo salió mal y el juego no te lo dirá: silenciosamente se convertirá en el cargamento más rentable del mundo y cada caravana lo transportará.
Una mercancía para vender
Tendrás un producto al que la economía sabe cómo ponerle precio, vinculado a la vela que el juego ya vende, listo para que un comerciante lo tenga.
Captura de pantalla: Aún no tomada. Este espacio permanece vacío hasta que haya uno real: un dibujo de cómo podría verse sería lo único de la página que no sea real.
Lea primero: Qué es un mod · Un mod en diez minutos · Nombres e ids
Copia de: la carpeta llamada chandlery, que ya está en tu carpeta de mods. El juego lo coloca ahí la primera vez que se inicia, lo apaga y es el resultado final de estos seis tutoriales: cada registro a continuación está ahí. También es el paquete que la línea de prueba del repositorio hace girar contra el cargador, por lo que no hay ningún registro aquí que el juego rechazaría. Actívelo para verlo funcionar, o copie la carpeta, cámbiele el nombre y hágala suya.
Dónde van los archivos:
where the files go
mods
└ chandlery
├ mod.json
└ content
└ economy
└ goods
└ goods.jsonEmpieza con la vela que ya tiene el juego. Se llama candle, cuesta 3, pesa 0.5, es MANUFACTURED y PRESERVED, y está hecha por el boticario. El tuyo es lo mismo hecho con cera mejor, así que guarda todas esas respuestas y cambia dos.
Antes de mod.json:
mod.json
{
"id": "chandlery",
"name": "The Chandlery",
"version": "0.1.0",
"game_version": "0.0.0-dev",
"dependencies": [],
"load_order": 100,
"content_types": ["goods"],
"overrides": [],
"canon_safe": true
}Entonces content/economy/goods/goods.json:
a goods record
[
{
"id": "chandlery:beeswax_candle",
"display_name": "Beeswax Candle",
"category": "MANUFACTURED",
"decay_tier": "PRESERVED",
"base_price": 9,
"weight": 0.4,
"production_class": "chandler",
"daily_consumption_class": "household",
"tags": ["light", "household"]
}
]| Campo | ¿Por qué este valor? |
|---|---|
id | El nombre de su paquete, dos puntos y luego su palabra. Todo lo que no tenga su espacio de nombres al frente se rechaza, por lo que no puede tomar la identificación de otra persona por accidente. |
display_name | Lo que lee un jugador. Ningún artículo: «Vela de cera de abejas», nunca «Una vela de cera de abejas»: el artículo viene dado por la frase que lo rodea y el artículo depende del idioma. Palabras que lee un jugador. |
category | MANUFACTURED, porque alguien lo hace. Los cinco son materia prima, artefacto, consumibles, munición y equipo, y el que elijas decide qué edificios de producción y caravanas se ven afectados. |
decay_tier | PRESERVED: 90 días, como la vela del juego. La cera se conserva; no se conserva para siempre. PERISHABLE tiene 7 días y ETERNAL nunca se pudre. |
base_price | 9. La vela simple en el juego es 3 y un frasco de miel es 8. La cera de abejas proviene de las mismas colmenas que la miel y arde sin olor a grasa derretida, por lo que se encuentra justo encima de la miel y es aproximadamente tres veces mejor que una vela de sebo. No es una importación: la pimienta negra tiene 14 años y ha cruzado un mar. |
weight | 0,4, un poco por debajo del 0,5 de la vela simple. El peso es lo que puede transportar una caravana, por lo que un producto que no pesa nada y se vende caro es un error que se escribe a propósito. |
production_class | ¿Qué profesión hace? chandler es el que utiliza el paquete de referencia. |
daily_consumption_class | Quien lo consume. household significa que las ciudades lo consumen constantemente, y eso es lo que mantiene abastecido a un comerciante. |
tags | Palabras libres. Otros registros y sus archivos posteriores pueden buscar en ellos. |
Listo, ahora encuéntralo en el juego. Reinicia, abre Mod y la línea debajo de la tuya dice 1 entry added. Es todo lo que hace una mercancía por sí sola: tiene un precio, es comercializable y no está en el mostrador de nadie, porque nadie lo tiene todavía. No es un fracaso y es lo que confunde a todos alguna vez. Continúe con Un comerciante que lo almacena.
Si no se muestra: No apareció nada tiene los seis motivos en orden. El más común, con diferencia, es content_types: una familia que falta en esa línea significa que la carpeta nunca se abre, independientemente de lo que contenga. Luego Antes de pedir ayuda a alguien, que es un solo botón.
Un objeto para llevar
Tendrás lo que un jugador recoge, apila en su mochila y revende, junto con la mercancía que acabas de escribir.
Captura de pantalla: Aún no tomada.
Lea primero: Un bien para vender · Nombres e identificadores
Copiar de: chandlery/content/inventory/items/items.json a tu carpeta de mods.
Dónde van los archivos:
where the files go
mods
└ chandlery
├ mod.json
└ content
├ economy
│ └ goods
│ └ goods.json
└ inventory
└ items
└ items.jsonUna mercancía y un objeto son dos mitades de una misma cosa. La mercancía es el punto de vista de la economía: qué produce una ciudad, qué transporta una caravana, cuánto vale. El objeto es el punto de vista del jugador: qué cabe en la mochila, qué se apila, qué se exhibe en una tienda. El trigo tiene una mercancía y no un objeto, porque nadie lleva consigo un saco de trigo. Las velas tienen ambos.
Agregue "items" a content_types en mod.json, luego escriba content/inventory/items/items.json:
a items record
[
{
"id": "chandlery:beeswax_candle_bundle",
"display_name": "Bundle of Beeswax Candles",
"category": "MATERIAL",
"rarity": "COMMON",
"weight": 0.4,
"max_stack": 20,
"base_value": 10,
"sellable": true,
"tags": ["light", "household"]
}
]| Campo | ¿Por qué este valor? |
|---|---|
id | Su DNI, no el de la mercancía. Son registros diferentes en familias diferentes y nada los obliga a coincidir: emparejarlos es su trabajo y la línea comercial a continuación es donde ocurre el emparejamiento. |
category | MATERIAL, que es la vela del juego. No CONSUMABLE: no comes nada. |
rarity | COMMON. Rareza es lo que leen las mesas de botín y las tiendas cuando ruedan; sucede algo común. |
weight | 0,4, como los productos. Cuando los dos no están de acuerdo, la mochila del jugador y la caravana no están de acuerdo en el mismo artículo. |
max_stack | 20, como pan caliente y como el paquete de referencia. Veinte es la pila normal del juego para las cosas pequeñas que llevas encima; 1 es para algo único. |
base_value | 10 versus 9 para los productos. Un paquete conlleva una pequeña prima sobre el precio al por mayor: el paquete de sebo de referencia es 4 versus 3 productos básicos, y esta es la misma forma un paso arriba. |
sellable | Es cierto, de lo contrario el comerciante no podrá comprárselo. |
Listo, ahora encuéntralo en el juego. Un elemento que nadie entrega se carga y se puede acceder a él desde la nada. En una compilación de depuración, item chandlery:beeswax_candle_bundle coloca uno en tu mochila de inmediato y es la prueba más rápida de que está cargado, pero ese comando no existe en el juego que la gente descarga, por lo que es un atajo para ti y nunca la respuesta para un jugador. La verdadera respuesta es el siguiente tutorial.
Si no se muestra: No apareció nada, entonces [Antes de pedir ayuda a alguien](#antes de-pedir ayuda a alguien).
Un comerciante que lo posee
Tendrás una mujer con un nombre parada en Old Seat con un mostrador, suministros que se reponen cada dos días y tus velas en el mostrador.
Captura de pantalla: Aún no tomada.
Lee primero: Un artículo para llevar · Ahora encuéntralo en el juego
Copia de: chandlery/content/narrative/npcs/npcs.json y chandlery/content/world/vendor_inventories/vendors.json.
Dónde van los archivos:
where the files go
mods
└ chandlery
├ mod.json
└ content
├ economy
│ └ goods
├ inventory
│ └ items
├ narrative
│ └ npcs
│ └ npcs.json
└ world
└ vendor_inventories
└ vendors.jsonEste es aquel en el que dos familias tienen que ponerse de acuerdo. La persona lleva la identificación del banco, el banco lleva la identificación de la persona y cada fila del banco lleva la identificación de un objeto. Tres identificadores, y cada uno debe escribirse exactamente como lo escribió en el otro archivo. Es el error que cuesta una noche, y la pantalla Mods lo nombra: una línea que apunta a una identificación que nadie proporciona aparece como requiere otro mod que no está instalado.
Agregue "npc_definitions" y "vendor_inventories" a content_types.
a npc_definitions record
[
{
"id": "chandlery:hesta",
"display_name": "Hesta the Chandler",
"title": "Candle Seller",
"short_bio": "She renders fat behind the tannery and sells what burns longest.",
"voice_tone": "brisk",
"faction": "NONE",
"role": "NONE",
"settlement_id": "old_seat",
"is_vendor": true,
"vendor_inventory_id": "chandlery:candle_stall",
"price_multiplier": 1.0,
"personality_tags": ["brisk", "practical"],
"offers_quest_ids": []
}
]a vendor_inventories record
[
{
"id": "chandlery:candle_stall",
"display_name": "Chandler's Stall",
"npc_id": "chandlery:hesta",
"global_price_multiplier": 1.0,
"buyback_rate": 0.35,
"entries": [
{
"item_id": "chandlery:beeswax_candle_bundle",
"kind": "misc",
"daily_stock": 6,
"price_multiplier": 1.0,
"restock_days": 2,
"min_standing": 0
}
]
}
]| Campo | ¿Por qué este valor? |
|---|---|
settlement_id | Usa un id de asentamiento creado por los autores. Los ids de asentamiento son creados por los autores y estables: Durnwall, Thorngate, Valdmere, Grentham y las doce aldeas pueden recibir nombre. La seed cambia el terreno y los biomas a su alrededor, la escasez del año y la organización política, no el id. |
is_vendor + vendor_inventory_id | Juntos transforman a una persona en una tienda. Uno sin el otro es una persona que no puede vender o un mostrador que nadie cuida. |
price_multiplier | 1.0 — pregunta cuánto valen las cosas. Arriba de 1 hay un lugar que sabe que no tienes opciones; los comerciantes en el juego están en 1.0 si no hay ningún motivo en el mapa. |
buyback_rate | 0,35: Paga alrededor de un tercio del valor de lo que le vendes. Es el número que más escuchan los jugadores y es el que utiliza el distribuidor de paquetes de referencia. |
daily_stock | 6. Cuántos tiene cuando el banco repone. Seis es la cifra del paquete de referencia para un artículo doméstico barato; uno es para algo que una ciudad ve dos veces al año. |
restock_days | 2, por lo que se repone cada dos días, y no el día en que instalas el mod. Por eso al principio un nuevo comerciante parece vacío. En una compilación de depuración, day avanza un día. |
min_standing | 0: Cualquiera puede comprar. Por encima de cero están las acciones que mantiene para las personas que le agradan. |
kind | ¿En qué tipo de mostrador se encuentra? misc para artículos para el hogar. Los otros son weapon, armor, shield, consumable y ammo. |
Listo, ahora encuéntralo en el juego. Reinicia, viaja a Old Seat, encuentra a Hesta, abre la pantalla de intercambio. Si el banco está vacío, aún no se ha repuesto: eso es restock_days, no es un error. La cadena se puede romper de tres maneras y las tres están en la pantalla Mod: los bienes que nadie tiene, el contador que apunta a una identificación de artículo que no existe, la persona que señala una identificación de contador que no existe.
Ella también puede hablar. Una dialogue_graph cuyo speaker es su identificación hace bromas cuando un jugador hace clic en ellas, y tu paquete no tiene que redefinir nada que el juego ya tenga para obtenerlas; consulta Tus conversaciones. Un archivo locales te ofrece todo esto en siete idiomas.
Si no aparece nada: primero verifique los tres identificadores entre sí, luego No apareció nada, luego [Antes de pedir ayuda a alguien](#antes de-pedir ayuda a alguien).
El servicio de un edificio.
Tendrás una puerta en un asentamiento con tu etiqueta y color, que se abre a un interior que el juego ya tiene.
Captura de pantalla: Aún no tomada.
Lea primero: Un comerciante que lo guarda · [Lo que un mod nunca puede hacer](#lo-que-un mod-nunca-puede-hacer)
Copia de: chandlery/content/world/buildings/buildings.json.
Dónde van los archivos:
where the files go
mods
└ chandlery
└ content
└ world
└ buildings
└ buildings.jsonEstás recombinando, no construyendo. Un registro buildings agrega un nuevo servicio con una etiqueta, color de puerto y función de rutina, y puede reutilizar una extensión que el juego ya tiene al nombrarla. No se puede traer una extensión. Una extensión es una escena, una escena es código y un paquete que nombra una ruta res:// o .tscn se rechaza incluso antes de que se lea este registro. No es un vacío esperando a ser llenado: es la línea que hace que sea seguro instalar el mod de un extraño.
a buildings record
[
{
"id": "chandlery:chandlery",
"label": "Chandlery",
"role": "merchant",
"color": { "r": 0.44, "g": 0.38, "b": 0.24 },
"interior_service": "shop"
}
]| Campo | ¿Por qué este valor? |
|---|---|
label | Las palabras en la puerta. Si lo omites, el juego escribe tu identificación en mayúscula y se lee como una identificación. |
role | ¿Qué hace la gente adentro todo el día? merchant pone la rutina de un comerciante detrás de la puerta. El papel es el vocabulario del juego, no el tuyo: un extraño irrumpe y actúa como si nada en particular. |
color | Cera de abejas marrón, 0.44 / 0.38 / 0.24. Cada canal varía de 0 a 1 y también funciona una cadena hexadecimal HTML. Elija algo que se ajuste al tamaño en el que está dibujada una puerta: Art That Fits. |
interior_service | shop: el interior que el juego ya diseña para una tienda. El truco está aquí: obtienes una habitación real y amueblada sin tener que traerla. |
Listo, ahora encuéntralo en el juego. Reinicia e ingresa un acuerdo que tenga tu servicio. Un registro sin settlement se carga y no se coloca en ninguna parte, lo cual es idéntico a un registro fallido: la pantalla Mod dirá 1 entry added y no encontrará nada. Lea la línea antes de buscar la puerta.
Si no aparece: No apareció nada · Antes de pedir ayuda a alguien.
Un lugar en el mapa
Tendrás un lugar en el mapa mundial con el que un jugador puede tropezar, con una descripción del mismo y su efecto en el estado de ánimo del grupo.
Captura de pantalla: Aún no tomada.
Lea primero: El servicio de construcción · Ahora encuéntrelo en el juego
Copia de: chandlery/content/world/pois/pois.json.
Dónde van los archivos:
where the files go
mods
└ chandlery
└ content
└ world
└ pois
└ pois.jsonLas coordenadas son absolutas y el mundo se genera alrededor de lugares creados por los autores. El mapa mide 61 440 × 34 560 píxeles del mundo y Old Seat está exactamente en el centro, (30720, 17280), en todas las partidas. Las ciudades y aldeas creadas por los autores conservan sus nombres y posiciones. La seed cambia el terreno y los biomas a su alrededor, la escasez del año, la organización política y qué caminos merecen la pena. Así, un punto sigue siendo real y estable; lo que queda al lado cambia en cada partida. Dos formas honestas de usarlo: anclar un punto de interés cerca de un asentamiento creado por los autores, para que el jugador pase por allí; o elegir el vacío, porque un foso de renderizado que nadie ha visitado en años debe estar en ninguna parte en particular.
a pois record
[
{
"id": "chandlery:tallow_pit",
"kind": "RUINS",
"display_name": "The Tallow Pit",
"description": "A rendering pit behind the tannery. The smell reaches the road.",
"world_position": { "x": 5400.0, "y": 3000.0 },
"discovery_radius": 2.0,
"one_time_loot": false,
"morale_modifier": -1,
"awareness_modifier": 0.0
}
]| Campo | ¿Por qué este valor? |
|---|---|
kind | RUINS: qué dibuja el mapa y qué cree el juego que es. |
world_position | (5400, 3000), extremo noroeste del centro: vacío deliberado, segundo de los dos usos honestos anteriores. Muévalo a unos pocos miles de píxeles de (30720, 17280) y se convertirá en un lugar que los jugadores realmente encontrarán. |
discovery_radius | 2.0. Qué tan reñida debe pasar la fiesta. Lo suficientemente grande como para encontrarlo a lo largo de una carretera, lo suficientemente pequeño como para no anunciarlo de un extremo a otro de una provincia. |
morale_modifier | −1. Es un pozo de grasa derretida. El número es pequeño a propósito: un lugar es un lugar, no un evento, y −1 es un estado de ánimo, no un castigo. |
awareness_modifier | 0.0 — no ayuda a verlo. Deje un número en cero en lugar de eliminar el campo, cuando el cero es una decisión. |
one_time_loot | Falso: no hay nada que tomar, por lo tanto nada que tomar sólo una vez. |
Listo, ahora encuéntralo en el juego. Adelante. No hay un comando de teletransporte, ni en una versión de depuración ni en el exterior, así que elige las coordenadas hasta donde estés dispuesto a caminar mientras lo intentas.
Si no aparece: Probablemente te hayas quedado sin discovery_radius, o la ubicación está en algún lugar donde la semilla coincidente puso un océano. No apareció nada.
Cambiando lo que ya está ahí
Habrás cambiado un registro que el juego trajo consigo y lo habrás declarado, de modo que el cambio sea visible para el jugador y todos los demás mods.
Captura de pantalla: Aún no tomada.
Lee primero: Cambiar lo que ya tiene el juego · Cuando dos mods quieren lo mismo
Copia de: chandlery/content/economy/goods/goods.json, que agrega un registro y corrige uno del juego en el mismo archivo.
Adónde van los archivos: Ningún lugar nuevo. Un cambio en algo que el juego ya tiene se encuentra en la misma carpeta familiar en la que se encuentran tus registros: el archivo dice qué registro pretende y qué le está haciendo.
where the files go
mods
└ chandlery
├ mod.json the change is declared here
└ content
└ economy
└ goods
└ goods.json your record and the patch, in one fileDos reglas antes del archivo. Un cambio en el registro de otra persona debe nombrarse en overrides dentro de mod.json; un registro que llega a una identificación que no declaraste se rechaza, por lo que nada puede reescribir de manera encubierta algo que el jugador no aceptó. Y patch, que cambia un campo y deja el resto solo, requiere "manifest_version": 2.
mod.json
{
"id": "chandlery",
"name": "The Chandlery",
"version": "0.1.0",
"game_version": "0.0.0-dev",
"manifest_version": 2,
"load_order": 100,
"content_types": ["goods", "items", "npc_definitions", "vendor_inventories", "buildings", "pois"],
"overrides": ["candle"],
"canon_safe": true
}a goods record
[
{
"op": "patch",
"id": "candle",
"changes": [
{ "op": "set", "field": "base_price", "value": 4 },
{ "op": "append_unique", "field": "tags", "value": "chandlery_touched" }
]
}
]| Elección | Por qué |
|---|---|
patch, no replace | replace no hereda nada: tendrías que reescribir el peso de la vela, su grado de descomposición, el objeto conectado y la clase de producción, y el día que el juego le diera a las velas un nuevo campo, tu copia sería la única vela en el mundo sin él. |
| 3 → 4 | Una moneda, y la razón es el mod en sí: la tuya es una ciudad que derrite la cera correctamente, por lo que una vela normal aquí vale un poco más. Pasar de 3 a 30 no sería un cambio de vela, sería un cambio de prioridad de carga de cada caravana. |
append_unique a tags | Lo único que pueden hacer dos mods sin entrar en conflicto. Si ambos ponen en cola la misma etiqueta, no hay choque y no se duplica. |
| Nombra un campo, nunca una posición | tags.0 es rechazado. La tercera etiqueta de hoy es la segunda etiqueta después de cargar el paquete de otra persona. |
Listo, ahora encuéntralo en el juego. La pantalla Mod nombra el registro que has adquirido. La pantalla del otro autor también hace esto, si lo hay: cuando dos paquetes escriben la misma identificación, la línea del perdedor ahora dice reemplazado: vela — 'chandlery' lo escribe al final, en lugar de mostrar silenciosamente una entrada menos de la que escribió. Quien tenga el load_order más alto escribe el último y gana.
Ganar no es lo mismo que tener permiso. Dos paquetes tomando un registro sin nombrar al otro en supersedes se reportan como undeclared_collision y la composición no está bien: el validador fuera de línea dice lo mismo y rechaza:
typed into the debug console
ERROR: conflict on goods:candle: ['early', 'late'] each supply the whole record
and none declares the others under `supersedes`El ganador todavía está calculado, porque un rechazo no tiene por qué ser también un lanzamiento de moneda, sino que dos autores que lo deseaban tienen que decirlo. Cuando dos mods quieren lo mismo es esa conversación.
Si no aparece: la causa habitual es overrides — el id debe estar en esa lista, escrito exactamente, de lo contrario el registro se rechaza en lugar de aplicarse. Cuando dos mods quieren lo mismo · [No apareció nada](#no apareció nada).
Un mod en diez minutos
1. Crea una carpeta en tu carpeta de mods, con el nombre en minúsculas y guiones bajos: northern_reach. Todo sucede ahí dentro.
2. Escribe mod.json en la parte superior:
mod.json
{
"id": "northern_reach",
"name": "The Northern Reach",
"version": "0.1.0",
"game_version": "0.0.0-dev",
"dependencies": [],
"load_order": 100,
"content_types": ["items"],
"overrides": [],
"canon_safe": true
}id debe coincidir con el nombre de la carpeta. content_types enumera las familias que traes: una familia que falta en esa línea nunca se lee, sin importar lo que haya en la carpeta.
3. Crea las carpetas content/inventory/items y pon blades.json dentro:
a items record
[
{
"id": "northern_reach:frost_blade",
"display_name_key": "northern_reach.item.frost_blade.name",
"display_name": "Frost Blade",
"category": "weapon",
"base_value": 240,
"weight": 3
}
]Los corchetes son una lista: agrega tantas espadas como quieras, separadas por comas. Se lee cada archivo .json en una carpeta familiar, así que divídalos como desee.
240 no es un número elegido para impresionar. En este juego, las armas de una mano varían de 50 a 300, por lo que una espada helada a 240 es una espada cara y no una espada legendaria, y un jugador puede permitírsela en el momento en que pueda permitirse las buenas que el herrero ya vende. Dónde están los números del juego es la tabla que hay que mirar antes de elegir cualquier número; un precio sin nada al lado es una hipótesis, y en una economía que comercia entre ciudades una hipótesis no permanece donde la pones.
4. Inicia el juego y abre Mods desde el menú principal. Su paquete obtiene exactamente un estado y ¿Se cargó? tiene los seis.
5. Lea la línea a continuación para saber qué se ha leído, aplicado y rechazado, con el motivo de cada rechazo. Mostrar detalles tiene identificadores.
6. Tu espada está en el juego. Todo lo que viene después es más de lo mismo.
Ahora encuéntralo en el juego.
El informe dice applied. Significa que el disco está cargado, y eso no es lo mismo que poder caminar delante de él. Aquí es donde toda guía se detiene y todo autor comienza a adivinar.
| ¿Qué agregaste? | donde aparece | la captura |
|---|---|---|
goods | En un comerciante, solo una línea de vendor_inventories lo solicita. Un producto que nadie posee está cargado, valorado, comercializable como sea que lo llames y no se encuentra en ningún mostrador. | Agregar mercancía es la mitad del trabajo. La otra mitad es la línea. |
vendor_inventories | El comerciante mencionado en npc_id. Cada fila lleva su propio daily_stock y su propio restock_days, por lo que una fila con restock_days: 2 se repone cada dos días y no el día en que la agregó. | Utilice day en la consola para saltarse un día en lugar de esperarlo. |
items | En todas partes algo te entrega uno: una línea de comerciante, una tabla de botín, una recompensa de misión. Existe un objeto que no otorga nada y solo se puede acceder a él con item <id> en la consola. | item northern_reach:frost_blade lo guarda en tu mochila de inmediato y es la forma más rápida de ver que está cargado. |
npc_definitions | La liquidación indicada en settlement_id, en el lugar indicado por location_morning / location_afternoon / location_evening. | Lea el siguiente párrafo sobre settlement_id antes de escribir uno. |
buildings | La liquidación indicada en settlement, sorteada con el role y el color que le diste. interior_service es lo que encuentra un jugador cuando ingresa. | Un edificio sin settlement se carga y no se coloca en ninguna parte. |
pois | En el mapa mundial en world_position, visible por discovery_radius. | Lea el párrafo sobre coordenadas a continuación. Eso es lo que a todos les importa. |
settlement_id nombra un lugar creado por los autores. Los ids de asentamiento son creados por los autores y estables: Durnwall, Thorngate, Valdmere, Grentham y las doce aldeas pueden recibir nombre. La seed cambia el terreno y los biomas a su alrededor, la escasez del año y la organización política, no el id. Si quieres que alguien encuentre sin falta a una persona, usa cualquier id de asentamiento creado por los autores y conserva su nombre en los datos de idioma de tu paquete.
Las coordenadas son absolutas y el mundo se genera alrededor de lugares creados por los autores. El mapa mide 61 440 × 34 560 píxeles del mundo y Old Seat está exactamente en el centro, (30720, 17280), en todas las partidas. Las ciudades y aldeas creadas por los autores conservan sus nombres y posiciones. La seed cambia el terreno y los biomas a su alrededor, la escasez del año, la organización política y qué caminos merecen la pena. Por eso una world_position de (6000, 2200) es un punto real y estable en el noroeste lejano del mapa, mientras que lo que queda cerca cambia en cada partida: puede ser un camino, un bosque o la nada. Dos formas honestas de usarlo:
- Aún en el centro. Un punto de interés a unos miles de píxeles de (30720, 17280) está cerca del asiento antiguo en cada juego, por lo que es un lugar que un jugador encontrará.
- Te refieres al vacío. Una ruina por la que nadie ha pasado durante cien años debe estar en cualquier lugar. Las coordenadas absolutas son exactamente las correctas para esto y la semilla decidirá qué vecinos tendrá.
Los comandos de consola que más tiempo ahorran. day [n] y hour [n] avanzan el tiempo, que es como ves un suministro sin experimentarlo. item <id> [count] y gold <amount> ponen las cosas en tus manos. flag, quest_start y faction_rep mueven el estado que una condición podría estar esperando. No existe un comando de teletransportación: para llegar a un lugar, viaja hasta allí.
mod.json, campo por campo
| Campo | Qué hace |
|---|---|
id | En el ejemplo anterior. El nombre de su paquete. Debe coincidir exactamente con la carpeta y es la palabra antes de los dos puntos en cada identificación que escriba. |
name | En el ejemplo anterior. Lo que ve un jugador. Las mayúsculas y los espacios están bien aquí. |
version | En el ejemplo anterior. Tú lo eliges. Súbelo cada vez que cambies algo. |
game_version | En el ejemplo anterior. La compilación para la que hiciste esto. |
content_types | En el ejemplo anterior. Las familias que traes. Una familia que falta en esta lista nunca se lee, sin importar lo que haya en la carpeta. |
dependencies | En el ejemplo anterior. Los paquetes que el tuyo necesita. Un nombre o un objeto con optional: true. |
load_order | En el ejemplo anterior. ¿Quién va primero cuando dos paquetes tocan lo mismo? El más bajo se carga primero. |
overrides | En el ejemplo anterior. Los ID del juego base que deseas cambiar. Una identificación, o un file.json:id cuando te refieres a la copia que crea un archivo preciso. |
canon_safe | En el ejemplo anterior. Si tu mod encaja en la historia del juego. Eres tú quien se lo dice a los jugadores, no el juego que decide. |
roots | Una carpeta familiar, cuando la desee en un lugar distinto al predeterminado en [Familias, una por una] (#las-familias-una-por-una). Quédese dentro de su paquete. |
manifest_version | ¿Qué tipo de manifiesto estás escribiendo? Las operaciones Cambiar lo que ya tiene el juego requieren 2. Esta compilación lee hasta 2. |
type | ¿Qué tipo de paquete es? El cuarto valor es el que envía comportamiento en lugar de datos, y lo único en esta compilación que dice sí a ejecutar el comportamiento dice no, por lo que un paquete que lo declara es rechazado. Está en la lista porque se decide la forma, no porque la puerta esté abierta; Lo que un mod nunca puede hacer es la lectura honesta. Uno de content, overhaul, total_conversion, feature_extension. |
capabilities | Qué paquete le pediría al huésped si alguna vez se abre el nivel superior. Un campo desconocido aquí falla al cerrarse, en lugar de ser ignorado. |
trust_tier | No confiable, que es y sigue siendo un mod descargado por un jugador. Es un invitado quien nombra al otro; nada de lo que escriba un paquete aquí lo promueve. Uno de untrusted, trusted. |
supersedes | Los paquetes que esto pretende anular. Un campo reclamado de esta manera deja de ser reportado como una colisión. Aquí también un campo desconocido no se cierra. |
fallback_policy | ¿A qué recurre un paquete cuando falta algo que anula? Uno de vanilla, none. |
campaign | La campaña que tiene una conversión. |
campaign_package | Declare que este paquete es una campaña, con su propio id, nombre y versión. Un paquete que lo contiene solo se lee mientras la campaña está en progreso, y el jugador lo elige en la pantalla Mods antes de un nuevo juego. Una conversión total. |
Una dependencia puede ser un objeto en lugar de un nombre: {"id": "some_mod", "version": "", "optional": true}.
Un valor que nombra otro paquete es una referencia entre modificaciones y la referencia debe ser una dependencia declarada. Si esa dependencia es opcional, asigne al campo un fallback; de lo contrario, el registro se omitirá cuando la dependencia esté ausente:
a goods record
[
{
"op": "add",
"id": "northern_reach:alloy",
"display_name": "Alloy",
"linked_item_id": "absent_helper:ore",
"fallback": { "linked_item_id": "iron_ore" }
}
]Dónde va cada archivo
where the files go
northern_reach/
mod.json the label
content/assets/images/
images.json your art
content/inventory/items/
blades.json your first record
content/narrative/quest_plans/
the_long_winter.json your questNombres e identificaciones
Una identificación son letras minúsculas, dígitos y guiones bajos, y nada más. frost_blade, no Frost Blade, no frost-blade y no frost.blade. Ni siquiera lleva su propio separador, porque un separador dentro de un id es la carpeta que se filtra en el nombre: mueve el archivo y el id ya no concuerda con el disco. Los : anteriores son la única excepción y ambas mitades siguen la regla.
La parte antes de los dos puntos es la identificación de su paquete. Así es como dos mods pueden agregar un Frost Blade sin chocar.
Palabras que lee un jugador
El texto escrito dentro de un registro es texto en un solo idioma. En su lugar, señale una clave:
a locale CSV
northern_reach.item.frost_blade.name
northern_reach.item.frost_blade.descriptionLas claves están en minúsculas, unidas por puntos, con el espacio de nombres como identificadores. Incorpora palabras a la familia locales: un .csv bajo content/locale con una columna key y una columna de idioma. Las familias, una a una tiene la forma exacta.
También escriba el simple display_name al lado de la clave. Un registro que tiene sólo una frase tiene que ser reescrito a mano el día que lo traduces, y para entonces habrá cuatrocientas.
Las dos formas de hacer esto mal fallan de maneras muy diferentes, y solo una de ellas te dice eso. Una clave que no responde a nada aparece como la clave misma: northern_reach.item.frost_blade.name, en la pantalla, deliberadamente fea para que alguien la arregle, y contada como un agujero. Un registro que solo contiene texto y no contiene claves nunca aparece: funciona, en su idioma, para todos los jugadores en todos los idiomas. No se rechaza nada ni falta nada, por lo que nada lo informa y un jugador que lee en portugués lee en silencio tu italiano. Encuentras el primer error. El segundo encuentra a tus lectores.
Traduce un mod y serás traducido
El juego sale en siete idiomas, por lo que un paquete con inglés incluido en los registros se lee como inglés para seis séptimas partes de quienes lo instalan. Esto es lo que cuesta evitarlo, que es casi nada si lo haces el primer día y una reescritura si lo haces el cuatrocientos.
Los idiomas que hay
Siete, y esta tabla se lee desde la compilación en lugar de estar escrita a mano aquí, por lo que un idioma que llega o sale se mueve el mismo día:
| escribe esto | Lengua | Encabezado de columna | |
|---|---|---|---|
en | Inglés | en | el idioma de origen |
it | italiano | it | |
fr | francés | fr | |
de | alemán | de | |
es | Español | es | |
pt-BR | Português (Brasil) | pt_BR | |
zh-Hans | 简体中文 | zh_Hans |
Dos de los códigos tienen una segunda ortografía en circulación: pt-BR es la que usa una tienda digital y esta página, pt_BR es la que cumple el motor, y en el encabezado de una columna se aceptan ambos. Escriba el que copió.
Llevar palabras en más de un idioma.
Un CSV en content/locale, con key primero y una columna por idioma:
a locale CSV
key,en,it,de
northern_reach:GOOD_FROST_SALT,Frost Salt,Sale di Brina,Frostsalz
northern_reach:ITEM_FROST_BLADE_NAME,Frost Blade,Lama di Brina,Frostklinge| Regla | Por qué |
|---|---|
| Cada clave cabe en su espacio de nombres | northern_reach:GOOD_FROST_SALT, con los mismos dos puntos que usan los ids. Una clave que sale de allí se rechaza a menos que overrides la declare; de lo contrario, dos paquetes que escriban GOOD_GRAIN se resolverían mediante el orden de carga, de forma silenciosa. |
| Se rechaza una columna que nombra un idioma que el juego no incluye | No ignorado. Una columna que el cargador dejara caer silenciosamente no traería nada y te enterarías por un jugador. |
| Una celda en blanco no es una respuesta | Se omite en lugar de almacenarse, por lo que un idioma al que aún no ha llegado pasa al siguiente paso en lugar de permanecer en blanco en la pantalla. |
| Nunca ambos | Se rechaza un registro que contenga un campo _key y una cadena textual para lo mismo. La clave es la promesa; la cadena es lo que reemplazó la clave. |
Cuando una clave no tiene respuesta en el idioma del jugador, el juego desciende por una escalera fija: el idioma del jugador, luego el idioma en el que su paquete dice haber sido escrito, luego el catálogo del juego y luego la clave misma. El último paso es feo a propósito: una clave sin resolver tiene que verse mal para que alguien la arregle. Una conversión total se salta el catálogo de juegos, porque Old Seat aparecer en un mundo ambientado en otro continente no es un pequeño descuido de la traducción, es el juego base el que brilla.
Escribe un texto que se pueda traducir.
- No hay oraciones construidas en partes. El orden de las palabras no es el mismo en todos los idiomas, por lo que un nombre ensamblado en tiempo de ejecución a partir de una columna de adjetivos y una columna de sustantivos produce Oro Cervo en italiano. Una entrada escrita para cada idioma, completa.
- El nombre de una persona nunca se traduce ni se flexiona. Aldric es Aldric en todos los idiomas. Lo que también significa que una clave no debe poner un nombre en una posición oblicua (
"of {name}","{name}'s") porque muchos idiomas rechazan los nombres propios y el juego no. - No hay límite de caracteres y eso no es lo mismo que no tener límite. Ningún campo cuenta caracteres; lo que termina siendo espacio en la pantalla. El alemán es aproximadamente un tercio más largo que el inglés y es el idioma que rompe botones; el chino es mucho más bajo y casi nunca lo hace. Si prueba solo una traducción, pruebe con el alemán y coloque una etiqueta con la redacción más corta que aún sea correcta.
Alguien que traduzca tu paquete
Agrega una columna y le devuelve el archivo. El flujo de trabajo está todo aquí, y es por eso que el formato es CSV en lugar de algo más amigable para un programador: un traductor puede abrirlo en una hoja de cálculo y sus herramientas ya lo leen.
Dos cosas marcan la diferencia entre un paquete que se traduce y otro que no. Mantenga las claves estables: una clave renombrada es una traducción perdida y el traductor se entera cuando un jugador se entera. Y diga para qué sirve una línea: una clave llamada NR_MSG_01 obtiene una respuesta, mientras que northern_reach:VENDOR_HERB_GREETING recibe un saludo de vendedor de hierbas.
Si eres tú quien traduce el paquete de otra persona, te obligan las mismas reglas: las columnas son los idiomas que lleva el juego, las claves son sus claves y no las tuyas, y un nombre sigue siendo un nombre.
Cambiando lo que el juego ya tiene
| Quieres | Operación | Qué necesitas |
|---|---|---|
| Agrega algo nuevo | add | Tu propia identificación con tu propio espacio de nombres. Nada más. |
| Reescribe uno de los registros del juego. | replace | La identificación del registro que figura en overrides. Un expediente completo: no hereda nada. |
| Cambie un campo y deje el resto en paz | patch | overrides, más "manifest_version": 2 en mod.json. |
| Retirar un registro | remove | overrides, y una familia que lo acepta. Ver Sacar algo. |
part of mod.json
"overrides": ["iron_sword"]overrides es una promesa. Un registro que llega a una identificación que no declaraste se rechaza, por lo que nunca puedes cambiar silenciosamente algo de lo que un jugador no sabía nada.
a goods record
[
{
"op": "patch",
"id": "iron_ore",
"changes": [
{ "op": "set", "field": "base_price", "value": 14 }
]
}
]| Operación | Qué hace | Requiere | Rechazar |
|---|---|---|---|
add | Proporcione un registro nuevo y completo en su espacio de nombres. | identificación con espacio de nombres | una identificación que ya existe, ya sea del juego base o de otro mod |
replace | Proporcionar un registro completo de una identificación que ya existe, habiéndola declarado. | sobrescribir declarado, registro completo | una identificación ausente en el registro y una identificación que el manifiesto no incluye en overrides |
patch | Cambie los campos con nombre de un registro existente y deje el resto en paz. | anulación declarada, cambios | un id ausente del registro, un campo que la familia no permite y cualquier forma de modificación fuera de patch_operations |
remove | Retire un registro existente y deje una lápida en su lugar. | anulación declarada, familia removible | una identificación ausente del registro y cualquier familia que no esté marcada como extraíble a continuación |
Un parche nombra sus cambios uno a la vez:
- set: escribe
valueenfield, lo que haya antes. Está escrito confieldyvalue. - unset: elimina
fielddel registro, para que el lector vea el valor predeterminado de la familia. Está escrito confield. - append_unique: agrega
valuea la lista enfieldsi aún no está allí. Está escrito confieldyvalue. - remove_value: elimina cada aparición de
valuede la lista enfield. Está escrito confieldyvalue.
- Nombre un campo por ruta, nunca por ubicación.
tags.0se rechaza. La tercera etiqueta de hoy es la segunda después de cargar el mod de otra persona. - Una ruta tiene hasta cuatro nombres en minúsculas unidos por puntos. Todo lo que contenga un operador se rechaza.
append_uniquees el que dos mods pueden compartir. Si ambos ponen en cola la misma etiqueta, no es un conflicto y no la duplica.
Sólo a veces
Un registro puede indicarle cuándo vale la pena. Agregue un when al lado del op, en un paquete con "manifest_version": 2:
a presentation_bindings record
{
"op": "add",
"id": "my_mod:snowy_cloak",
"subject": "wool_cloak",
"kind": "item",
"slot": "icon",
"cue": "my_mod:cloak_snowy",
"when": { "season": { "is": "winter" } }
}No hay operador ni nada que calcular. Todo lo que una condición puede decir está en estas dos tablas.
| Preguntar por | Decidido | Evidencia | Valores |
|---|---|---|---|
packages | al cargar | all_of, none_of | ID de mod cargados junto al tuyo |
campaign | al cargar | is, any_of, not_any_of | la campaña desde la que comenzó el partido |
locale | al cargar | is, any_of, not_any_of | el idioma en el que estás jugando |
season | mientras juegas | is, any_of, not_any_of | spring, summer, autumn, winter |
weather | mientras juegas | is, any_of, not_any_of | una identificación del clima en el que se desarrolló el juego |
day_phase | mientras juegas | is, any_of, not_any_of | dawn, day, dusk, night |
day | mientras juegas | at_least, at_most | cuantos dias duro el partido |
| Ensayo | Acepta | Cierto cuando |
|---|---|---|
is | un nombre | la respuesta es exactamente esa |
any_of | una lista | la respuesta es una de esas |
not_any_of | una lista | la respuesta es ninguna de esas |
at_least | un numero | la respuesta es esa o superior |
at_most | un numero | la respuesta es esa o menos |
all_of | una lista | ellos estan todos alli |
none_of | una lista | no hay nadie |
Máximo cuatro sujetos en un when, dos ensayos por sujeto. Dos ensayos sobre el mismo tema son un intervalo: { "day": { "at_least": 10, "at_most": 30 } }.
Qué familia toma qué. Cada familia toma los tres decididos al cargar. Solo presentation_bindings y effects toman los cuatro que se mueven mientras juegan, porque solo esos dos se reconstruyen cuando el mundo cambia. Se rechaza nominar a season en otro lugar y el mensaje dice qué temas realmente toma esa familia.
La razón son los rescates. Un registro que decide un elemento, una persona o una misión debe ser el mismo registro la próxima vez que se cargue, y una condición de movimiento es exactamente lo que le impide hacerlo.
Un aspecto de temporada va en el enlace, no en la imagen. Trae la imagen solo una vez, luego dos registros presentation_bindings para ella: uno con un when y otro sin él. images, audio y fonts rechazan un when sin discusión.
La retención no se rechaza. Una condición que no se cumple mantiene su registro y el informe de carga lo dice por su nombre:
what the game prints back
WITHHELD my_mod:snowy_cloak from my_mod: season is winter, and it is springUn paquete con cincuenta récords de temporada se conserva en cualquier momento en las tres cuartas partes. Es el paquete el que funciona.
Si se niega cualquier asociación de presentación condicional, el informe aún muestra la familia tal como se declaró e imprime bound=0 junto con cada fila WITHHELD; no informa incorrectamente que el paquete no tiene superficie de presentación. Si ningún enlace incondicional proporciona el mismo espacio, también imprime NO_APPLICABLE kind/subject/slot con la condición sin respuesta, lo que significa "nada se aplica en este estado mundial", no "el registro no era válido". Pruebe la condición en el host o en el carril de ejecución con el estado mundial correspondiente antes de asumir que la asociación ha sido rechazada.
Dos versiones de lo mismo. Trae dos registros add con el mismo id y diferentes condiciones. El que mantiene su condición es el que cobra. Si ambos se cumplen, el segundo se rechaza como duplicado, que es la forma en que se informan las condiciones superpuestas en lugar de resolverse mediante el orden del archivo.
quitar algo
remove significa descontinuado, no fuera de existencia. El historial se sigue resolviendo y queda marcado: ya no se ofrece nada nuevo, no se mantiene en stock, no se fabrica ni se genera por él, y todo lo que un jugador ya tiene y que le nombra sigue leyendo exactamente lo que siempre ha leído.
| Familia | remove | Lo que sucede |
|---|---|---|
goods | Sí | Retirado. Todavía resuelve la identificación, algo que no es lo que ofrece el juego. |
vendor_inventories | Sí | Cancelado. Se elimina la línea. |
| todo lo demás | No | Rechazado, con razón. |
a goods record
{ "op": "remove", "id": "iron_ore" }vendor_inventories es la única familia que quita el registro, y solo porque las reglas de guardado ya dicen que nadie señala esa línea.
Un remove no puede transportar un when. Se debe decidir una retirada que podría denominarse un rescate, de lo contrario una identificación se resuelve una noche y no la siguiente.
La eliminación es permanente para una composición. Se rechaza un patch, replace o un segundo remove posterior dirigido al ID retirado, incluso si una retirada de mercancías mantiene el registro antiguo resoluble mediante su eliminación permanente. Esto evita que el informe guardado indique "retirado" mientras que un paquete posterior hace que el registro se comporte nuevamente como se proporcionó. Agregue una nueva ID de espacio de nombres cuando necesite un nuevo registro; No confíe en la remoción seguida de una resurrección silenciosa.
Cuando dos mods quieren lo mismo
Ambos cargan. Cada cambio se compone antes de construir algo, por lo que el juego ve ambos.
| que choca | Lo que sucede |
|---|---|
| Diferentes campos de un mismo registro | Ambos aplican. No se pierde nada. |
| El mismo campo simple | Gana el load_order más tarde, y un choque no declarado es un error: undeclared_collision, y la composición no es correcta. |
| Dos paquetes que proporcionan el registro completo | Lo mismo. El ganador se decide en load_order y el plan aún se niega hasta que alguien lo declara. |
La misma lista, con append_unique / remove_value | Sin conflictos. Ambos dicen lo que debería contener la lista, no lo que debería ser. |
| Un paquete retira un registro y otro lo modifica o reemplaza | La retirada se mantiene. La operación posterior se rechaza, sin importar el orden de carga. |
| Dos paquetes que visten el mismo tema | La orden de carga gana posteriormente y el perdedor se menciona en el informe. |
| Un paquete que viste el contenido de otro paquete | Refused. |
Ganar y obtener permiso son dos cuestiones diferentes, y esa es la parte sorprendente. El juego siempre calcula qué paquete escribe en último lugar (dejarlo en manos del azar haría que incluso lanzar una moneda al aire fuera rechazado) y aun así marca el par como una colisión que nadie declaró. El validador fuera de línea rechaza el mismo par sin discusión, por lo que te enterarás antes que un jugador.
supersedes en tu manifiesto es tu forma de decir que lo hiciste a propósito. Nombra la identificación del otro paquete y el conflicto se convierte en declared_replacement: registrado, con motivo y ya no es un error.
Dale a tu paquete un load_order propio. Dos paquetes que comparten un número no se rechazan, y luego el ganador queda fuera del orden alfabético de la identificación del mod: un orden que ningún autor eligió y que ningún jugador puede leer en la pantalla.
Imágenes, sonido, escritura, color.
Traer un archivo y usarlo son dos pasos separados y necesitas ambos. Un archivo al que nada apunta se lee, se comprueba, se mide y nunca se muestra.
| Tipo | Archivo | Instalado | Qué significa |
|---|---|---|---|
image | .png, .webp | Sí | Se lee el archivo y se construye la textura. |
audio | .ogg, .wav | No | Se validan los descriptores, se lee el encabezado y se delimita la duración, y nada suena: ninguna familia de contenidos lleva audio y la funcionalidad de audio no solicita ningún catálogo de un paquete de sonido. Trae el sonido cuando la familia exista; hoy sería mesurado y silencioso. |
font | .ttf, .otf | No | Se validan los descriptores y se verifica la cobertura del idioma, y ningún tema resuelve un carácter de paquete. La interfaz crea sus fuentes a partir del tema que trae consigo, por lo que una fuente proporcionada por un paquete se verificará y no se configurará con ningún valor. |
trae el archivo
Cada familia de recursos es un descriptor de archivo más los archivos que nombra. El descriptor debe tener el mismo nombre que su familia: images.json, audio.json, fonts.json.
where the files go
content/assets/images/
images.json
river_guard.png| Familia | Carpeta | Aceptar | Campos obligatorios |
|---|---|---|---|
images | content/assets/images | .png, .webp | id, file, format |
audio | content/assets/audio | .ogg, .wav (sin comprimir) | id, file, codec, role |
fonts | content/assets/fonts | .ttf, .otf | id, file, format, sizes, covers, fallback_font |
themes | content/assets/themes | fichas de colores | id, tokens |
effects | content/assets/effects | modelos anfitriones | id, template |
a images record
[
{
"id": "northern_reach:river_guard",
"file": "river_guard.png",
"format": "png"
}
]Tres reglas que muerden:
- El encabezado se verifica antes de que algo lo decodifique.
formates lo que es el archivo, no lo que afirma la extensión. - Un nombre de
fileque contiene..o~, o que comienza con/,\,res://ouser://, se rechaza en el nombre. - Una identificación que no se resuelve recibe un marcador de posición y una advertencia, nunca silencio.
apuesta por ello
En un registro que llevas, con un campo que toma tu identificación de imagen:
| Familia | Campo | Qué es |
|---|---|---|
items | icon_id | El icono de un artículo que llevas. |
npc_definitions | portrait_id | El retrato de un NPC con nombre. |
perks | icon | El icono de un privilegio. |
En cualquier cosa, incluido el contenido del juego base, con un registro presentation_bindings que nombre el tema, su tipo y su espacio:
a presentation_bindings record
[
{
"id": "northern_reach:iron_sword_icon",
"subject": "iron_sword",
"kind": "item",
"slot": "icon",
"cue": "northern_reach:river_guard",
"alternative_key": "northern_reach_iron_sword_icon_alt"
}
]| Tragamonedas | tu llevas | donde aparece | alternative_key | Estirado |
|---|---|---|---|---|
portrait | image | El marco del diálogo, para la identificación del hablante. | obligatorio | Sí |
sprite | image | Una ficha de tropa, terreno de un mapa mundial o un edificio en un asentamiento. | — | Sí |
icon | image | Celdas de inventario, para cualquier artículo, tuyo o del juego. | obligatorio | Sí |
banner | image | Los colores de la casa en la página de su diario. | — | Sí |
voice | audio | Suena cuando aparece la línea del hablante. | obligatorio | todavía no |
use_sound | audio | Suena cuando se usa un elemento y el uso ha surtido efecto. | — | todavía no |
ambience | audio | Realiza un ciclo mientras el jugador se encuentra en ese terreno. | — | todavía no |
theme | theme | ¿Cuál de tus paletas lleva la interfaz? | — | Sí |
font | font | ¿Cuál de tus personajes lleva la interfaz? | — | todavía no |
effect | effect | Meteorología y luz del terreno al que está vinculado. | — | Sí |
alternative_key es obligatorio cuando un slot lleva información: es la clave de idioma que dice lo mismo a un jugador que no puede recibir la imagen.
Sonido
role es un límite, no una etiqueta: cada uno tiene su propia duración máxima, su propio límite sobre cuántos jugadores juegan juntos y el cursor que busca un jugador.
| Rol | Para | Cursor |
|---|---|---|
music | Canciones | Música |
ambience | Habitaciones, tiempo, lugares. | Ambiente |
sfx | efectos cortos | Efectos |
voice | chistes hablados | Efectos |
Se rechaza un WAV comprimido: descodificarlo requiere un analizador, y el analizador es precisamente lo que estás evitando.
Escritos
covers nombra los idiomas para los que su fuente contiene glifos y la compilación se niega a instalarla para otros. Un personaje al que le falta un idioma no falla: dibuja cuadritos y en la pantalla se lee como una traducción a medio terminar, con el texto correcto y el fallo de la fuente.
fallback_font es obligatorio: nombre otra identificación de fuente propia o una familia del sistema (Segoe UI, Noto Sans). sizes es sobre lo que se calcula el caché de glifos.
Solo un carácter, nunca una colección: un .ttc contiene varios y cuál llega depende de un índice que el descriptor no puede llevar. Fuentes gratuitas con amplia cobertura: Google Fonts, Font Squirrel. Compruebe que la licencia le permita redistribuir el archivo; su paquete lo incluye.
Color
Tokens, nunca una escena, guión o ruta de recursos. Los nombres son los del juego: bg_deep, bg_mid, bg_button, bg_hover, border, border_hi, text, text_dim, accent, gold. Un nombre que esta compilación no conoce se menciona en el registro en lugar de permanecer allí como si estuviera aplicado.
a themes record
[
{
"id": "northern_reach:dusk",
"tokens": {
"bg_deep": { "kind": "colour", "value": "#12131a" },
"text": { "kind": "colour", "value": "#e8e2d0" },
"border": { "kind": "colour", "value": "#7f6ab0" }
},
"contrast_pairs": [
{ "text": "#e8e2d0", "background": "#12131a" }
]
}
]contrast_pairs se verifican en una proporción de 4,5 y por debajo de eso el tema se rechaza. El medidor WebAIM le indica la proporción de un par antes de usarlo.
Apague el paquete y la interfaz recuperará sus colores y escrituras.
Arte que sienta bien
La compilación comprueba que una imagen sea una imagen. No tiene nada que decir sobre si se ve bien, y en un mundo dibujado en grises, una espada brillante, alegre y de alta resolución no deja de estar equivocada al pasar todo escrutinio. Esto es lo que se sabe hoy.
| El registro | Pixel art, gris y poco heroico. Aburrido, desgastado, manchado por el tiempo. Una paleta adecuada para una tarde lluviosa en una ciudad que ha tenido un mal año. |
| Tacos | 16 píxeles, para cualquier cosa dibujada dentro de un mapa. Tus mapas. |
| Formatos y límites | .png o .webp, hasta 8192 por lado, hasta 8 MB, controlados por encabezado antes de que nada los decodifique. |
| Color de interfaz | Los diez tokens de themes y una relación contrast_pairs de 4,5 por debajo del cual se rechaza el tema. |
La guía de estilo completa aún no está publicada. Lo que traerá: la paleta en sí, las dimensiones en las que se dibuja cada tipo de cosa y ejemplos paralelos de lo que entra al mundo y lo que sale de él. Vale la pena esperar en lugar de adivinar, porque el fallo que evita no es un archivo rechazado: es un paquete que se instala perfectamente y hace que el juego parezca dos juegos.
Mientras no exista, el método fiable es el que no necesita ningún documento: coloca tu imagen junto a la imagen del juego y míralos juntos.
Tus mapas
Dibujar en [mosaico] (https://www.mapeditor.org/), exportar a .tmj e indexar a content/world/maps/maps.json.
a maps record
[
{
"id": "northern_reach:river_bend",
"file": "river_bend.tmj",
"name_key": "NORTHERN_REACH_RIVER_BEND",
"world_origin": [4096, 2560],
"region_id": "northern_reach:lowlands"
}
]| Regla | Qué significa |
|---|---|
| El equipo | Mosaicos de 16 píxeles, ortogonales, abajo a la derecha, terminados. |
| Los niveles son roles, no nombres | ground, collision y walkable son obligatorios. Un nivel llamado collisions se rechaza en lugar de ignorarse. |
| La geometría se declara | El área de colisión y de caminata son objetos que dibujas, nunca se deducen de la apariencia de los mosaicos. |
| Cada nombre de objeto tiene su propio espacio de nombres | northern_reach:towpath, no towpath. |
world_origin | ¿Dónde está tu esquina superior izquierda, en píxeles del mundo? Se dice porque un archivo de mapa no tiene idea de dónde se encuentra en un mundo. |
| Un mapa dice dónde, nunca qué | Un objeto poi en la capa bindings nombra un punto de interés que trajiste como registro; el arreglo lo mueve a donde lo dibujaste. |
| Todo o nada | Una disposición rechazada no aporta absolutamente nada. |
| Sin rutas | Una propiedad llamada path, scene, script, resource o template se rechaza por el nombre, sea cual sea su contenido. |
Un enlace que nombra contenido de otro paquete, o del juego base, hace que se rechace todo el diseño. modding_map_report nombra la disposición y la regla que la rechazó.
Tus misiones
Una misión es un conjunto de registros que sólo tienen sentido juntos, en content/narrative/quest_plans.
| Tipo | Qué es |
|---|---|
arc | La historia. Enumera las misiones que contiene. |
quest | La tarea: quién la da, cómo se llama, cuánto pagan. |
objective | Una cosa que el jugador debe hacer. |
ending | Cómo termina el arco. |
a quest_plans record
[
{
"kind": "arc",
"id": "northern_reach:the_long_winter",
"stages": ["northern_reach:bring_the_grain"]
},
{
"kind": "quest",
"id": "northern_reach:bring_the_grain",
"name_key": "northern_reach.quest.bring_the_grain.name",
"giver": "northern_reach:the_reeve",
"in_arc": "northern_reach:the_long_winter",
"objectives": ["northern_reach:gather_grain"],
"rewards": [
{ "grant": "receive_coin", "coin": 250 }
]
},
{
"kind": "objective",
"id": "northern_reach:gather_grain",
"quest": "northern_reach:bring_the_grain",
"goal": "collect_item",
"target": "northern_reach:winter_grain",
"count": 40
},
{
"kind": "ending",
"id": "northern_reach:the_barns_are_full",
"arc": "northern_reach:the_long_winter",
"requires": ["northern_reach:bring_the_grain"]
}
]| Objetivo | visto hoy |
|---|---|
collect_item | sí, llevas suficiente algo |
defeat_unit | Sí, has matado suficiente de algo. |
earn_coin | si, tienes suficiente dinero |
reach_place | sí, visitaste un asentamiento |
survive_days | sí, han pasado suficientes días |
speak_to, deliver_item, defend_place, escort_unit, learn_lore | no — rechazado por nombre en lugar de aceptado y luego nunca completado |
| Premio | Entregado hoy |
|---|---|
give_item, receive_coin | Sí |
change_relation | si, cuando el sujeto es el jugador |
| los otros cinco | se negó en voz alta |
- Un plan es todo o nada. Un registro incorrecto y no se instala ninguno: la alternativa es un arco que se detiene a mitad de camino con el jugador sosteniendo la espada y no el título.
- Una recompensa es un
grant, nunca unkind.kinddice cuál de los cuatro registros es. Una recompensa escrita conkindse lee muy bien y se rechaza.
Consulta el tuyo con modding_quest_plan_report.
Tus conversaciones
Una conversación son tres tipos de registros en content/narrative/dialogue: el dialogue_graph que le da nombre y dice en qué barra se abre, las barras dialogue_node que son las líneas y las opciones dialogue_option que están encima.
Tu línea es tu línea y nada la reescribe. Lo que un modelo local puede hacer es responder una pregunta que el jugador le escribe al personaje, manteniéndose dentro de lo que dice tu línea, y cuando no puede permanecer dentro, dice que no sabe. Es el jugador quien decide si esa superficie existe; Con el modelo apagado, el personaje dice tu frase y se detiene. La traducción de tu chiste proviene de los archivos de idioma, como todo lo que escribes.
El gráfico nombra speaker y el disparador está ahí. Cada personaje del juego le pregunta a esta familia qué conversaciones hay encima de ellos cuando se hace clic, para que puedas darle al herrero algo que decir sin redefinir al herrero.
a dialogue record
[
{
"kind": "dialogue_graph",
"id": "northern_reach:gate_toll",
"entry": "northern_reach:gate_open",
"speaker": "gate_warden",
"name_key": "TALK_PACK_GATE"
},
{
"kind": "dialogue_node",
"id": "northern_reach:gate_open",
"graph": "northern_reach:gate_toll",
"voice": "line",
"speaker": "gate_warden",
"line_key": "TALK_PACK_GATE_OPEN"
}
]Tú escribes la conversación, nunca las palabras: cada chiste es una clave de idioma, por lo que un mismo paquete se puede leer en todos los idiomas que tenga el jugador. Un paquete que contiene prosa es rechazado en el archivo en lugar de en la pantalla.
Un chiste y una elección pueden conllevar cada una de las condiciones, y una elección puede conllevar órdenes. Una condición decide si el objeto se muestra al jugador; una orden es lo que sucede cuando la recibe.
| Controlar | Acepta | el pregunta | Respondido hoy |
|---|---|---|---|
companion_present | companion | Ese compañero está ahí para escucharlo. | Sí |
faction_stance | faction, stance | Una facción se encuentra donde la opción espera. | sí, para hostile: cualquier otro valor se rechaza antes de la primera medida |
has_coin | coin | El jugador se lo puede permitir. | Sí |
has_item | item, count | El jugador lo lleva consigo. | Sí |
has_knowledge | lore | Esto le dijeron al jugador. | Sí |
has_trait | trait | El reproductor fue construido así. | Sí |
lacks_knowledge | lore | Esto aún no se lo han comunicado al jugador. | Sí |
quest_state | quest, state | Una misión es donde la opción espera. | Sí |
relation_at_least | subject, target, regard | Un lado piensa al menos esto del otro. | Sí |
season | season | Estamos en esa parte del año. | Sí |
time_of_day | phase | Estamos en esa parte del día. | Sí |
| Dominio | Acepta | Atrás | Hecho hoy |
|---|---|---|---|
change_relation | subject, target, delta | Mueve una reputación dentro de las reglas de relaciones publicadas por el anfitrión. | Sí |
give_item | item, count | Entregar algo. | Sí |
grant_knowledge | lore | Le dice algo al jugador. | Sí |
open_shop | vendor | Muestra los suministros de un comerciante en la pantalla. | Sí |
pay_coin | coin | El jugador paga. | Sí |
receive_coin | coin | Al jugador se le paga. | Sí |
recruit_companion | companion | Añade a alguien al grupo cuando las reglas de reclutamiento del anfitrión lo permitan. | Sí |
set_quest_state | quest, state | Llevar una misión a un estado que su historial lo permita. | sí, para active y failed: cualquier otro valor se rechaza antes de la primera medida |
start_combat | encounter | Cierra la conversación. | Sí |
take_item | item, count | Quita algo. | Sí |
travel_to | destination | Mover la empresa. | Sí |
- Nunca se abre una conversación que nombra algo que esta compilación no puede hacer. No la opción que lo usa: la conversación completa, antes de su primera línea. Una discusión que se detiene en la tercera opción ya se ha llevado las monedas del jugador.
- Nada se mueve más de lo que hay. Pregunta primero con
has_coinohas_item; un paquete que se olvida no puede poner al jugador en menos cuarenta monedas, porque nadie ha aceptado una deuda y ninguna pantalla la explica. - Todo chiste necesita una salida. Un chiste al que un jugador puede llegar y del que no puede escapar se rechaza cuando se carga el gráfico.
Consulta el tuyo con modding_dialogue_report.
tus escenas
Una escena es el único tipo de contenido que le quita el control al jugador, por lo que también es la única con una regla final. Las escenas viven en content/narrative/scenes y cada una nombra un where, el lugar donde se juega. Entra en ese lugar y comienza la escena.
a scenes record
[
{
"id": "northern_reach:the_morning_after",
"where": "northern_reach:waystation",
"beats": [
{ "beat": "fade_in", "seconds": 1.5 },
{ "beat": "lock_player" },
{ "beat": "say", "actor": "gate_warden", "line_key": "SCENE_PACK_GREETING" },
{ "beat": "wait", "seconds": 1.0 },
{ "beat": "unlock_player" }
]
}
]| Broma | Acepta | Veces | Jugado hoy |
|---|---|---|---|
ask_name | prompt_key | la escena la espera | Sí |
end | — | la escena continúa | Sí |
fade_in | seconds | la escena la espera | Sí |
fade_out | seconds | la escena la espera | Sí |
lock_player | — | la escena continúa | Sí |
narrate | line_key, seconds | la escena la espera | Sí |
play_cue | cue | la escena continúa | Sí |
remove_actor | actor | la escena continúa | Sí |
say | actor, line_key | la escena la espera | Sí |
show_exit | — | la escena continúa | Sí |
start_dialogue | graph | la escena la espera | Sí |
unlock_player | — | la escena continúa | Sí |
wait | seconds | la escena la espera | Sí |
walk_to | actor, anchor | la escena la espera | Sí |
- Una escena que elimina controles debe devolverlos. Una secuencia que termina sin
unlock_playerse rechaza, porque la alternativa es traer una habitación de la que el jugador solo puede salir cerrando el juego. - Las líneas van en orden y se espera una línea de bloqueo. Esto es lo que hace que una escena sea una escena en lugar de una lista de cosas que suceden todas a la vez.
Consulta el tuyo con modding_scene_report.
Tus capturas de pantalla
El diseño de una pantalla te indica qué secciones van en qué panel de pantalla ya tiene el juego y en qué orden. Presenta las piezas que dibuja esta construcción; no puede agregar uno, porque una sección que nadie escribió no tiene nada que dibujar.
Las disposiciones se encuentran en content/ui/screens. Las familias, una a una tiene campos y un registro para copiar.
Consulta el tuyo con modding_screen_report.
No apareció nada
Lea primero el estado en la pantalla Mod. Casi todos los estados mencionan el problema abiertamente, al pie de la letra, y también lo hace el error más común de todos: el que alguna vez estuvo en la parte superior de esta lista.
La familia falta en content_types. Escribes goods.json, olvidas "goods" en la lista de manifiesto y la carpeta nunca se abre: no se rechaza nada porque no se ha leído nada. El paquete se carga vacío. Ahora la pantalla le indica qué archivo pasó y qué agregar:
what the game prints back
content/economy/goods/goods.json was not read — add "goods" to content_types in mod.jsonEl validador fuera de línea imprime la misma oración, por lo que los dos no pueden estar en desacuerdo. Sólo si la línea dice cargado y no nombra ningún archivo no leído, baja en esta lista. Está en orden de frecuencia con la que cada uno es el culpable.
| # | Síntoma | Lo que dice el validador |
|---|---|---|
| 1 | La ruta de la carpeta es incorrecta. | WARN: declared goods root missing: …/content/economy/goods. Una advertencia, no un error: El paquete pasa de todos modos, y es por eso que --strict antes de publicar es el consejo que es. Familias, una a una tiene la carpeta exacta de cada familia. |
| 2 | La identificación no tiene dos puntos. | ERROR: add needs an id under your own namespace. Se rechaza frost_blade; Se acepta northern_reach:frost_blade. |
| 3 | El JSON está roto | ERROR: invalid json goods.json: Expecting ',' delimiter: line 6 column 5. Una coma faltante hace que todo el archivo sea ilegible y se le indica la línea. |
| 4 | El archivo está en el paquete incorrecto. | El mismo mensaje que el n. 2. Una identificación con el espacio de nombres de otra persona no es suya para escribir, y la verificación no puede distinguirla de un error tipográfico: solo sabe que el prefijo no es la identificación de su paquete. |
| 5 | Falta un campo obligatorio | El informe lo nombra: para los campos que una familia realmente requiere, que son menos de los que imagina. Apareció y está mal es el caso en el que no se informa nada en absoluto. |
Los informes nunca te hacen dudar. Un registro rechazado recibe un nombre, su problema y, por lo general, un código; consulte [Cada código de diagnóstico] (#cada-código-de-diagnóstico).
Apareció y está mal.
El caso más difícil, porque no se informa nada de nada. Dos cosas pasan todo escrutinio y aun así te dan un registro que no escribiste.
Un campo que omitiste no es un error: es un valor predeterminado. El esquema de cada familia te indica sin qué campos no se puede instalar un registro y, para casi todas las familias, esa lista es corta. goods requiere exactamente uno: id. Omita base_price y es 1. Omita weight y es 1.0. Omita category y el producto básico será una materia prima. Nada te alerta, porque no pasa nada: pediste un bien y lo obtuviste.
Incluso un valor que no está entre las opciones es un valor predeterminado. El lector pone todo en mayúsculas antes de buscar, por lo que manufactured y MANUFACTURED son el mismo valor y las mayúsculas nunca son el problema: no empieces a reescribir archivos por eso. El problema es MANUFACTURED_GOODS: no es miembro, por lo que pasa a ser RAW_MATERIAL. SLOW para un decay_tier se convierte en ETERNAL. El registro se instala, la pantalla dice aplicado y su vela tiene el precio y la caducidad de otra cosa.
Nada en el juego dice esto, porque no hay nada que decir: el campo se declara como una cadena y una cadena mal escrita sigue siendo una cadena. El validador es el único lugar al que puedes llevarlo, y ahora lo toma:
typed into the debug console
$ python tools/quality/validate_mod_data.py --root mods/northern_reach
WARN: northern_reach:goods:goods.json#1: category is "MANUFACTURED_GOODS",
which is not one of RAW_MATERIAL, MANUFACTURED, CONSUMABLE, AMMUNITION,
EQUIPMENT. It loads as RAW_MATERIAL.
ERROR=0 WARN=1Una advertencia y no un error, porque el registro realmente se carga y rechazarlo ahora rompería los paquetes que ya funcionan. --strict lo convierte en un error y es la razón por la que ejecuta --strict antes de publicar.
Un campo que omitiste permanece en silencio y no se puede tomar: omitir category y escribir RAW_MATERIAL son la misma solicitud. Entonces, las tablas de campo en [Las familias, una por una](#las-familias-una por una) marcan Obligatorio y dan la columna de valores como la forma que verifica el cargador. Cuando un registro se carga y se comporta como otra cosa, primero compare sus campos con esa tabla: lo que está buscando es un campo que no escribió o una palabra que el cargador no reconoció.
Referencia
cada familia
Una carpeta y un informe por familia. La columna de estado se mide en función de la construcción, por lo que nunca es una promesa que el juego no cumple. Lo que es es solo la primera línea, por lo que la tabla sigue siendo algo por lo que puedes desplazarte con la vista; la descripción completa de cada familia, con sus campos y un registro a copiar, es su entrada en Las familias, una a una.
| Familia | Estado | Carpeta en su paquete | Comando de informe | Qué es |
|---|---|---|---|---|
adaptive | Listo para usar | content/player/adaptive | modding_adaptive_report | Perfiles que analizan cómo va un partido y sugieren un enfoque diferente. |
audio | Validado, nada lo consume todavía | content/assets/audio | modding_audio_report | Sonidos que lleva un paquete, nombrados por id: música, ambiente, efectos y voz, cada uno apuntando a un archivo dentro de su propia carpeta y declarando el rol que lo delimita. |
buildings | Listo para usar | content/world/buildings | modding_building_report | Definiciones de edificios y servicios del asentamiento: denominación, color, función e interior reutilizado. |
caravans | Listo para usar | content/logistics/caravans | modding_caravan_report | Rutas comerciales que recorre una caravana: de dónde sale, hacia dónde va, qué trae, qué tan bien escoltada y a qué velocidad va. |
combat_balance | Listo para usar | content/combat/balance | modding_combat_balance_report | Valores de equilibrio de combate acotados que ajustan los parámetros del solucionador existente sin agregar reglas, operaciones o mecánicas. |
dialogue | Listo para usar | content/narrative/dialogue | modding_dialogue_report | Conversaciones como registros: el gráfico, sus chistes y las elecciones que en él se encuentran. |
effects | Listo para usar | content/assets/effects | modding_effect_report | Clima, polvo, chispas y luces, compuestos a partir de los modelos que el presentador pone a disposición. |
enemy_archetypes | Listo para usar | content/threat/enemy_archetypes | modding_enemy_archetype_report | Tipos de enemigos que conoce el nivel estratégico: rango, qué variantes despliegan, dónde acampan, qué tamaño tiene la guarnición y con qué frecuencia atacan. |
enemy_variants | Listo para usar | content/combat/enemy_variants | modding_enemy_variant_report | Bloques de estadísticas para un tipo de cuerpo enemigo en el campo: clase, rango, los cinco atributos y los identificadores del arma, mano izquierda y escudo que lleva. |
fonts | Validado, nada lo consume todavía | content/assets/fonts | modding_font_report | Tipos de letra que lleva un paquete, nombrados por id: el archivo, el tamaño en el que están dibujados y los idiomas cuyos glifos llevan. |
goods | Listo para usar | content/economy/goods | modding_goods_report | Bienes comercializables y sus propiedades económicas. |
group_archetypes | Listo para usar | content/strategic/group_archetypes | modding_group_archetype_report | Parámetros de estrategia ajustables para un grupo que vive en el mapa mundial: radio de advertencia, preferencia de objetivo, número de miembros, umbrales de suministro y retirada. |
images | Listo para usar | content/assets/images | modding_image_report | Imágenes que trae un paquete, nombradas por id: íconos, retratos y hojas de sprites, cada una apuntando a un archivo dentro de su propia carpeta. |
input_bindings | Listo para usar | content/input | modding_input_report | Acciones propias de un paquete, con la clave que deseen. |
items | Listo para usar | content/inventory/items | modding_items_report | Artículos de inventario, incluidas armas y armaduras. |
locales | Listo para usar | content/locale | modding_locale_report | Las palabras que lee un jugador, en CSV con una columna por idioma: las claves propias del paquete, y las del juego donde el paquete declara sobrescribir. |
lore | Listo para usar | content/narrative/lore | modding_lore_report | Entradas del códice: lugares, personas, eventos, costumbres y cosas sobre las que el mundo cuenta historias. |
maps | Listo para usar | content/world/maps | modding_map_report | Arreglos que dibuja un paquete en Tiled, nombrados por id: el archivo, dónde se encuentra en el mundo y la clave de idioma por la que se conoce. |
mercenary_templates | Listo para usar | content/character/mercenaries | modding_mercenary_report | Modelos de mercenarios contratables: nombre, clase, origen, salud y moral iniciales, costo de contratación y el día en que aparecen por primera vez. |
mr_lines | Listo para usar | content/medieval_realism/structured | modding_mr_lines_report | Líneas estructuradas de realismo medieval, enrutadas por identificación de archivo y línea en lugar de un campo de identificación en JSON. |
noble_houses | Listo para usar | content/politics/noble_houses | modding_noble_house_report | Datos iniciales de una casa noble: el señor, el heredero, qué asentamientos responden a la casa, y quién cuenta como rival o aliado. |
npc_definitions | Listo para usar | content/narrative/npcs | modding_npc_report | Definiciones de NPC nombrados. |
perks | Listo para usar | content/character/perks | modding_perk_report | Privilegios declarativos: desencadenantes y efectos, sin ningún controlador escrito en código. |
pois | Listo para usar | content/world/pois | modding_poi_report | Puntos de interés colocados por coordenadas en el mapa mundial escrito a mano. |
presentation_bindings | Listo para usar | content/presentation/bindings | - | Qué recurso del paquete ocupa qué espacio y en qué tema: el ícono de un objeto, el sprite de una unidad o mosaico, el estandarte de una facción, tanto para el contenido del paquete como para el del juego base. |
progress | Listo para usar | content/player/progress | - | Registros de progresión del jugador: objetivos, perfiles de dificultad seguros y perfiles de partido dentro de las reglas del anfitrión. |
quest_metadata | Listo para usar | content/narrative/quest_metadata | modding_quest_metadata_report | Registros de metadatos de Quest, indexados por quest_id en lugar de id. |
quest_plans | Listo para usar | content/narrative/quest_plans | modding_quest_plan_report | Planes de misión como registros: los arcos, misiones, objetivos y finales que escribe un paquete y a partir de los cuales el juego construye sus propias misiones. |
quests | Comprobado, aún no instalado | content/narrative/quests | - | Recursos de misión escritos a mano, cargados por ruta en lugar de interpretados como registros. |
recipes | Listo para usar | content/economy/recipes | - | Recetas artesanales: qué se consume, qué sale de ellas, dónde se elabora, cuánto cuesta y qué probabilidades hay de que se eche a perder. |
relationships | Listo para usar | content/companion/relationships | - | Patrones de pareja, políticas de relaciones acotadas, condiciones de reclutamiento y vínculos declarativos. |
scenes | Listo para usar | content/narrative/scenes | modding_scene_report | Escenas escenificadas: la habitación, quién está en ella y las líneas que se desarrollan en orden. |
screens | Listo para usar | content/ui/screens | modding_screen_report | Diseños de pantalla: qué secciones encajan en qué panel de pantalla ya tiene el juego y en qué orden. |
settings | Listo para usar | content/settings | modding_settings_report | Opciones que un jugador puede cambiar, declaradas en lugar de sorteadas. |
themes | Listo para usar | content/assets/themes | modding_theme_report | Paletas de interfaz como fichas: colores, tamaños y espacios con nombre, con pares cuyo contraste un jugador debe poder leer. |
vendor_inventories | Listo para usar | content/world/vendor_inventories | modding_vendor_inventory_report | Mesas de suministros para comerciantes. |
world_generation | Listo para usar | content/world/generation | - | Perfiles de generación hechos únicamente de datos: opciones ponderadas de bioma y ubicación, propiedad del anfitrión. |
- Listo para usar: formulario publicado, el juego instala tus registros, hay un ejemplo y tus ID sobreviven después de guardar y recargar.
- Validado, nada lo consume todavía — el cargador lee y comprueba la familia, pero ninguna superficie de paquete para el jugador la consume. Los paquetes de audio y fuentes están en este nivel: un informe limpio no hace aparecer en el juego una señal silenciosa ni una fuente sin usar.
- Comprobado, aún no instalado: el juego reconoce a la familia y verifica tu archivo, y nada lo coloca en un juego en curso. Un paquete dirigido a él pasa todas las comprobaciones y no carga nada. Está en la página a propósito: la alternativa es que alguien pase una noche allí sin descubrir que no ha hecho nada malo.
Decidida en pleno, sin ningún familiar que los cargue, por lo que ningún cartel puede preguntarle:
| seria | ¿A dónde iría? | Qué es |
|---|---|---|
feature_extension | todavía no hay carpeta | Un paquete que es una característica más que un contenido. Lo que un mod nunca puede hacer es la lectura honesta de esto. |
Esto no es un desperdicio. Lo que un mod nunca puede hacer es esa lista.
Las familias, una por una
Cada familia que construye sabe lo que acepta y un registro que puede copiar.
- Los campos obligatorios son aquellos sin los cuales no se puede instalar un registro.
- La columna de valores es la forma que verifica el cargador, no una pista.
- Cuando una familia lo dice, un campo que la tabla no nombra se rechaza junto con el registro en el que se encuentra. Un error tipográfico en el nombre de un campo es un registro que no se carga y el informe familiar lo dice por nombre.
Cada entrada también dice qué sucede con una partida guardada el día que un jugador te desinstala:
| Respuesta | ¿Qué hace el rescate? |
|---|---|
preserve_inert_reference | La identificación permanece, no se resuelve y se informa. El que tenía el jugador aún tiene nombre. |
substitute_placeholder | Un reemplazo estable propiedad del motor responde, por lo que el mundo se carga de todos modos y la identificación original se mantiene cerca. |
drop_optional_presentation | Se elimina la referencia porque nada depende de ello. Sólo una familia de presentación puede declarar esto. |
Aquí no hay nada escrito a mano. Los campos provienen del esquema publicado de cada familia. Cada ejemplo es uno de los paquetes que la matriz de prueba del marco hace girar contra el cargador, lo vuelve a colocar bajo el espacio de nombres northern_reach y lo vuelve a verificar con su patrón cuando ingresa a esta página: un ejemplo que el juego rechazaría hace que la compilación falle.
El mundo y los lugares que contiene.
5 familias: buildings, caravans, maps, pois, world_generation.
buildings
Definiciones de edificios y servicios del asentamiento: denominación, color, función e interior reutilizado.
- Estado Listo para usar
- Viajó en El servicio de un edificio
- Carpeta
content/world/buildings - Registros enrutados para el campo
id - Informe
modding_building_report - Si un reproductor te desinstala
substitute_placeholder. Un asentamiento con un agujero donde hubo un servicio es injugable; Se lee y recupera un edificio visiblemente desaparecido.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
role | Sí | cadena |
color | - | alguien |
description_key | - | cadena |
interior | - | texto, id |
interior_service | - | texto, id |
label | - | cadena |
label_key | - | cadena |
map_binding | - | texto, id |
services | - | lista |
settlement | - | texto, id |
tier | - | número entero de 0 a 5 |
En un archivo llamado buildings.json, o el nombre .json que quieras dentro de esa carpeta:
a buildings record, under content/world/buildings
[
{
"id": "northern_reach:guildhall",
"label": "Guild Hall",
"role": "reeve",
"color": {
"r": 0.4,
"g": 0.34,
"b": 0.26
},
"interior_service": "moot_hall"
}
]caravans
Rutas comerciales que recorre una caravana: de dónde sale, hacia dónde va, qué trae, qué tan bien escoltada y a qué velocidad va.
- Estado Listo para usar
- Carpeta
content/logistics/caravans - Registros enrutados para el campo
id - Informe
modding_caravan_report - Si un reproductor te desinstala
preserve_inert_reference. Una ruta cuyo paquete ha desaparecido conserva su nombre y no lleva nada. Reemplazar un destino enviaría los bienes de un jugador a un lugar que nunca aceptó.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
origin_settlement_id | Sí | cadena |
destination_settlement_id | Sí | cadena |
cargo_type | - | cadena |
cargo_value | - | entero, 0 o más |
daily_progress | - | número de 0,01 a 1,0 |
display_name | - | cadena |
group_archetype_id | - | cadena |
guard_strength | - | none, light, medium, heavy |
initial_spawn_offset_days | - | entero de 0 a 30 |
En un archivo llamado caravans.json, o el nombre .json que quieras dentro de esa carpeta:
a caravans record, under content/logistics/caravans
[
{
"id": "northern_reach:salt_road_run",
"display_name": "Salt Road Run",
"origin_settlement_id": "valdmere",
"destination_settlement_id": "old_seat",
"cargo_type": "salt",
"cargo_value": 240,
"guard_strength": "light",
"daily_progress": 0.08,
"initial_spawn_offset_days": 3
}
]maps
Arreglos que dibuja un paquete en Tiled, nombrados por id: el archivo, dónde se encuentra en el mundo y la clave de idioma por la que se conoce. El índice es el registro; el arreglo al lado se lee como datos y nunca como un recurso, se normaliza en forma canónica, se compara con el kit publicado y se ensambla antes de colocar cualquier cosa. Un diseño rechazado no coloca nada en absoluto, porque la mitad del mapa es una región a la que el jugador ingresa sin forma de saber qué mitad ha llegado.
- Estado Listo para usar
- Carpeta
content/world/maps - Registros enrutados para el campo
id - Informe
modding_map_report - Si un reproductor te desinstala
drop_optional_presentation. Ningún rescate menciona una disposición. Un guardado nombra el punto de interés que un diseño ha movido y ese registro conserva sus coordenadas, por lo que un mapa retirado cuesta el diseño y nunca el contenido. Dejarlo es lo que hace que el mundo vuelva a lo que dicen sus registros, en lugar de mantener una posición que ya nadie ofrece.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
file | Sí | texto, fixed shape |
name_key | Sí | cadena |
world_origin | Sí | lista de números enteros de -1000000 a 1000000 |
region_id | - | cadena |
sha256 | - | texto, fixed shape |
En un archivo llamado maps.json, o el nombre .json que quieras dentro de esa carpeta:
a maps record, under content/world/maps
[
{
"id": "northern_reach:river_bend",
"file": "river_bend.tmj",
"name_key": "MAP_RIVER_BEND",
"world_origin": [
4096,
2560
],
"region_id": "northern_reach:lowlands"
}
]pois
Puntos de interés colocados por coordenadas en el mapa mundial escrito a mano.
- Estado Listo para usar
- Ruta a Un lugar en el mapa
- Carpeta
content/world/pois - Registros enrutados para el campo
id - Informe
modding_poi_report - Si un reproductor te desinstala
preserve_inert_reference. Un lugar descubierto permanece descubierto. Las misiones y el historial de viajes apuntan a la identificación.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
display_name | Sí | cadena |
awareness_modifier | - | número de -1 a 1 |
description | - | cadena |
discovery_radius | - | numero del 1 al 10 |
kind | - | entero o cadena |
linked_quest_id | - | cadena |
morale_modifier | - | número entero de -10 a 10 |
narrative_significance_key | - | cadena |
one_time_loot | - | booleano |
world_position | - | alguien |
En un archivo llamado pois.json, o el nombre .json que quieras dentro de esa carpeta:
a pois record, under content/world/pois
[
{
"id": "northern_reach:drowned_mile",
"kind": "RUINS",
"display_name": "The Drowned Mile",
"description": "A stretch of road the river took back. The milestones still stand, chest deep.",
"world_position": {
"x": 0.0,
"y": 0.0
},
"discovery_radius": 3.0,
"one_time_loot": true,
"morale_modifier": -1,
"awareness_modifier": 0.05,
"narrative_significance_key": "POI_DROWNED_MILE_LORE"
}
]world_generation
Perfiles de generación hechos únicamente de datos: opciones ponderadas de bioma y ubicación, propiedad del anfitrión.
- Estado Listo para usar
- Carpeta
content/world/generation - Registros enrutados para el campo
id - Informe nada suyo;
modding_preflight_reportse encarga de ello - Si un reproductor te desinstala
preserve_inert_reference. Un guardado registra la identificación del perfil elegido. Si falta su paquete, mantener e informar esa identificación es más seguro que reconstruir silenciosamente el juego con el mapa del juego base.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
kind | Sí | alguien |
id | Sí | texto, id |
stream | Sí | texto, id |
tables | Sí | objeto |
description_key | - | cadena |
name_key | - | cadena |
En un archivo llamado profiles.json, o el nombre .json que quieras dentro de esa carpeta:
a world_generation record, under content/world/generation
[
{
"kind": "generation_profile",
"id": "northern_reach:ashen_reach",
"stream": "northern_reach:world_stream",
"tables": {
"biomes": [
{
"id": "plains",
"weight": 60
},
{
"id": "forest",
"weight": 30
},
{
"id": "hills",
"weight": 10
}
],
"settlements": [
{
"id": "northern_reach:hamlet",
"weight": 100
}
],
"buildings": [
{
"id": "northern_reach:longhouse",
"weight": 100
}
],
"pois": [
{
"id": "northern_reach:standing_stone",
"weight": 100
}
]
}
}
]Personas, familias y lo que pueden hacer
8 familias: enemy_archetypes, enemy_variants, group_archetypes, mercenary_templates, noble_houses, npc_definitions, perks, relationships.
enemy_archetypes
Tipos de enemigos que conoce el nivel estratégico: rango, qué variantes despliegan, dónde acampan, qué tamaño tiene la guarnición y con qué frecuencia atacan.
- Estado Listo para usar
- Carpeta
content/threat/enemy_archetypes - Registros enrutados para el campo
id - Informe
modding_enemy_archetype_report - Si un reproductor te desinstala
preserve_inert_reference. Un campamento todavía indica lo que lo estableció. Reemplazar cambiaría silenciosamente lo que asedia un acuerdo; nombrando la ausencia que leemos.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
aggression | - | numero del 0 al 1 |
behavior_profile_mix | - | lista de cadenas |
camp_count | - | entero de 0 a 12 |
camp_glyph | - | cadena |
corruption_chance | - | numero del 0 al 1 |
description | - | cadena |
display_name | - | cadena |
encounter_id | - | cadena |
garrison_max | - | número entero de 1 a 60 |
garrison_min | - | número entero de 1 a 60 |
preferred_camp_biomes | - | lista de cadenas |
raid_cooldown_days | - | entero de 0 a 30 |
sortie_size_max | - | número entero de 1 a 30 |
sortie_size_min | - | número entero de 1 a 30 |
target_preferences | - | lista de cadenas |
tier | - | número entero de 1 a 5 |
variant_ids | - | lista de cadenas |
variant_weights | - | lista |
En un archivo llamado enemy_archetypes.json, o el nombre .json que quieras dentro de esa carpeta:
a enemy_archetypes record, under content/threat/enemy_archetypes
[
{
"id": "northern_reach:salt_reavers",
"display_name": "Salt Reavers",
"description": "Coastal raiders who winter inland and burn what they cannot carry.",
"tier": 2,
"corruption_chance": 0.1,
"preferred_camp_biomes": [
"marsh",
"coast"
],
"camp_count": 3,
"garrison_min": 8,
"garrison_max": 16,
"aggression": 0.4,
"raid_cooldown_days": 5,
"sortie_size_min": 4,
"sortie_size_max": 9,
"target_preferences": [
"caravan",
"settlement"
],
"camp_glyph": "tent"
}
]enemy_variants
Bloques de estadísticas para un tipo de cuerpo enemigo en el campo: clase, rango, los cinco atributos y los identificadores del arma, mano izquierda y escudo que lleva.
- Estado Listo para usar
- Carpeta
content/combat/enemy_variants - Registros enrutados para el campo
id - Informe
modding_enemy_variant_report - Si un reproductor te desinstala
substitute_placeholder. No se puede luchar contra un cuerpo que ya está en el campo sin un bloque de estadísticas. Un reemplazo estable que posee el motor mantiene la batalla solucionable y la identificación original se conserva.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
archetype_id | Sí | cadena |
agility | - | numero del 0 al 12 |
ai_behavior | - | cadena |
aim | - | numero del 0 al 12 |
constitution | - | numero del 0 al 12 |
display_name | - | cadena |
main_weapon_id | - | cadena |
off_weapon_id | - | cadena |
shield_id | - | cadena |
special_ability_description | - | cadena |
special_ability_name | - | cadena |
strength | - | numero del 0 al 12 |
tier | - | número entero de 1 a 4 |
variant_class | - | soldier, archer, berserker, ranger, finisher |
will | - | numero del 0 al 12 |
En un archivo llamado enemy_variants.json, o el nombre .json que quieras dentro de esa carpeta:
a enemy_variants record, under content/combat/enemy_variants
[
{
"id": "northern_reach:salt_reaver_archer",
"archetype_id": "northern_reach:salt_reavers",
"display_name": "Salt Reaver Archer",
"variant_class": "archer",
"tier": 2,
"strength": 3.0,
"agility": 5.0,
"constitution": 3.5,
"aim": 6.0,
"will": 2.5,
"main_weapon_id": "short_bow",
"ai_behavior": "keeps distance and gives ground rather than trade blows"
}
]group_archetypes
Parámetros de estrategia ajustables para un grupo que vive en el mapa mundial: radio de advertencia, preferencia de objetivo, número de miembros, umbrales de suministro y retirada.
- Estado Listo para usar
- Carpeta
content/strategic/group_archetypes - Registros enrutados para el campo
id - Informe
modding_group_archetype_report - Si un reproductor te desinstala
substitute_placeholder. La inteligencia estratégica debe leer un umbral en alguna parte. Responde a un valor por defecto que posee el motor, que es el mismo al que ya recurre esta familia.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
aggression | - | cadena |
alarm_radius_px | - | número de 0 a 2000 |
behavior_profile_mix | - | lista de cadenas |
captain_archetype_id | - | cadena |
display_name | - | cadena |
faction_id | - | cadena |
kind | - | none, caravan, patrol, army, lair, camp, … |
max_members | - | número entero de 1 a 60 |
member_archetype_mix | - | lista de cadenas |
min_members | - | número entero de 1 a 60 |
night_aggression_multiplier | - | número de 0,25 a 4 |
provisions_max | - | entero de 0 a 99 |
retreat_hp_pct | - | numero del 0 al 1 |
target_preference | - | cadena |
En un archivo llamado group_archetypes.json, o el nombre .json que quieras dentro de esa carpeta:
a group_archetypes record, under content/strategic/group_archetypes
[
{
"id": "northern_reach:pilgrim_column",
"display_name": "Pilgrim Column",
"kind": "nomad",
"faction_id": "",
"target_preference": "wandering",
"aggression": "avoid_player",
"alarm_radius_px": 300.0,
"night_aggression_multiplier": 0.5,
"min_members": 6,
"max_members": 14,
"behavior_profile_mix": [
"coward",
"balanced"
],
"provisions_max": 6,
"retreat_hp_pct": 0.6
}
]mercenary_templates
Modelos de mercenarios contratables: nombre, clase, origen, salud y moral iniciales, costo de contratación y el día en que aparecen por primera vez.
- Estado Listo para usar
- Carpeta
content/character/mercenaries - Registros enrutados para el campo
id - Informe
modding_mercenary_report - Si un reproductor te desinstala
preserve_inert_reference. Los mercenarios ya contratados viven en el rescate como una unidad; sólo la lista de la taberna pierde su plantilla. La identificación permanece nombrada, por lo que aún se puede leer el origen de lo orgánico.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
display_name | Sí | cadena |
available_from_day | - | número entero de 0 a 999 |
background | - | cadena |
class_id | - | cadena |
hire_cost | - | entero de 0 a 9999 |
hp_max | - | número entero de 1 a 999 |
morale_start | - | número entero de 1 a 100 |
En un archivo llamado mercenaries.json, o el nombre .json que quieras dentro de esa carpeta:
a mercenary_templates record, under content/character/mercenaries
[
{
"id": "northern_reach:ditchwater_sapper",
"display_name": "Ditchwater Sapper",
"class_id": "skirmisher",
"background": "Dug siege trenches for whoever was paying, and stopped asking which side it was.",
"hp_max": 24,
"morale_start": 70,
"hire_cost": 180,
"available_from_day": 6
}
]noble_houses
Datos iniciales de una casa noble: el señor, el heredero, qué asentamientos responden a la casa, y quién cuenta como rival o aliado.
- Estado Listo para usar
- Carpeta
content/politics/noble_houses - Registros enrutados para el campo
id - Informe
modding_noble_house_report - Si un reproductor te desinstala
preserve_inert_reference. El respeto de un jugador por una casa queda registrado en su identificación. Reemplazar uno sería reescribir sin decir nada a aquellos que eran leales.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
alignment | - | pro_crown, pragmatic, isolationist, hostile, neutral, opportunist, … |
ally_house_ids | - | alguien |
apex_ambition | - | alguien |
apex_claim_legitimacy | - | alguien |
captain_initial_opinion | - | entero de 0 a 100 |
captain_initial_stance | - | hostile, suspicious, neutral, willing, allied |
castle_id | - | cadena |
corruption_risk | - | low, moderate, high, critical, unknown |
current_lord_id | - | cadena |
designer_hooks | - | cadena |
display_name | - | cadena |
display_name_key | - | cadena |
family_npc_ids | - | alguien |
heir_id | - | cadena |
house_power_base | - | alguien |
is_defunct | - | booleano |
is_minor | - | booleano |
lord_state | - | healthy, ailing, corrupted, missing, dead, none |
lore_summary | - | cadena |
predecessor_house_id | - | cadena |
rival_house_ids | - | alguien |
secret_flags | - | alguien |
settlement_ids | - | alguien |
steward_npc_id | - | cadena |
strength | - | dominant, stable, reduced, weakened, vacant, extinct |
En un archivo llamado noble_houses.json, o el nombre .json que quieras dentro de esa carpeta:
a noble_houses record, under content/politics/noble_houses
[
{
"id": "northern_reach:house_tidewatch",
"display_name_key": "VALID_NOBLE_HOUSE_MOD_HOUSE_TIDEWATCH",
"display_name": "House Tidewatch",
"strength": "reduced",
"alignment": "isolationist",
"corruption_risk": "moderate",
"is_minor": true,
"lord_state": "ailing",
"captain_initial_stance": "suspicious",
"captain_initial_opinion": 35,
"apex_ambition": 20,
"apex_claim_legitimacy": 15,
"house_power_base": 25,
"lore_summary": "Kept the coast road open for two hundred years and was paid in salt for it."
}
]npc_definitions
Definiciones de NPC nombrados.
- Estado Listo para usar
- Entrado Un comerciante que lo posee
- Carpeta
content/narrative/npcs - Registros enrutados para el campo
id - Informe
modding_npc_report - Si un reproductor te desinstala
preserve_inert_reference. No es lo mismo una persona con un nombre que el mundo recuerda que otra que nunca existió, y los informes apuntan al ello.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
display_name | Sí | cadena |
faction | - | cadena o número entero |
flag_keys | - | lista de cadenas |
is_vendor | - | booleano |
kill_reputation_delta | - | número entero de -100 a 100 |
location_afternoon | - | texto, id |
location_evening | - | texto, id |
location_morning | - | texto, id |
lore_only | - | booleano |
need_quest_ids | - | lista de cadenas |
offers_quest_ids | - | lista de cadenas |
personal_need | - | cadena |
personality_tags | - | lista de cadenas |
portrait_id | - | texto, id |
price_multiplier | - | número del 0,1 al 10 |
role | - | cadena o número entero |
settlement_id | - | texto, id |
short_bio | - | cadena |
starts_hidden | - | booleano |
title | - | cadena |
vendor_inventory_id | - | texto, id |
voice_tone | - | cadena |
En un archivo llamado npcs.json, o el nombre .json que quieras dentro de esa carpeta:
a npc_definitions record, under content/narrative/npcs
[
{
"id": "northern_reach:wandering_herbalist",
"display_name": "Wandering Herbalist",
"title": "Travelling Healer",
"role": "NONE",
"settlement_id": "old_seat",
"is_vendor": true,
"vendor_inventory_id": "northern_reach:herb_stall",
"personality_tags": [
"gentle",
"secretive"
]
}
]perks
Privilegios declarativos: desencadenantes y efectos, sin ningún controlador escrito en código.
- Estado Listo para usar
- Carpeta
content/character/perks - Registros enrutados para el campo
id - Informe
modding_perk_report - Si un reproductor te desinstala
preserve_inert_reference. Un personaje conserva lo que se ha ganado. Eliminar una función reescribe silenciosamente un edificio en el que el jugador pasó una partida.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
skill | Sí | texto, fixed shape |
name_key | Sí | cadena |
kind | Sí | road, junction, lateral, capstone |
col | Sí | entero de 0 a 4 |
row | Sí | número entero del 1 al 7 |
level | Sí | número entero de 1 a 300 |
description_key | - | cadena |
icon | - | texto, id |
parents | - | lista de cadenas |
side | - | L, R |
En un archivo llamado perks.json, o el nombre .json que quieras dentro de esa carpeta:
a perks record, under content/character/perks
[
{
"id": "northern_reach:stoneskin",
"skill": "armour",
"name_key": "PERK_STONESKIN",
"description_key": "PERK_STONESKIN_DESC",
"kind": "lateral",
"side": "L",
"col": 0,
"row": 7,
"level": 100,
"parents": [],
"icon": "northern_reach:stoneskin_icon"
}
]relationships
Patrones de pareja, políticas de relaciones acotadas, condiciones de reclutamiento y vínculos declarativos.
- Estado Listo para usar
- Carpeta
content/companion/relationships - Registros enrutados para el campo
id - Informe nada suyo;
modding_preflight_reportse encarga de ello - Si un reproductor te desinstala
preserve_inert_reference. La semilla de la relación de pareja permanece adherida a su identificación, por lo que eliminar un paquete no puede borrar silenciosamente la confianza, los rencores o el historial de abandonos.
Campos. Esta familia contiene más de un tipo de registro y cada tipo se compara con su propia lista. Un campo que esta tabla no nombra se rechaza junto con el registro.
Un registro con kind: bond:
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
kind | Sí | bond |
relation | Sí | cadena |
subject | Sí | cadena |
target | Sí | cadena |
initial_regard | Sí | número entero de -100 a 100 |
policy | Sí | cadena |
description_key | - | cadena |
name_key | - | cadena |
note_key | - | cadena |
Un registro con kind: companion_template:
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
kind | Sí | companion_template |
unit | Sí | cadena |
recruit | Sí | cadena |
loyalty | Sí | cadena |
description_key | - | cadena |
leave_below | - | número entero de -100 a 100 |
name_key | - | cadena |
starting_regard | - | número entero de -100 a 100 |
Un registro con kind: recruit_terms:
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
kind | Sí | recruit_terms |
means | Sí | cadena |
cost | - | número entero de 0 a 1000000 |
description_key | - | cadena |
name_key | - | cadena |
requires_bond | - | cadena |
Un registro con kind: relationship_policy:
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
kind | Sí | relationship_policy |
relation_kinds | Sí | lista de cadenas |
bounds | Sí | objeto |
bands | Sí | lista de objetos |
decay_per_day | - | número entero de 0 a 20 |
description_key | - | cadena |
max_change_per_event | - | número entero de 1 a 50 |
name_key | - | cadena |
En un archivo llamado relationships.json, o el nombre .json que quieras dentro de esa carpeta:
a relationships record, under content/companion/relationships
[
{
"id": "northern_reach:marsh_policy",
"kind": "relationship_policy",
"relation_kinds": [
"comrade",
"feud",
"sworn"
],
"bounds": {
"floor": -100,
"ceiling": 100
},
"bands": [
{
"name": "hostile",
"from": -100,
"to": -61
},
{
"name": "cold",
"from": -60,
"to": -31
},
{
"name": "wary",
"from": -30,
"to": -11
},
{
"name": "neutral",
"from": -10,
"to": 10
},
{
"name": "warm",
"from": 11,
"to": 40
},
{
"name": "trusted",
"from": 41,
"to": 70
},
{
"name": "devoted",
"from": 71,
"to": 100
}
],
"max_change_per_event": 12,
"decay_per_day": 1
},
{
"id": "northern_reach:hire_terms",
"kind": "recruit_terms",
"means": "hire",
"cost": 240
},
{
"id": "northern_reach:marsh_companion",
"kind": "companion_template",
"unit": "northern_reach:marsh_unit",
"recruit": "northern_reach:hire_terms",
"loyalty": "northern_reach:marsh_policy",
"starting_regard": 8,
"leave_below": -60
}
]Cosas, comercio y los números detrás de un choque
5 familias: combat_balance, goods, items, recipes, vendor_inventories.
combat_balance
Valores de equilibrio de combate acotados que ajustan los parámetros del solucionador existente sin agregar reglas, operaciones o mecánicas.
- Estado Listo para usar
- Carpeta
content/combat/balance - Registros enrutados para el campo
id - Informe
modding_combat_balance_report - Si un reproductor te desinstala
substitute_placeholder. El saldo es una definición de datos en poder del anfitrión, no del inventario del jugador. Cuando su paquete está ausente el equilibrio canónico y estable responde, y la carga posterior no trae consigo una segunda forma de guardar los ajustes.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
values | Sí | objeto |
En un archivo llamado balance.json, o el nombre .json que quieras dentro de esa carpeta:
a combat_balance record, under content/combat/balance
[
{
"id": "northern_reach:coastal_balance",
"values": {
"zone_penalty_head": 22,
"crit_damage_mult": 1.75,
"friendly_fire_redirect_chance": 0.2
}
}
]goods
Bienes comercializables y sus propiedades económicas.
- Estado Listo para usar
- Viajó en [Un producto bueno para vender](#un producto bueno para vender)
- Carpeta
content/economy/goods - Registros enrutados para el campo
id - Informe
modding_goods_report - Si un reproductor te desinstala
preserve_inert_reference. Una escort que nombra un bien que nadie suministra es honesta. Reemplazarla cambiaría silenciosamente lo que tiene un jugador.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
base_price | - | número entero de 0 a 1000000 |
category | - | cadena o número entero |
daily_consumption_class | - | cadena |
decay_tier | - | cadena o número entero |
display_name | - | cadena |
display_name_key | - | cadena |
linked_item_id | - | cadena |
production_class | - | cadena |
tags | - | lista de cadenas |
weight | - | número de 0 a 10000 |
En un archivo llamado goods.json, o el nombre .json que quieras dentro de esa carpeta:
a goods record, under content/economy/goods
[
{
"id": "northern_reach:spiced_wine",
"display_name": "Spiced Wine",
"category": "consumable",
"decay_tier": "preserved",
"base_price": 12,
"weight": 0.5,
"tags": [
"luxury",
"drink"
]
}
]items
Artículos de inventario, incluidas armas y armaduras.
- Estado Listo para usar
- Entrado Un artículo para llevar
- Carpeta
content/inventory/items - Registros enrutados para el campo
id - Informe
modding_items_report - Si un reproductor te desinstala
preserve_inert_reference. El repositorio sigue nombrando lo que había en él, y esa es la única razón por la que la reinstalación se lo devuelve.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
base_value | - | entero, 0 o más |
category | - | cadena o número entero |
condition | - | numero del 0 al 1 |
description_key | - | cadena |
display_name | - | cadena |
display_name_key | - | cadena |
icon_id | - | texto, id |
max_stack | - | entero, 1 o más |
quality_tier | - | entero, 0 o más |
rarity | - | cadena o número entero |
sellable | - | booleano |
tags | - | lista de cadenas |
weight | - | número, 0 o más |
En un archivo llamado items.json, o el nombre .json que quieras dentro de esa carpeta:
a items record, under content/inventory/items
[
{
"id": "northern_reach:spiced_wine_bottle",
"display_name": "Bottle of Spiced Wine",
"category": "CONSUMABLE",
"rarity": "UNCOMMON",
"weight": 0.5,
"max_stack": 10,
"base_value": 14,
"sellable": true,
"tags": [
"drink",
"luxury"
]
}
]recipes
Recetas artesanales: qué se consume, qué sale de ellas, dónde se elabora, cuánto cuesta y qué probabilidades hay de que se eche a perder.
- Estado Listo para usar
- Carpeta
content/economy/recipes - Registros enrutados para el campo
id - Informe nada suyo;
modding_preflight_reportse encarga de ello - Si un reproductor te desinstala
preserve_inert_reference. Nada en un guardado nombra una receta: un guardado nombra el objeto que ha producido un proceso, y la familia de ese objeto es responsable de ello. Lo que una receta retirada deja atrás es una estación que ya no ofrece algo, que se informa en lugar de arreglarse, porque inventar una receta de reemplazo pondría en la mano del jugador un artículo que ningún paquete proporciona.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
inputs | Sí | objeto |
craft_tax_rate | - | número de 0.0 a 1.0 |
description_key | - | cadena |
display_name_key | - | cadena |
enhancer_policy | - | none, consumed, preserved, damaged, transformed |
failure_policy | - | none, lose_fuel, lose_catalyst, lose_all, damaged_output |
gold_cost | - | entero de 0 a 9999 |
legality | - | legal, licensed, suspicious, forbidden, black_market |
optional_enhancer | - | cadena |
output_count | - | número entero de 1 a 99 |
output_good_id | - | cadena |
output_item_id | - | cadena |
quality_policy | - | fixed, material_inputs, crafter_skill, enhancer, materials_and_crafter |
recipe_kind | - | normal, equipment, special, enhancement |
requires_perk_id | - | cadena |
requires_service | - | cadena |
station_fee | - | entero de 0 a 9999 |
success_chance | - | número de 0.0 a 1.0 |
time_cost_minutes | - | número entero de 1 a 60 |
tools_required | - | lista de cadenas |
En un archivo llamado recipes.json, o el nombre .json que quieras dentro de esa carpeta:
a recipes record, under content/economy/recipes
[
{
"id": "northern_reach:salt_cured_ration",
"display_name_key": "VALID_RECIPE_MOD_SALT_CURED_RATION",
"recipe_kind": "normal",
"inputs": {
"salt": 1,
"dried_meat": 2
},
"output_item_id": "northern_reach:salt_cured_ration",
"output_count": 3,
"requires_service": "kitchen",
"gold_cost": 4,
"time_cost_minutes": 20,
"success_chance": 0.95,
"failure_policy": "lose_fuel",
"quality_policy": "material_inputs",
"legality": "legal"
}
]vendor_inventories
Mesas de suministros para comerciantes.
- Estado Listo para usar
- Entrado Un comerciante que lo posee
- Carpeta
content/world/vendor_inventories - Registros enrutados para el campo
id - Informe
modding_vendor_inventory_report - Si un reproductor te desinstala
drop_optional_presentation. Las existencias se regeneran. Un comerciante con un estante vacío es un estado legible y la línea no apunta a nada más.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
display_name | Sí | cadena |
entries | Sí | lista de objetos |
buyback_rate | - | numero del 0 al 1 |
description | - | cadena |
global_price_multiplier | - | número, 0 o más |
npc_id | - | cadena |
En un archivo llamado vendors.json, o el nombre .json que quieras dentro de esa carpeta:
a vendor_inventories record, under content/world/vendor_inventories
[
{
"id": "northern_reach:herb_stall",
"display_name": "Herbalist's Stall",
"npc_id": "northern_reach:wandering_herbalist",
"global_price_multiplier": 1.0,
"buyback_rate": 0.4,
"entries": [
{
"item_id": "northern_reach:spiced_wine_bottle",
"kind": "consumable",
"daily_stock": 3,
"price_multiplier": 1.1,
"restock_days": 2,
"min_standing": 0
}
]
}
]Historia, misiones y las palabras que lee un jugador.
9 familias: dialogue, locales, lore, mr_lines, progress, quest_metadata, quest_plans, quests, scenes.
dialogue
Conversaciones como registros: el gráfico, sus chistes y las elecciones que en él se encuentran. Tres tipos comparten la familia y kind dice cuál. Un paquete escribe la conversación, nunca las palabras (cada pulsación de tecla es una tecla de idioma) y cada condición y cada consecuencia es una verificación o comando que esta compilación ya ejecuta.
- Estado Listo para usar
- Carpeta
content/narrative/dialogue - Registros enrutados para el campo
id - Informe
modding_dialogue_report - Si un reproductor te desinstala
preserve_inert_reference. Un guardado registra lo que ha hecho una conversación (una misión que se ha movido, un objeto que ha cambiado de manos, una verdad aprendida), nunca la conversación en sí, que termina en el momento en que escribes algo. Cuando el paquete desaparece, las consecuencias permanecen porque nunca fueron parte de la conversación y la conversación simplemente ya no se ofrece. Reemplazarlo pondría palabras en boca de un personaje que su autor nunca escribió.
Campos. Esta familia contiene más de un tipo de registro y cada tipo se compara con su propia lista. Un campo que esta tabla no nombra se rechaza junto con el registro.
Un registro con kind: dialogue_graph:
| Campo | Necesario | Valores |
|---|---|---|
kind | Sí | dialogue_graph |
id | Sí | cadena |
entry | Sí | cadena |
description_key | - | texto, fixed shape |
name_key | - | texto, fixed shape |
speaker | - | cadena |
Un registro con kind: dialogue_node:
| Campo | Necesario | Valores |
|---|---|---|
kind | Sí | dialogue_node |
id | Sí | cadena |
graph | Sí | alguien |
voice | Sí | line |
speaker | Sí | cadena |
line_key | Sí | alguien |
conditions | - | alguien |
description_key | - | alguien |
name_key | - | alguien |
reveals | - | alguien |
Un registro con kind: dialogue_node:
| Campo | Necesario | Valores |
|---|---|---|
kind | Sí | dialogue_node |
id | Sí | cadena |
graph | Sí | alguien |
voice | Sí | narration |
line_key | Sí | alguien |
conditions | - | alguien |
description_key | - | alguien |
name_key | - | alguien |
reveals | - | alguien |
Un registro con kind: dialogue_node:
| Campo | Necesario | Valores |
|---|---|---|
kind | Sí | dialogue_node |
id | Sí | cadena |
graph | Sí | alguien |
voice | Sí | end |
conditions | - | alguien |
description_key | - | alguien |
line_key | - | alguien |
name_key | - | alguien |
reveals | - | alguien |
Un registro con kind: dialogue_option:
| Campo | Necesario | Valores |
|---|---|---|
kind | Sí | dialogue_option |
id | Sí | cadena |
node | Sí | cadena |
label_key | Sí | texto, fixed shape |
goto | Sí | cadena |
commands | - | lista de cualquier cosa |
conditions | - | lista de cualquier cosa |
description_key | - | texto, fixed shape |
name_key | - | texto, fixed shape |
En un archivo llamado gate_toll.json, o el nombre .json que quieras dentro de esa carpeta:
a dialogue record, under content/narrative/dialogue
[
{
"kind": "dialogue_graph",
"id": "northern_reach:gate_toll",
"entry": "northern_reach:gate_open",
"speaker": "gate_warden",
"name_key": "TALK_PACK_GATE_TOLL_NAME",
"description_key": "TALK_PACK_GATE_TOLL_DESC"
},
{
"kind": "dialogue_node",
"id": "northern_reach:gate_open",
"graph": "northern_reach:gate_toll",
"voice": "line",
"speaker": "gate_warden",
"line_key": "TALK_PACK_GATE_OPEN"
},
{
"kind": "dialogue_option",
"id": "northern_reach:opt_pay_the_toll",
"node": "northern_reach:gate_open",
"label_key": "TALK_PACK_OPT_PAY",
"goto": "northern_reach:gate_paid",
"commands": [
{
"step": "pay_coin",
"coin": 25
},
{
"step": "change_relation",
"subject": "player",
"target": "gate_warden",
"delta": 4
}
]
}
]El encuentro contiene 12 registros; Se muestran 3.
locales
Las palabras que lee un jugador, en CSV con una columna por idioma: las claves propias del paquete, y las del juego donde el paquete declara sobrescribir.
- Estado Listo para usar
- Carpeta
content/locale - Informe
modding_locale_report - Si un reproductor te desinstala
preserve_inert_reference. Un guardado nombra el disco, nunca las palabras que lo dicen, por lo que un paquete retirado entre dos sesiones cuesta una traducción y nada. La clave se conserva y aparece, lo que se lee como una traducción faltante en lugar de contenido faltante.
Columnas. Una columna que esta tabla no nombra se rechaza con el registro.
| Columna | Necesario | Valores |
|---|---|---|
key | Sí | texto, id |
en | - | cadena |
En un archivo llamado words.csv. El nombre del archivo es la mitad de la dirección y la identificación de la línea es la otra mitad, por lo que dos archivos pueden contener la misma identificación de línea sin colisionar:
a locales file
key,en,it
word_pack:GOOD_FROST_SALT,Frost Salt,Sale di Brinalore
Entradas del códice: lugares, personas, eventos, costumbres y cosas sobre las que el mundo cuenta historias. Una entrada cargada no es una entrada conocida.
- Estado Listo para usar
- Carpeta
content/narrative/lore - Registros enrutados para el campo
id - Informe
modding_lore_report - Si un reproductor te desinstala
preserve_inert_reference. Una entrada del Códice que un jugador ha leído es algo que ha visto. Quitarlo borra parte de lo que sabe sobre un mundo en el que pasó un tiempo, y las misiones y otras entradas apuntan a la identificación.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
category | Sí | place, person, event, custom, thing |
title_key | Sí | cadena |
body_key | Sí | cadena |
chronology_index | - | completo |
citation_key | - | cadena |
content_warnings | - | lista de cadenas |
era | - | cadena |
relates_to | - | lista de cadenas |
requires | - | lista de cadenas |
reveals | - | lista de cadenas |
En un archivo llamado lore.json, o el nombre .json que quieras dentro de esa carpeta:
a lore record, under content/narrative/lore
[
{
"id": "northern_reach:the_drowned_causeway",
"category": "place",
"title_key": "STORY_PACK_DROWNED_CAUSEWAY_TITLE",
"body_key": "STORY_PACK_DROWNED_CAUSEWAY_BODY",
"era": "before_the_mark",
"citation_key": "STORY_PACK_CAUSEWAY_CITATION"
},
{
"id": "northern_reach:the_tide_watch",
"category": "custom",
"title_key": "STORY_PACK_TIDE_WATCH_TITLE",
"body_key": "STORY_PACK_TIDE_WATCH_BODY",
"relates_to": [
"northern_reach:the_drowned_causeway"
]
}
]mr_lines
Líneas estructuradas de realismo medieval, enrutadas por identificación de archivo y línea en lugar de un campo de identificación en JSON.
- Estado Listo para usar
- Carpeta
content/medieval_realism/structured - Informe
modding_mr_lines_report - Si un reproductor te desinstala
drop_optional_presentation. Un chiste de colores al que nada hace referencia. Quitarlo no cuesta nada y conservarlo mostraría una cadena vacía.
Columnas. Se permite una columna sin nombre en esta tabla y debe ser un valor simple en lugar de una lista u objeto.
| Columna | Necesario | Valores |
|---|---|---|
line_id | Sí | texto, id |
mechanical_hint | - | cadena |
public_label | - | cadena |
public_line | - | cadena |
public_summary_line | - | cadena |
speaker | - | cadena |
tone | - | cadena |
voice | - | cadena |
Cada registro necesita al menos uno de public_line, public_label, public_summary_line.
Estos nombres son rechazados sin lugar a dudas, contengan lo que contengan: unsafe_example, unsafe_reason, audit_note, expected_block_reason, script, scene, resource_path. Algunas son las columnas de verificación con las que escriben quienes juegan y las otras son los nombres en forma de código que Lo que un mod nunca puede hacer rechaza por todas partes. Un registro que lo contiene es rechazado en lugar de ser borrado silenciosamente.
En un archivo llamado MR_L03_TAVERN_INN_LINES.csv. El nombre del archivo es la mitad de la dirección y la identificación de la línea es la otra mitad, por lo que dos archivos pueden contener la misma identificación de línea sin colisionar:
a mr_lines file
line_id,tavern_state,speaker_role,tone,public_line,mechanical_hint
northern_reach:tavern_extra_01,evening_rush,innkeeper,welcoming,"Warm bread and a clean cup if you've the coin for it, friend.",food_onlyprogress
Registros de progresión del jugador: objetivos, perfiles de dificultad seguros y perfiles de partido dentro de las reglas del anfitrión.
- Estado Listo para usar
- Carpeta
content/player/progress - Registros enrutados para el campo
id - Informe nada suyo;
modding_preflight_reportse encarga de ello - Si un reproductor te desinstala
preserve_inert_reference. Los logros obtenidos y los perfiles de coincidencia elegidos permanecen nombrados cuando su paquete está ausente; Quitarlos en silencio reescribiría la historia del jugador o el contrato del partido.
Campos. Esta familia contiene más de un tipo de registro y cada tipo se compara con su propia lista. Un campo que esta tabla no nombra se rechaza junto con el registro.
Un registro con kind: achievement:
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
kind | Sí | achievement |
name_key | Sí | cadena |
description_key | Sí | cadena |
condition | Sí | lista de objetos |
campaign | - | cadena |
hidden | - | booleano |
icon | - | banner, blade, coin, crown, hand, road, … |
Un registro con kind: difficulty_profile:
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
kind | Sí | difficulty_profile |
name_key | Sí | cadena |
modifiers | Sí | objeto |
campaign | - | cadena |
description_key | - | cadena |
permadeath | - | booleano |
Un registro con kind: run_profile:
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
kind | Sí | run_profile |
name_key | Sí | cadena |
difficulty | Sí | cadena |
campaign | - | cadena |
description_key | - | cadena |
seed_stream | - | cadena |
starting_origin | - | cadena |
En un archivo llamado progress.json, o el nombre .json que quieras dentro de esa carpeta:
a progress record, under content/player/progress
[
{
"id": "northern_reach:hard_tide",
"kind": "difficulty_profile",
"name_key": "DIFF_HARD_TIDE",
"description_key": "DIFF_HARD_TIDE_DESC",
"modifiers": {
"enemy_strength_percent": 140,
"coin_gain_percent": 80
},
"permadeath": true
},
{
"id": "northern_reach:tide_run",
"kind": "run_profile",
"name_key": "RUN_TIDE",
"description_key": "RUN_TIDE_DESC",
"difficulty": "northern_reach:hard_tide",
"seed_stream": "tide"
},
{
"id": "northern_reach:held_tide",
"kind": "achievement",
"name_key": "ACH_HELD_TIDE",
"description_key": "ACH_HELD_TIDE_DESC",
"condition": [
{
"when": "days_survived",
"count": 30
}
],
"icon": "tower"
}
]quest_metadata
Registros de metadatos de Quest, indexados por quest_id en lugar de id.
- Estado Listo para usar
- Carpeta
content/narrative/quest_metadata - Registros enrutados para el campo
quest_id - Informe
modding_quest_metadata_report - Si un reproductor te desinstala
preserve_inert_reference. Describe misiones que ya podrían reducirse a una lápida; Quitarlo los dejaría sin descripción en lugar de ausentes.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
quest_id | Sí | texto, id |
arc_id | - | texto, id |
choice_valence | - | cadena |
consequence_hooks | - | lista de cadenas |
difficulty_band | - | cadena |
faction_context | - | cadena |
failure_consequence | - | cadena |
moral_pressure | - | cadena |
notification_policy | - | cadena |
novelty_tags | - | lista de cadenas |
player_model_tags | - | lista de cadenas |
quest_role | - | cadena |
replay_suppression_key | - | cadena |
reward_intent | - | cadena |
story_turn_role | - | cadena |
urgency_band | - | cadena |
world_reason | - | cadena |
En un archivo llamado quests.json, o el nombre .json que quieras dentro de esa carpeta:
a quest_metadata record, under content/narrative/quest_metadata
[
{
"quest_id": "northern_reach:tavern_errand",
"world_reason": "settlement_shortage",
"quest_role": "recovery",
"difficulty_band": "standard",
"urgency_band": "soon"
}
]quest_plans
Planes de misión como registros: los arcos, misiones, objetivos y finales que escribe un paquete y a partir de los cuales el juego construye sus propias misiones. El formulario de registro de una misión, junto a los recursos escritos a mano en lugar de en su lugar.
- Estado Listo para usar
- Carpeta
content/narrative/quest_plans - Registros enrutados para el campo
id - Informe
modding_quest_plan_report - Si un reproductor te desinstala
preserve_inert_reference. Un plan construye las mismas misiones que ejecuta el juego, por lo que uno retirado deja el mismo agujero que dejaría la escritura a mano. El progreso es lo único que un jugador no puede reconstruir: una misión no resuelta se informa y nunca se completa o se cancela silenciosamente.
Campos. Esta familia contiene más de un tipo de registro y cada tipo se compara con su propia lista. Un campo que esta tabla no nombra se rechaza junto con el registro.
Un registro con kind: arc:
| Campo | Necesario | Valores |
|---|---|---|
kind | Sí | alguien |
id | Sí | texto, id |
stages | Sí | lista |
description_key | - | texto, fixed shape |
name_key | - | texto, fixed shape |
Un registro con kind: ending:
| Campo | Necesario | Valores |
|---|---|---|
kind | Sí | alguien |
id | Sí | texto, id |
arc | Sí | cadena |
requires | Sí | lista |
description_key | - | texto, fixed shape |
epilogue_key | - | texto, fixed shape |
name_key | - | texto, fixed shape |
Un registro con kind: objective:
| Campo | Necesario | Valores |
|---|---|---|
kind | Sí | alguien |
id | Sí | texto, id |
quest | Sí | cadena |
goal | Sí | collect_item, defeat_unit, defend_place, deliver_item, earn_coin, escort_unit, … |
count | - | número entero de 1 a 999 |
description_key | - | texto, fixed shape |
name_key | - | texto, fixed shape |
optional_step | - | booleano |
target | - | cadena |
Un registro con kind: quest:
| Campo | Necesario | Valores |
|---|---|---|
kind | Sí | alguien |
id | Sí | texto, id |
name_key | Sí | texto, fixed shape |
giver | Sí | cadena |
objectives | Sí | lista |
deadline_days | - | número entero de 1 a 3650 |
description_key | - | texto, fixed shape |
forfeits | - | lista de cualquier cosa |
in_arc | - | cadena |
rewards | - | lista de cualquier cosa |
En un archivo llamado the_long_winter.json, o el nombre .json que quieras dentro de esa carpeta:
a quest_plans record, under content/narrative/quest_plans
[
{
"kind": "arc",
"id": "northern_reach:the_long_winter",
"name_key": "northern_reach.arc.the_long_winter.name",
"stages": [
"northern_reach:bring_the_grain"
]
},
{
"kind": "quest",
"id": "northern_reach:bring_the_grain",
"name_key": "northern_reach.quest.bring_the_grain.name",
"description_key": "northern_reach.quest.bring_the_grain.description",
"giver": "northern_reach:the_reeve",
"in_arc": "northern_reach:the_long_winter",
"objectives": [
"northern_reach:gather_grain",
"northern_reach:pay_the_toll"
],
"deadline_days": 30,
"rewards": [
{
"grant": "receive_coin",
"coin": 250
},
{
"grant": "give_item",
"item": "northern_reach:reeves_seal",
"count": 1
}
]
},
{
"kind": "objective",
"id": "northern_reach:gather_grain",
"quest": "northern_reach:bring_the_grain",
"goal": "collect_item",
"target": "northern_reach:winter_grain",
"count": 40,
"name_key": "northern_reach.objective.gather_grain.name"
}
]El accesorio contiene 5 registros; Se muestran 3.
quests
Recursos de misión escritos a mano, cargados por ruta en lugar de interpretados como registros. Un paquete que quiere su propia misión escribe quest_plans.
- Estado Comprobado, aún no instalado
- Carpeta
content/narrative/quests - Informe nada suyo;
modding_preflight_reportse encarga de ello - Si un reproductor te desinstala
preserve_inert_reference. El progreso es lo único que un jugador no puede reconstruir. Una misión no resuelta se informa y nunca se completa o se cancela silenciosamente.
Esta familia se carga por ruta en lugar de leerse como un registro, y un paquete no puede transportar el archivo que desea; consulte [Lo que un mod nunca puede hacer] (#qué-un-mod-nunca-puede-hacer). En su lugar, escriba quest_plans.
scenes
Escenas escenificadas: la habitación, quién está en ella y las líneas que se desarrollan en orden. Es el único contenido que le quita el control al jugador, razón por la cual una secuencia que nunca llega a end se rechaza en lugar de reproducirse. Los chistes y los accesorios son nombres tomados de listas publicadas; Aquí no se cargan escenas de Godot, recursos ni guiones.
- Estado Listo para usar
- Carpeta
content/narrative/scenes - Registros enrutados para el campo
id - Informe
modding_scene_report - Si un reproductor te desinstala
preserve_inert_reference. Un guardado registra lo que hizo una escena (un nombre elegido, una misión movida, una puerta abierta), nunca el hecho de que fue vista. Se juega y finaliza en una sola sesión, por lo que un paquete que sale cuesta la escena y nunca una consecuencia de haberlo visto. Reemplazarlo representaría algo que el autor nunca escribió bajo el nombre de algo que escribió.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
beats | Sí | lista de cualquier cosa |
cast | - | lista de cualquier cosa |
name_key | - | alguien |
stage | - | objeto |
where | - | cadena |
En un archivo llamado scenes.json, o el nombre .json que quieras dentro de esa carpeta:
a scenes record, under content/narrative/scenes
[
{
"id": "northern_reach:tollhouse_wake",
"name_key": "STAGE_PACK_TOLLHOUSE_WAKE",
"stage": {
"room": [
880,
600
],
"light": "candle",
"props": [
{
"prop": "bed",
"at": "bedside"
},
{
"prop": "storage",
"at": "east",
"label_key": "STAGE_PACK_BELONGINGS"
},
{
"prop": "light_marker",
"at": "north",
"light": "candle"
},
{
"prop": "walkway",
"at": "bedside",
"to": "door"
}
]
},
"cast": [
{
"actor": "northern_reach:tollkeeper",
"name_key": "STAGE_PACK_TOLLKEEPER",
"sprite": "default",
"at": "bedside"
}
],
"beats": [
{
"beat": "lock_player"
},
{
"beat": "fade_in",
"seconds": 2.0
},
{
"beat": "say",
"actor": "northern_reach:tollkeeper",
"line_key": "STAGE_PACK_WAKE_1"
},
{
"beat": "wait",
"seconds": 0.8
},
{
"beat": "say",
"actor": "northern_reach:tollkeeper",
"line_key": "STAGE_PACK_WAKE_2"
},
{
"beat": "play_cue",
"cue": "northern_reach:door_latch"
},
{
"beat": "walk_to",
"actor": "northern_reach:tollkeeper",
"anchor": "door"
},
{
"beat": "remove_actor",
"actor": "northern_reach:tollkeeper"
},
{
"beat": "show_exit"
},
{
"beat": "unlock_player"
},
{
"beat": "end"
}
]
}
]Como ves y oyes todo
7 familias: audio, effects, fonts, images, presentation_bindings, screens, themes.
audio
Sonidos que lleva un paquete, nombrados por id: música, ambiente, efectos y voz, cada uno apuntando a un archivo dentro de su propia carpeta y declarando el rol que lo delimita.
- Estado Validado, nada lo consume todavía
- Carpeta
content/assets/audio - Registros enrutados para el campo
id - Informe
modding_audio_report - Si un reproductor te desinstala
preserve_inert_reference. Un guardado nombra el tema y nunca el sonido encima de él, por lo que un paquete retirado entre dos sesiones cuesta una atmósfera y nada. La referencia se conserva y se informa: silencio sin nada que decir por qué es precisamente el estado que esta familia desea evitar.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
file | Sí | texto, fixed shape |
codec | Sí | ogg, wav |
role | Sí | music, ambience, sfx, voice |
duration_seconds | - | número, 0 o más |
sha256 | - | texto, fixed shape |
subtitle_key | - | cadena |
En el archivo audio.json, que es el único archivo a través del cual se lee esta carpeta:
a audio record, under content/assets/audio
[
{
"id": "northern_reach:hearth_hum",
"file": "hearth_hum.wav",
"codec": "wav",
"role": "ambience",
"duration_seconds": 0.25,
"sha256": "23fc92432963f74bd638f38ea9d7ddb475853f022810bdc8b344269bf43d5830"
}
]effects
Clima, polvo, chispas y luces, compuestos a partir de los modelos que el presentador pone a disposición. Un paquete nombra un modelo y establece parámetros dentro de rangos declarados; no hay ningún campo, en ninguna parte, que contenga un sombreador, una escena o un guión, y eso es lo que permite que un paquete extraño solicite fuego sin poder solicitar un programa.
- Estado Listo para usar
- Carpeta
content/assets/effects - Registros enrutados para el campo
id - Informe
modding_effect_report - Si un reproductor te desinstala
preserve_inert_reference. Nada en un guardado nombra un efecto. El aire vuelve a lo que dibuja el juego base cuando el paquete se va, lo que cuesta un aspecto y nada que el jugador posea.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
template | Sí | dust_drift, lightning_flash, rain_sheet, smoke_column, snow_drift, spark_burst, … |
parameters | - | objeto |
priority | - | entero de 0 a 100 |
En un archivo llamado effects.json, o el nombre .json que quieras dentro de esa carpeta:
a effects record, under content/assets/effects
[
{
"id": "northern_reach:moor_drift",
"template": "dust_drift",
"parameters": {
"amount": 64,
"lifetime": 6,
"scale": 2,
"wind": 4,
"colour": "#c8bfa8"
},
"priority": 40
}
]fonts
Tipos de letra que lleva un paquete, nombrados por id: el archivo, el tamaño en el que están dibujados y los idiomas cuyos glifos llevan. La portada, en cambio, pretende estar expuesta, porque un personaje al que le faltan los glifos de una lengua no falla: dibuja cuadritos y en la pantalla se lee como una traducción que alguien dejó a medio terminar.
- Estado Validado, nada lo consume todavía
- Carpeta
content/assets/fonts - Registros enrutados para el campo
id - Informe
modding_font_report - Si un reproductor te desinstala
preserve_inert_reference. Nada en un guardado nombra a un personaje. La interfaz vuelve a la fuente del kit de herramientas cuando el paquete sale, que es la única que cualquier autor tenía que elegir.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
file | Sí | texto, fixed shape |
format | Sí | ttf, otf |
sizes | Sí | lista de números enteros del 8 al 96 |
covers | Sí | lista |
fallback_font | Sí | cadena |
glyphs | - | lista |
oversampling | - | número entero de 1 a 4 |
sha256 | - | texto, fixed shape |
En el archivo fonts.json, que es el único archivo a través del cual se lee esta carpeta:
a fonts record, under content/assets/fonts
[
{
"id": "northern_reach:plain",
"file": "plain.ttf",
"format": "ttf",
"sizes": [
12,
16,
24
],
"oversampling": 1,
"covers": [
"en"
],
"fallback_font": "Segoe UI",
"sha256": "613b1d24f9f8b0365a94f01214155af8e87ca72aa6633befd5e0ee05b3dc4122"
}
]images
Imágenes que trae un paquete, nombradas por id: íconos, retratos y hojas de sprites, cada una apuntando a un archivo dentro de su propia carpeta.
- Estado Listo para usar
- Carpeta
content/assets/images - Registros enrutados para el campo
id - Informe
modding_image_report - Si un reproductor te desinstala
preserve_inert_reference. Un guardado nombra objetos y personas, nunca una imagen de uno de ellos, por lo que una imagen que deja de resolverse cuesta un dibujo y no una cosa. La referencia se conserva y se informa: reemplazarla con arte de otro paquete le mostraría al jugador algo que ningún autor eligió, y eliminar la identificación silenciosamente haría que el ícono faltante pareciera un defecto de diseño.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
file | Sí | texto, fixed shape |
format | Sí | png, webp |
frame_columns | - | número entero de 1 a 256 |
frame_rows | - | número entero de 1 a 256 |
sha256 | - | texto, fixed shape |
En el archivo images.json, que es el único archivo a través del cual se lee esta carpeta:
a images record, under content/assets/images
[
{
"id": "northern_reach:salt_pouch",
"file": "salt_pouch.png",
"format": "png"
}
]presentation_bindings
Qué recurso del paquete ocupa qué espacio y en qué tema: el ícono de un objeto, el sprite de una unidad o mosaico, el estandarte de una facción, tanto para el contenido del paquete como para el del juego base.
- Estado Listo para usar
- Carpeta
content/presentation/bindings - Registros enrutados para el campo
id - Informe nada suyo;
modding_preflight_reportse encarga de ello - Si un reproductor te desinstala
preserve_inert_reference. Un guardado nombra al sujeto -el objeto, la persona, la pieza- y nunca qué imagen lo vistió, por lo que un enlace que deja de resolverse cuesta un dibujo y no una cosa. La referencia se conserva y se informa: el tema vuelve al arte que ya tenía la construcción, que es la única respuesta que ningún autor tuvo que elegir.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
subject | Sí | texto, id |
kind | Sí | building, faction, interface, item, region, tile, … |
slot | Sí | ambience, banner, effect, font, icon, portrait, … |
cue | Sí | texto, id |
alternative_key | - | cadena |
En un archivo llamado bindings.json, o el nombre .json que quieras dentro de esa carpeta:
a presentation_bindings record, under content/presentation/bindings
[
{
"op": "add",
"id": "northern_reach:cloak_icon",
"subject": "wool_cloak",
"kind": "item",
"slot": "icon",
"cue": "northern_reach:cloak_plain",
"alternative_key": "item_wool_cloak_icon_alt"
},
{
"op": "add",
"id": "northern_reach:cloak_icon_winter",
"subject": "wool_cloak",
"kind": "item",
"slot": "icon",
"cue": "northern_reach:cloak_snowy",
"alternative_key": "item_wool_cloak_icon_alt",
"when": {
"season": {
"is": "winter"
}
}
}
]screens
Diseños de pantalla: qué secciones encajan en qué panel de pantalla ya tiene el juego y en qué orden. Tiene piezas que esta compilación dibuja y no puede agregar ninguna: una nueva pantalla necesitaría widgets, fuentes de datos y controladores de clics, que en conjunto son un lenguaje de programación.
- Estado Listo para usar
- Carpeta
content/ui/screens - Registros enrutados para el campo
id - Informe
modding_screen_report - Si un reproductor te desinstala
preserve_inert_reference. Nada en un rescate menciona una disposición. Decide cómo se dibuja una página mientras se carga el paquete, y la página vuelve al diseño que esta compilación lleva consigo cuando se va: cuesta un aspecto y nada que posea el jugador.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
screen | Sí | character_sheet |
panels | Sí | objeto |
En un archivo llamado screens.json, o el nombre .json que quieras dentro de esa carpeta:
a screens record, under content/ui/screens
[
{
"id": "northern_reach:character_sheet",
"screen": "character_sheet",
"panels": {
"header": [
"header"
],
"left": [
"vitals",
"combat"
],
"middle": [
"attributes",
"skills"
],
"right": [
"service",
"weight",
"background"
]
}
}
]themes
Paletas de interfaz como fichas: colores, tamaños y espacios con nombre, con pares cuyo contraste un jugador debe poder leer. Nunca una escena, guión o ruta de recursos.
- Estado Listo para usar
- Carpeta
content/assets/themes - Registros enrutados para el campo
id - Informe
modding_theme_report - Si un reproductor te desinstala
preserve_inert_reference. Nada en un guardado nombra un tema. La interfaz vuelve a los colores del kit de herramientas cuando sale el paquete, que es la única paleta que cualquier autor ha tenido que elegir.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
id | Sí | texto, id |
tokens | Sí | objeto |
contrast_pairs | - | lista de objetos |
En un archivo llamado themes.json, o el nombre .json que quieras dentro de esa carpeta:
a themes record, under content/assets/themes
[
{
"id": "northern_reach:dusk",
"tokens": {
"bg_deep": {
"kind": "colour",
"value": "#12131a"
},
"bg_panel": {
"kind": "colour",
"value": "#1b1c26"
},
"bg_panel_hi": {
"kind": "colour",
"value": "#262838"
},
"text": {
"kind": "colour",
"value": "#e8e2d0"
},
"text_bright": {
"kind": "colour",
"value": "#f4efe2"
},
"text_mute": {
"kind": "colour",
"value": "#6f6a80"
},
"border": {
"kind": "colour",
"value": "#7f6ab0"
},
"border_dark": {
"kind": "colour",
"value": "#14151c"
},
"border_soft": {
"kind": "colour",
"value": "#4a4560"
},
"danger": {
"kind": "colour",
"value": "#d4564b"
},
"success": {
"kind": "colour",
"value": "#7fc46a"
},
"warning": {
"kind": "colour",
"value": "#e0b13c"
},
"accent_player": {
"kind": "colour",
"value": "#6f97e8"
},
"accent_enemy": {
"kind": "colour",
"value": "#c94a4a"
}
},
"contrast_pairs": [
{
"text": "#e8e2d0",
"background": "#12131a"
},
{
"text": "#f4efe2",
"background": "#1b1c26"
},
{
"text": "#e8e2d0",
"background": "#262838"
}
]
}
]¿Qué controla el jugador y qué observa?
3 familias: adaptive, input_bindings, settings.
adaptive
Perfiles que analizan cómo va un partido y sugieren un enfoque diferente. El resultado es un consejo y nunca un cambio: un perfil que pudiera actuar sería lo único que trae un paquete capaz de alterar una partida sin que el jugador o el invitado lo haya pedido, y en un diff quedaría exactamente como una tabla de ajustes. Las entradas son una lista publicada de agregados del juego, cada uno de los cuales es un recuento o promedio que el juego ya tiene sobre sí mismo.
- Estado Listo para usar
- Carpeta
content/player/adaptive - Registros enrutados para el campo
id - Informe
modding_adaptive_report - Si un reproductor te desinstala
drop_optional_presentation. No guardar nombres de un perfil. Lo que ha tocado un perfil es un multiplicador recalculado por los mutadores activos cada vez que cambian, por lo que un paquete retirado deja de ser consultado y el juego vuelve exactamente a lo que el jugador había elegido. Nada se preserva, por lo tanto no hay nada que preservar.
Campos. Esta familia contiene más de un tipo de registro y cada tipo se compara con su propia lista. Un campo que esta tabla no nombra se rechaza junto con el registro.
Un registro con kind: adaptive_profile:
| Campo | Necesario | Valores |
|---|---|---|
kind | Sí | alguien |
id | Sí | texto, id |
name_key | Sí | texto, fixed shape |
policy | Sí | enemy_composition, event_cadence, hint_frequency, pace_economy, pace_encounters, weather_variety |
reads | Sí | lista |
fallback_policy | Sí | enemy_composition, event_cadence, hint_frequency, pace_economy, pace_encounters, weather_variety |
confidence_floor_percent | - | número entero de 1 a 100 |
description_key | - | texto, fixed shape |
sample_days | - | número entero de 1 a 365 |
Un registro con kind: threshold_set:
| Campo | Necesario | Valores |
|---|---|---|
kind | Sí | alguien |
id | Sí | texto, id |
profile | Sí | texto, id |
thresholds | Sí | lista de objetos |
description_key | - | texto, fixed shape |
name_key | - | texto, fixed shape |
En un archivo llamado adaptive.json, o el nombre .json que quieras dentro de esa carpeta:
a adaptive record, under content/player/adaptive
[
{
"kind": "adaptive_profile",
"id": "northern_reach:hard_roads",
"name_key": "ADAPTIVE_HARD_ROADS",
"description_key": "ADAPTIVE_HARD_ROADS_BODY",
"policy": "pace_encounters",
"reads": [
"battles_won_ratio",
"days_survived",
"party_size"
],
"fallback_policy": "event_cadence",
"confidence_floor_percent": 60,
"sample_days": 14
},
{
"kind": "threshold_set",
"id": "northern_reach:hard_roads_lines",
"profile": "northern_reach:hard_roads",
"name_key": "ADAPTIVE_HARD_ROADS_LINES",
"thresholds": [
{
"signal": "battles_won_ratio",
"above": 80,
"advise": "raise"
},
{
"signal": "battles_won_ratio",
"below": 35,
"advise": "lower"
},
{
"signal": "party_size",
"below": 3,
"advise": "lower"
},
{
"signal": "days_survived",
"above": 60,
"advise": "hold"
}
]
}
]input_bindings
Acciones propias de un paquete, con la clave que deseen. El jugador decide: una sugerencia que termina en una combinación que ya había asignado pierde, y la acción ocurre sin botón, porque un botón que silenciosamente hace otra cosa es peor que un botón que no hace nada.
- Estado Listo para usar
- Carpeta
content/input - Registros enrutados para el campo
action_id - Informe
modding_input_report - Si un reproductor te desinstala
preserve_inert_reference. La reasignación de un jugador permanece almacenada bajo el ID de acción, por lo que al reinstalar el paquete se encuentra el botón donde lo colocaste. La acción en sí se elimina del mapa de comandos cuando el paquete sale, por lo que la pantalla de asignación nunca muestra algo que no responda a nada.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
action_id | Sí | texto, id |
label_key | Sí | cadena |
context | Sí | exploration, combat, menu, global |
suggested_keyboard | Sí | cadena |
suggested_controller | - | cadena |
En un archivo llamado bindings.json, o el nombre .json que quieras dentro de esa carpeta:
a input_bindings record, under content/input
[
{
"action_id": "northern_reach:call_scout",
"label_key": "KEY_PACK_CALL_SCOUT",
"context": "exploration",
"suggested_keyboard": "f9"
}
]settings
Opciones que un jugador puede cambiar, declaradas en lugar de sorteadas. Un paquete dice cuál es la opción, qué valores puede tener y dónde reside el valor; el control lo construye el huésped. Nada que cruce este límite es un control o un script, y esa es la única razón por la que un menú de configuración puede mostrar las opciones de un extraño sin ejecutar su código.
- Estado Listo para usar
- Carpeta
content/settings - Registros enrutados para el campo
key - Informe
modding_settings_report - Si un reproductor te desinstala
preserve_inert_reference. Un valor almacenado permanece bajo su clave, por lo que al reinstalar el paquete, el jugador elige dónde lo dejó. Lo que el paquete deja tras de sí es una línea en un perfil que nadie lee: no cuesta nada y preserva una elección que ha hecho el jugador.
Campos. Un campo al que esta tabla no nombra se rechaza con el registro.
| Campo | Necesario | Valores |
|---|---|---|
key | Sí | texto, id |
type | Sí | bool, int, float, string, enum |
default | Sí | alguien |
scope | Sí | installation, campaign, presentation |
label_key | Sí | cadena |
help_key | - | cadena |
max_length | - | entero de 1 a 4096 |
maximum | - | número |
migrates_from | - | texto, id |
minimum | - | número |
options | - | lista de cadenas |
requires_restart | - | booleano |
secret | - | booleano |
En un archivo llamado settings.json, o el nombre .json que quieras dentro de esa carpeta:
a settings record, under content/settings
[
{
"key": "northern_reach:patrol_density",
"type": "int",
"default": 3,
"minimum": 1,
"maximum": 9,
"scope": "campaign",
"label_key": "OPTION_PACK_PATROL_DENSITY",
"help_key": "OPTION_PACK_PATROL_DENSITY_HELP"
},
{
"key": "northern_reach:show_road_names",
"type": "bool",
"default": true,
"scope": "presentation",
"label_key": "OPTION_PACK_SHOW_ROAD_NAMES"
}
]Atajos de consola
Estos son un atajo, no un paso. Todo lo que aparece a continuación tiene un lugar en la pantalla Mods, que es donde va la ruta normal y donde verá cualquiera que haya descargado su paquete. La consola es más rápida cuando estás iterando y ya está abierta, y solo existe en una versión de depuración: una copia publicada del juego no tiene consola, por lo que nada de lo que un autor de paquete necesita puede vivir aquí solo.
| Dominio | Lo mismo en la pantalla Mod. |
|---|---|
modding_open_folder | la ruta en la parte superior y el botón al lado |
modding_manifest_report | la columna de estado y la fila debajo de cada fila |
modding_<family>_report | los recuentos de cada paquete y Mostrar detalles |
modding_preflight_report | Comprueba compatibilidad |
modding_roots_report, modding_safety_report | Copia el informe |
modding_reload | No hay botones en la pantalla. Reiniciar el juego hace lo mismo y es la única manera de tener una versión publicada; esto le ahorra tener que reiniciar mientras itera. Es la única línea aquí que es más conveniente que un atajo a algo que la pantalla ya hace. |
Comienza en modding_manifest_report: ¿el juego ve tu paquete y en qué estado? - luego modding_preflight_report para obtener un veredicto único sobre todo lo instalado. Luego el informe de la familia individual.
modding_reload vuelve a leer tus archivos sin reiniciar. Edita, cambia de ventana, escribe el comando y mira. Reconstruye lo que no está retenido — bindings, efectos e imágenes — y nombra cada familia que dejó intacta, porque una partida se apoya en los registros que una partida guardada puede nombrar:
what the game prints back
HELD BY THE RUN items: edited files are read on the next loadmodding_reload all vuelve a leer todo y muestra una pantalla de presentación sin ningún juego en progreso. modding_condition_report imprime lo que el juego ahora puede responder para un when y lo que no puede.
| Dominio | ¿Qué te dice? |
|---|---|
modding_roots_report | Raíces y huellas de las modificaciones de datos. |
modding_manifest_report | Estados de modificación (activo/inválido/ignorado/en conflicto) |
modding_fingerprint_report | Huellas deterministas de guardados (save_wired=no) |
modding_safety_report | Postura segura (modificaciones de comportamiento desactivadas, archivos bloqueados) |
modding_preflight_report | Veredicto VERDE/ROJO en todas las modificaciones activas |
modding_packaging_report | Detección PCK/ZIP de nivel 2 (desactivada de forma predeterminada) |
modding_campaign_report | Modding_campaign_report [id] - campañas instaladas de solo lectura; con una identificación, vas allí |
modding_condition_report | ¿Qué publica el mundo para condiciones récord? |
modding_reload | Modding_reload [todos] - releer paquetes; all solo si no hay ningún juego en curso |
modding_binding_report | Enlaces de envío: vinculados/rechazados/anulados |
modding_open_folder | Crea (si es necesario) y abre la carpeta de modificaciones del usuario. |
Herramientas sin conexión
Estas herramientas son para autores y automatización de publicaciones. Se incluyen en el checkout público de Bonemark; los jugadores que instalan un mod publicado no necesitan Python ni Godot. Si escribes un mod, clona la versión correspondiente desde github.com/tallowgames/Bonemark, mantén tu paquete de trabajo fuera de la carpeta mods del jugador y ejecuta los comandos siguientes desde ese checkout. El juego sigue siendo la autoridad final del runtime.
Python 3.10 o posterior; Godot solo para el carril de ejecución. Mantenga su paquete fuera de la carpeta mods del reproductor e intente copiarlo.
a command line
python tools/modding/new_mod.py --list
python tools/modding/new_mod.py --id my_mod --family goods --family itemsEscribe un paquete que pasa la validación incluso antes de que hayas escrito algo: un mod.json precompilado, un registro de trabajo para cada familia que solicitaste y un README con los siguientes dos comandos. Los registros provienen de dispositivos que la construcción ya verifica para esas familias, por lo que un motor de arranque que deja de funcionar provoca la misma verificación que hace que el dispositivo falle, en lugar de pudrirse dentro de un modelo. Se niega a escribir en una carpeta llamada mods.
a command line
python tools/quality/validate_mod_data.py --root "<mod-root>"
python tools/quality/validate_mod_data.py --strict --root "<mod-root>"Verifique mod.json, carpetas familiares, identificaciones, esquemas, referencias, límites y cargas útiles bloqueadas. --strict convierte las advertencias en fallas.
Comparar la superficie de modificación con la versión
Cuando el juego cambie, compare la instantánea de la superficie archivada antes de actualizar un paquete. Contiene un resumen más campos y operaciones para cada familia pública, por lo que el resultado indica qué familia cambió y por qué:
a command line
python tools/quality/modding_surface_contract.py --json
python tools/quality/modding_surface_contract.py --before "<previous-build>/game/games/bonemark/modding/data/mod_surface_contract.json" --jsonLa diferencia es unchanged, additive o breaking. Los motivos del fallo son explícitos: field_removed, required_added, type_changed, default_changed, constraint_changed, operation_removed y root_changed, format_changed, id_field_changed, catalogue_changed, family_removed y contract_major_changed_without_new_id. Nombre de modificación compatible field_added, required_removed, operation_added o family_added. El comando sin --before también verifica la línea base almacenada. Si la superficie actual se ha movido, la auditoría falla hasta que un mantenedor examina los resúmenes exactos de antes y después en tools/quality/modding_surface_contract_changes.json; un cambio importante también debe registrar cada motivo, la decisión, la nota de migración y el revisor. La promoción de una instantánea revisada intencionalmente es explícita:
a command line
python tools/quality/modding_surface_contract.py --write-baselineEsta es una verificación de lanzamiento/mantenedor; Los autores de mods solo necesitan la comparación --before, y los jugadores que instalan un paquete publicado no necesitan ejecutarlo.
a command line
python tools/modding/mod_test_host.py --root "<mod-root>" --repo-root "<framework-root>" --jsonLee el manifiesto, las dependencias, la compatibilidad y el orden de carga sin iniciar Godot y sin ejecutar ninguno de sus paquetes.
Nunca abre un archivo de contenido. Esta es la división del trabajo: el host responde estos paquetes se cargarán juntos, el validador responde este registro es correcto - pero eso significa que un paquete que el validador rechaza aún puede componerse limpiamente aquí. Medidos en catorce paquetes deliberadamente rotos, los dos no están de acuerdo en cada rechazo: el host presenta los catorce refused vacíos, incluido uno que lleva scripts/payload.sh que solo el validador encuentra. Marcar no es lo mismo que instalar de forma segura. Haga ambas cosas antes de publicar. Repita --root cuando el conjunto de prueba esté dividido en carpetas; Luego, el anfitrión compone el conjunto completo en un plan determinista.
a command line
python tools/modding/mod_test_matrix.py --repo-root "<framework-root>" --root "<mod-root>" --godot "<godot-exe>" --require-runtime --report "mod_test_matrix.json"Ejecuta el validador, el host de prueba, el dispositivo de cada familia listo para usar y el carril de tiempo de ejecución de Godot. Elimina --require-runtime si no tienes Godot; el informe dirá entonces que la prueba de tiempo de ejecución se omitió, no se aprobó.
Para un conjunto compuesto, repita la opción:
a command line
python tools/modding/mod_test_matrix.py --repo-root "<framework-root>" --root "<mod-a>" --root "<mod-b>" --godot "<godot-exe>" --require-runtimeEl informe mantiene un resultado por raíz y agrega composed_set para el conjunto completo. Este bloque es donde se demuestran los conflictos de paquetes, los ID duplicados y los errores de dependencia. Un paquete limpio por sí solo no es prueba de que el conjunto se cargará junto. El informe también incluye surface_contract, la versión actual del contrato familiar y el resumen de auditoría, por lo que una matriz no puede estar en verde mientras la instantánea de compatibilidad del repositorio esté desactualizada. Con --require-runtime, lea runtime.reachability.loaded_families y runtime.reachability.reachable_families. El primero dice que se han cargado los registros compuestos; el segundo sólo se llena cuando un camino real dirigido a los jugadores de la investigación Godot los ha consumido. runtime.reachability.observations mantiene el paquete, la familia, el ID de registro, la ruta y el estado de cada fila, mientras que unreachable enumera las filas cargadas que aún no tienen ninguna ruta. Una familia puede ser validada y puesta en escena pero aún así estar ausente de reachable_families: no es lo mismo "cargado" que "un jugador puede alcanzarlo".
Cada comando anterior se compara con las herramientas mismas a medida que se crea esta página: el script debe existir y cada opción debe ser de aceptación.
Cada código de diagnóstico
No lea esta lista en orden. Está aquí para que un código que encuentre en un informe sea una pregunta con una respuesta: una pequeña palabra en minúscula como asset_missing. Pegue uno en el cuadro de búsqueda en la parte superior de esta página.
Algunos códigos pertenecen a mecanismos a los que un paquete aún no puede llegar. Yo estoy aquí igual: un código que no puedes activar cuesta una línea que nunca leerás, y un código que falta cuesta una noche.
| Código | ¿Qué lo causó? | que hacer |
|---|---|---|
adaptive_brings_a_model | Un paquete que intenta cargar algo o llegar a alguna parte. | Elimine la ruta o dirección y elija una política publicada por nombre. Cualquier archivo que hayas traído no se cargará aquí. |
adaptive_fell_back | Un perfil que no llegó a su piso y utilizó la política que había declarado. | No hay nada que arreglar, a menos que nunca me detenga. El perfil no tenía suficientes señales entre los que lee, por lo que utilizó la política que declaró como alternativa. |
adaptive_invalid | El registro no es uno que esta compilación cargaría. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
adaptive_over_budget | Un paquete por encima de un techo declarado. | El informe imprime lo medido junto a lo permitido. Dividir el registro o eliminar entradas más allá de la línea: el límite es lo que una pantalla o un lector puede contener, no una sugerencia. |
adaptive_text_not_key | Una oración donde se necesita una clave de catálogo. | Mueva la frase a su catálogo de idiomas y coloque su clave en el campo. Un campo que termina en _key contiene una clave; una frase allí hace que su paquete esté en un idioma para siempre. |
adaptive_unknown_step | Una política, señal o dirección que esta construcción no tiene. | El nombre no está en la lista publicada para esa tabla. Elija uno que esté allí: la lista es corta porque cada entrada es algo que esta compilación ya hace. |
adaptive_unresolved_reference | Un registro con nombre que nadie proporciona. | La identificación nombrada es aquella que no proporciona nada en la composición. O llevas el registro al que apunta o dependes del paquete que lo lleva. |
assembly_dangling_reference | Una escalera, puerta o entrada nombra algo que este mapa no contiene. | Agregue el objeto nombrado a este mapa o corrija la identificación. Una escalera cuyo rellano no está en el mapa es un piso en el que el jugador puede entrar y del que no puede salir, y un edificio cuya entrada no es un pasaje es una puerta dibujada en una pared. Los dos extremos deben estar en el mismo archivo. |
assembly_leaked | El desmontaje soltó menos nudos que los que llevó el montaje. | No hay nada que arreglar en su paquete y nada en un paquete puede causarlo. El desmontaje liberó menos nodos de los que tomó el ensamblaje, por lo que algo se aferra a alguna parte del mapa anterior; escríbalo junto con el mapa que lo produjo. Se ve como un recuerdo que crece cada vez que entras al mismo lugar. |
assembly_missing_aspect | Una parte obligatoria del diseño no produjo nada, por lo que no cabe en el mapa. | Agregue la parte que falta en su capa y exporte nuevamente. El mensaje dice cuál: los rectángulos transitables van en la capa transitable, los colisionadores en caso de colisión y la capa de mosaicos de terreno deben cubrir el mapa. Un mapa sin nada transitable es un lugar al que el jugador puede ingresar y no moverse, por lo que se rechaza en lugar de publicarse. |
assembly_over_budget | La forma ensamblada se encuentra más allá del techo declarado. | Elimina parte de lo que contaba el mensaje, o divide el mapa. El techo se mide en función de lo que se montó y no del tamaño del archivo, por lo que comprimir las capas no cambia nada: el número en el mensaje es lo que la máquina debería haber contenido. |
assembly_refused | No se construyó nada, porque construir medio mapa es peor que no construir ninguno. | Corrija cualquier otro mensaje de esta ejecución y exporte nuevamente. Nada fue construido a propósito: la mitad del mapa es una habitación a la que se ingresa sin paredes, y no habría forma de saber qué mitad lo hizo. |
assembly_unreachable_affordance | Un fondeadero es aquel donde nada está declarado transitable, por lo que nadie puede llegar a lo que ofrece. | Dibuja un rectángulo transitable que toque el ancla nombrada por el mensaje, en el mismo plano. Un ancla es la cosa en sí y el actor se encuentra junto a ella, por lo que un mostrador que se encuentra dentro de un área transitable es un mostrador por el que pasa el jugador, y un mostrador sin nada alrededor es un servicio al que nadie puede llegar. Primero verifique la propiedad del piso: la habitación de abajo no da servicio a una litera de arriba. |
asset_invalid | Existe un descriptor y esta compilación lo rechaza. El veredicto dice qué regla. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
asset_kind_mismatch | La persona que llama preguntó por un tipo y el descriptor indica otro. Resolverlo de todos modos le daría una textura a algo que espera un sonido. | Vincula un recurso del tipo que toma la ranura. Nadie dibuja un retrato de una región, por lo que la conexión nunca se establecería y nada diría por qué. |
asset_missing | El paquete está instalado y no declara ningún descriptor bajo esa identificación. | La identificación del recurso no se resuelve en nada en la composición. Traiga el archivo o señale el enlace a uno que su paquete realmente contenga. |
asset_package_missing | Ningún paquete instalado responde al espacio de nombres que nombra la identificación. | El paquete que proporcionó este recurso no está instalado. Vuelva a instalarlo o vincule la ranura a algo que quepa en un paquete instalado. |
audio_cue_refused | Un sonido o lista de reproducción que esta compilación no graba. | Lea la regla nombrada al lado del código y vuelva a codificarla para cumplirla. Las causas habituales son un formato que no decodificamos y una duración superior al límite declarado. |
audio_placeholder_used | Un sonido rechazado o faltante se resolvió en el sustituto reservado y se notificó a la persona que llamó. | No hay nada que arreglar, si lo quisieras. Faltaba el sonido, por lo que sonó el reemplazo de su tipo y se señaló el reemplazo en lugar de quedarse en silencio. |
audio_refused | Un sonido que esta construcción no reproduce. El veredicto dice qué regla. | El archivo de audio en sí fue rechazado antes de que nada lo reprodujera. Vuelva a codificarlo a un formato declarado dentro del tamaño declarado y mantenga la frecuencia de muestreo entre las de la lista publicada. |
audio_stream_overran | Un flujo que superó la duración declarada por su descriptor se detuvo en el límite. | La transmisión es más larga de lo que permite su ranura. Acórtelo o muévalo a una ranura cuyo presupuesto lo cubra: un flujo que se excede es un flujo que el mezclador tiene que cortar a mitad de palabra. |
binding_invalid | Una conexión que esta construcción no hace. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
binding_missing_alternative | Información que un jugador no puede recibir sin que nada más la lleve. | Un retrato y un icono necesitan una clave descriptiva y una línea hablada necesita una clave de subtítulo. Añade la alternativa: es la única regla de accesibilidad que un jugador escucha directamente. |
binding_over_budget | Enviar un paquete más allá de lo que permite uno de los totales. | El informe imprime lo medido junto a lo permitido. Dividir el registro o eliminar entradas más allá de la línea: el límite es lo que una pantalla o un lector puede contener, no una sugerencia. |
binding_placeholder_used | Un sonido que nadie aporta, resuelto en el sustituto de su tipo. | No hay nada que arreglar, si lo quisieras. El enlace se resolvió en el sustituto del tipo de recurso de su espacio, y el informe dice qué espacio, para que pueda distinguir una decisión de un descuido. |
boot_attempt_recorded | Se escribió un intento antes de que comenzara la composición. | Nada que arreglar. El arranque se puso por escrito antes de intentarlo, y eso es lo que le permite al siguiente arranque saber que algo salió mal. |
boot_last_known_good_offered | En su lugar, se ofrece un perfil que se inició en el pasado. | La composición que falló no fue la que funcionó, por lo que se ofreció la última que funcionó. Consíguelo, luego reinstale los paquetes uno a la vez para encontrar el que rompió todo. |
boot_marker_unwritable | El intento no quedó registrado. El juego se inicia con la recuperación deshabilitada para esta sesión y así lo indica. | No se pudo escribir el marcador de inicio, por lo que la próxima vez no podrá distinguir un bloqueo de una salida limpia. Compruebe que se pueda escribir en la carpeta de datos del juego; No se trata de tu paquete. |
boot_package_rejected | Un paquete fue rechazado durante la recuperación. Se registra la identificación, nunca la ruta. | Este paquete impidió que se iniciara el juego y quedó fuera. El informe menciona la negativa; Arréglelo y reinstálelo, o déjelo fuera. |
boot_retry_offered | Por debajo del límite; Se vuelve a intentar el mismo perfil. | Acepta el reintento. Si el segundo arranque también falla, el problema es la composición y no el tiempo, y la próxima oferta será el modo seguro. |
boot_safe_mode_offered | El límite está agotado; El juego ofrece comenzar sin ningún paquete. | Acepte el modo seguro, luego elimine los paquetes uno a la vez hasta que se inicie. Su archivo guardado no se modifica: el modo seguro lo lee y nunca escribe en él. |
budget_aggregate_exceeded | El conjunto instalado ha excedido el límite compartido. El paquete nombrado es el que lo pasó, en orden de carga. | Quita algo de la composición. Son todos los paquetes juntos los que superan el límite, no solo el suyo, y el informe imprime el total junto al límite. |
budget_degraded | Una dimensión se ha reducido en lugar de rechazarse y se denomina aquello en lo que se pliega. | No hay nada que arreglar, a menos que quieras decir lo contrario. La composición se mantuvo dentro de su presupuesto, renunciando a la calidad y no al contenido: no falta nada, algo es más pequeño. |
budget_package_exceeded | Un paquete ha excedido su límite de tamaño. | Lee la talla mencionada en el informe y corta lo que mide. Imprima cuánto ha usado su paquete junto a cuánto puede usar un paquete. |
budget_soft_warning | Más allá del umbral suave, cargado de todos modos, informado a quienes lo crean. | No hay nada que arreglar por ahora. Estás lo suficientemente cerca de un techo como para que otro paquete lo supere, y es útil saberlo antes de que lo haga otro. |
budget_unknown_dimension | Ha habido un informe de consumo en un tamaño que esta compilación no declara, es decir, alguien escribiendo sobre una superficie que no existe. | El presupuesto menciona algo que esta construcción no mide. Elija un tamaño de la lista publicada; uno que no midamos nunca se aplicará. |
budget_unknown_profile | Un perfil que esta compilación no declara. Se aplica el perfil más severo en lugar del más ancho. | Elija un perfil de presupuesto de la lista publicada. Los perfiles se eligen en lugar de ser descritos, por lo que uno que no publicamos es uno que nadie haría cumplir. |
campaign_hardcoded_identity | Un consumidor escribió la identificación de la campaña base en lugar de preguntar qué campaña está seleccionada. | Algo tomó la identificación, el texto o la escena de la campaña base por nombre en lugar de preguntar a la campaña seleccionada. Resuelva esto a través del contexto de la campaña; de lo contrario, una conversión recibirá la respuesta de este mundo en lugar de la suya propia. |
campaign_invalid | La declaración no es una que esta compilación seleccionaría. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
campaign_not_found | Se ha seleccionado una campaña para id y no hay declaraciones que respondan a esa id. | La identificación de la campaña nombrada no está instalada. Comprueba cómo lo escribiste o instala el paquete que lo proporciona: aquí no recurre a la campaña básica. |
character_carries_handler | Datos públicos que nombran un símbolo privado. | Elimine el campo que nombra un método o devolución de llamada. La publicación de un símbolo interno lo convierte en un contrato público, y el cambio de nombre que lo rompe los jugadores lo reportan como la ruptura del juego. |
character_invalid | El registro no es uno que esta compilación cargaría. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
character_origin_missing | Un personaje cuyo origen no lo proporciona nadie, cargado de respaldo. | Reinstale el paquete que escribió esta fuente. El personaje se ha cargado con el respaldo reservado y la identificación que perdió viaja con él, por lo que la reinstalación lo coloca exactamente como estaba. |
character_tree_unenterable | Un bucle o nodo inalcanzable en un árbol de progresión. | Vea si el informe dice ciclo o huérfano y vuelva a conectar esa parte del árbol. Tampoco lo es un error al jugar: la opción simplemente nunca se ofrece y el archivo parece correcto. |
character_unknown_property | Una propiedad que no significaría nada para ningún sistema. | Utilice una propiedad que tenga esta construcción. Aceptar uno que no lo tiene pondría un campo en el guardado que no significa nada para ningún sistema y no se le puede explicar a nadie, para siempre. |
combat_carries_formula | Un paquete que intenta proporcionar la aritmética de un choque. | Retire el campo. El nivel 1 son los datos: lo que se ejecuta pertenece al juego y las nuevas funciones provienen de un proveedor confiable. |
combat_effect_expired | Un estado guardado cuya calibración desapareció y finaliza al cargar. | El paquete que calibró este estado ya no está instalado, por lo que el estado terminó aplicándose con números que nadie tiene. Vuelva a instalarlo para conservarlo. |
combat_invalid | El registro no es uno que esta compilación cargaría. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
combat_over_budget | Un paquete por encima de un techo declarado. | El informe imprime lo medido junto a lo permitido. Dividir el registro o eliminar entradas más allá de la línea: el límite es lo que una pantalla o un lector puede contener, no una sugerencia. |
combat_phase_unreachable | Una fase escrita y nunca alcanzada. | Dos fases comparten un umbral, por lo que una de ellas nunca comenzaría. Dales diferentes valores de salud restantes. |
combat_unknown_operation | Una operación o parámetro que el solucionador no tiene. | Elija la operación de la lista publicada y proporciónele solo sus parámetros. Un empujón que conlleva valor es una línea mal interpretada, no un empujón más fuerte. |
combat_unknown_status | Un estado que esta compilación no publica. | Calibre un estado que publica esta compilación en lugar de inventar uno. Un estado inventado se encuentra en una unidad detrás de un icono en blanco y no hay nada que se lo pueda quitar. |
combat_unresolved_reference | Un registro con nombre que nadie proporciona. | La identificación nombrada es aquella que no proporciona nada en la composición. O llevas el registro al que apunta o dependes del paquete que lo lleva. |
conversion_external_reference | Una dirección o ruta que sale del paquete. | Una conversión señalada desde su propio paquete. Trae contigo lo que mencionas; de lo contrario, el mundo buscará uno que no hayas escrito. |
conversion_fallback_allowed | Una conversión que no negó el retroceso en el juego base, ni en el cartel ni en la campaña. | Nada que arreglar. Esta familia puede recurrir al juego base y la línea dice por qué no es un escape. |
conversion_family_unclassified | Existe una familia de contenidos y este catálogo no la clasifica. | Declara a la familia como propiedad del campo o del motor. Una familia no clasificada es aquella sobre la que la prueba de escape del juego base no puede razonar en absoluto. |
conversion_missing_file | Un archivo que el aparato declara y no tiene. | Un archivo requerido que la conversión declaró no está en el paquete. Tráelo: una conversión a la que le falta una parte de sí misma comienza y luego no puede continuar. |
conversion_partial_atomic_family | Sólo se proporcionó parcialmente una familia atómica. Rechazado en lugar de publicado con la costura visible. | Trae a toda la familia o no los traigas en absoluto. La mitad de una lista de misiones es un mundo que se refiere a misiones que nadie escribió. |
conversion_required_family_missing | Falta una familia poseída por el campo que la reconversión debía proporcionar. | Trae a la familia. El catálogo dice cuáles son necesarios para una conversión y, sin ellos, el mundo es el juego base con arte nuevo. |
conversion_unclaimed_family | Una familia para la cual el paquete proporciona archivos y que la campaña no reclama. | Reclamar a la familia en un paquete, o declararlo aplazado con un motivo. Si no fue reclamado, nada dice si su ausencia fue intencional. |
conversion_unknown_family | La campaña declaró a una familia que no conoce esta construcción. | Nombra una familia del catálogo de tipos de contenido. Las familias se declaran allí antes de que alguien pueda proporcionar una. |
conversion_vanilla_leak | Una identificación que no pertenece ni a la conversión ni al espacio de nombres reservado del motor. | Reemplace la identificación, el texto o la escena que nombra el informe. Esta conversión niega el retroceso, por lo que la alternativa es que el jugador vea este mundo dentro de ese otro. |
dialogue_carries_expression | Un paquete que intenta ejecutar algo o escribir palabras en el acto. | Retire el campo. El nivel 1 son los datos: lo que se ejecuta pertenece al juego y las nuevas funciones provienen de un proveedor confiable. |
dialogue_dead_end | Una conversación de la que un jugador no puede salir. | Tenga una opción que apunte desde este nodo hasta un camino que llega a su fin. Un ciclo está bien; un bucle sin salida es una conversación de la que el jugador no puede salir. |
dialogue_invalid | El registro no es uno que esta compilación cargaría. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
dialogue_orphan_node | Un nodo al que nada puede llegar. | Nada va a este nodo, por lo que ningún jugador lo leerá. Haga que apueste contra una opción o descarte su apuesta. |
dialogue_over_budget | Un paquete por encima de un techo declarado. | El informe imprime lo medido junto a lo permitido. Dividir el registro o eliminar entradas más allá de la línea: el límite es lo que una pantalla o un lector puede contener, no una sugerencia. |
dialogue_text_not_key | Una oración donde se necesita una clave de catálogo. | Mueva la frase a su catálogo de idiomas y coloque su clave en el campo. Un campo que termina en _key contiene una clave; una frase allí hace que su paquete esté en un idioma para siempre. |
dialogue_unguarded_reveal | Un secreto sin nada por delante. | Ponga al menos una condición en el nodo. Una lista de condiciones vacía no cuenta como ninguna: el secreto pasaría a quien abra la conversación. |
dialogue_unknown_step | Un control o comando que esta compilación no tiene. | El nombre no está en la lista publicada para esa tabla. Elija uno que esté allí: la lista es corta porque cada entrada es algo que esta compilación ya hace. |
dialogue_unresolved_reference | Un registro con nombre que nadie proporciona. | La identificación nombrada es aquella que no proporciona nada en la composición. O llevas el registro al que apunta o dependes del paquete que lo lleva. |
distribution_hash_mismatch | Los archivos en el disco no son lo que describe el registro. | El paquete del disco no es el que se lanzó. Descárgalo nuevamente: una discrepancia es una transferencia que salió mal o un archivo que otra persona cambió. |
distribution_invalid | El registro no es uno que esta construcción aceptaría. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
distribution_offline | La procedencia se cotejó con lo registrado en el momento de la instalación. | Verifique su conexión y vuelva a intentarlo. Los paquetes ya instalados siguen funcionando; otros nuevos no pueden ocurrir hasta que regrese el servicio. |
distribution_reported | Alguien lo informó. El jugador es notificado y decide. | Lee el informe y decide. El paquete funciona igual: el informe existe para que la decisión se tome delante de él, no en su lugar. |
distribution_revoked | El paquete está en cuarentena o retirado. No se instala. | Retire el paquete. Fue retirado después de su publicación y no se carga; si lo escribió, el aviso de revocación dice el motivo. |
distribution_update_deferred | Hay una nueva versión disponible y hay una campaña en curso sobre la anterior. | Reinicie para recibir la actualización. Intercambiar un paquete en un juego en curso es la forma en que un guardado comienza a nombrar cosas que nadie proporciona. |
economy_expression_refused | Un campo que traería algo para evaluar. | Una entrada de precio intentó traer algo valioso. Elija una curva por nombre de las cuatro que implementa esta construcción: un precio que se puede ejecutar es el límite de nivel 1 alcanzado a través de la economía. |
economy_invalid | El registro no es uno que esta compilación cargaría. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
economy_out_of_bounds | Un número fuera del rango indicado. | Devuelve el número dentro del rango declarado. Cada campo numérico aquí tiene uno, y un campo sin rango declarado se rechaza en lugar de dejarse pasar. |
economy_overridden | Un paquete reemplazó un registro declarado por otro paquete o el juego base. | Nada que arreglar. Este registro fue tomado por otro paquete, y el informe dice cuál, para que puedas decidir si esa era la intención. |
economy_unresolved_reference | Una receta o tanque que pone nombre a contenidos que nadie proporciona. | La identificación nombrada es aquella que no proporciona nada en la composición. O llevas el registro al que apunta o dependes del paquete que lo lleva. |
effect_carries_source | Un descriptor que nombra un sombreador, una escena o un código. | Elimine el campo que nombra un sombreador, script o escena. Los efectos se componen de las primitivas del motor; proporcionar la fuente es proporcionar un programa. |
effect_degraded | Un efecto reducido para encajar dentro del marco, llamado así para que la reducción no sea un misterio. | No hay nada que arreglar, a menos que quieras decir lo contrario. El efecto fue bajar la calidad para mantenerse dentro del presupuesto del marco: sigue ahí y es más pequeño. |
effect_dropped | Un efecto que simplemente no estaba ahí. | Vea qué tamaño dice el estado de cuenta del presupuesto que llenó, luego córtelo. El marco se quedó sin espacio y este efecto no se dibujó en absoluto. |
effect_refused | Un efecto que esta construcción no marca. El veredicto dice qué regla. | Lea el parámetro nombrado en el informe e infórmelo dentro del rango impreso junto a él. El efecto fue rechazado antes de que algo lo provocara. |
extension_forbidden_field | El manifiesto incluye un campo que ninguna extensión puede incluir, como la ruta a un script, un solucionador o una importación privada. | Retire el campo. La ruta a un script, solucionador, importación privada o cambio de configuración del proyecto va más allá del contrato y llega al invitado, y una extensión que lo necesita solicita una capacidad en lugar de declararla: declare la capacidad en requires. |
extension_foreign_namespace | El espacio de nombres del estado declarado no es el ID del paquete de la extensión, por lo que su estado no sería atribuible una vez que desapareciera. | Cambie el nombre de state_namespace al ID del paquete de la extensión. El estado escrito en otra parte no se puede atribuir ni eliminar una vez que el paquete desaparece y el huésped conserva sus nombres. |
extension_missing_field | Falta un campo que el invitado necesita instalar, tomar una impresión, regresar o eliminar la extensión. | Agregue el campo al manifiesto de extensión. Cada uno de ellos es algo que el huésped necesita antes de poder solicitar la extensión, colocarla en el espacio de composición, regresar o eliminarla nuevamente: un cartel al que le falta uno describe una característica que el huésped podría instalar y nunca eliminar. |
extension_teardown_incomplete | Al eliminar la extensión se devolvió menos de lo necesario, lo que hace que se pierda en la siguiente instalación en lugar de hacerlo ahora. | Devuelva todo lo que tomó la extensión antes de declarar el desmontaje completo y actualice takes si el número real ha cambiado. Devolver menos no falla ahora: se pierde en la siguiente instalación, e instalar la misma extensión dos veces en una sesión es normal. |
extension_unbounded | Falta un presupuesto establecido o no hay una cifra, por lo que nada podrá superarlo. | Escriba un número para cada presupuesto que nombra el contrato. Un presupuesto que se omite, o se escribe como una frase, se lee tal como está dicho y no se compara con nada, por lo que la extensión nunca podrá excederlo. |
extension_unknown_capability | La extensión requiere o proporciona una capacidad que esta compilación no publica. | Compare los identificadores de habilidades con los que publica esta compilación y elimine o cambie el nombre de los que no coincidan. Negarse antes de la instalación es intencional: una extensión que descubriera una habilidad faltante mientras giraba la descubriría frente a un jugador. |
extension_would_add_autoload | El manifiesto agregaría una variable global. Rechazado lo que diga el nivel de confianza, porque un paquete que pudiera agregar uno desharía el retiro en el que se basa esta compilación. | Elimine el nombre de carga automática, singleton o base del manifiesto. Ningún nivel de confianza garantiza esto: toda la migración en la que se basa esta compilación es retirar variables globales, por lo que una extensión que pudiera agregar una la desharía desde afuera. Coloque el estado bajo el espacio de nombres de la extensión y llegue al invitado a través de las capacidades que publica. |
font_locale_fallback | Un glifo que el personaje elegido no lleva, extraído del respaldo e informado. | La fuente que proporcionaste no tiene glifos para este idioma, por lo que la alternativa la dibujó. Trae una fuente que cubra el idioma, de lo contrario el texto será cuadritos. |
font_refused | Un personaje que esta construcción no utiliza. El veredicto dice qué regla. | El archivo de fuente fue rechazado. Comprueba que el formato es uno de los que subimos y que el archivo no contiene ningún programa. |
image_bomb_refused | Un encabezado que reclamaba más que el presupuesto de decodificación, rechazado antes de que cualquier decodificador lo viera. | La imagen se descomprime en mucho más de lo que sugiere el tamaño del archivo. Reexportarlo a su tamaño real: se rechaza antes de ser decodificado, porque decodificarlo es el daño. |
image_frame_grid | Una hoja cuya cuadrícula declarada no la divide exactamente. | Los marcos de la hoja de sprites no dividen sus dimensiones exactamente. Ajuste la cuadrícula; de lo contrario, cada cuadro después del primero se dibujará desplazado por el resto. |
image_hash_mismatch | Los bytes cambiaron después de que se validó el descriptor. | La imagen no es la anunciada. Reexportar o redeclarar: una discrepancia significa que el archivo y el manifiesto no coinciden en lo que se transfirió. |
image_placeholder_used | Una imagen rechazada o faltante se resolvió en el sustituto reservado y se notificó a la persona que llamó. | No hay nada que arreglar, si lo quisieras. Faltaba la imagen y se dibujó el reemplazo de su tipo, con el reemplazo marcado en lugar de dejarlo en blanco. |
image_refused | Una imagen que esta compilación no decodifica. El veredicto dice qué regla. | Vuelva a exportar al tamaño, formato y presupuesto que indique el informe. La imagen fue rechazada antes de que nada la dibujara. |
inference_cancelled | Una ejecución superó su presupuesto de latencia y se detuvo. La heurística respondió, por lo que la persona que llamó no tuvo que esperar. | Reduzca el modelo o aumente max_latency_usec si el presupuesto fuera realmente demasiado ajustado. La ejecución excedió su presupuesto y se detuvo, y la heurística respondió en lugar de dejar a la persona que llama esperando: un fotograma pasado esperando es un fotograma que el jugador miró. |
inference_digest_mismatch | Los bytes del patrón no son los registrados, lo que lo convierte en un patrón diferente y no más antiguo. | Actualice el resumen declarado al SHA-256 del modelo que está portando, o transfiera el modelo que nombra el resumen. Bytes diferentes significan que se trata de un modelo diferente y no hay otra forma de notar la diferencia. |
inference_forbidden_field | La declaración incluye un tiempo de ejecución, un script, un punto final, algo de telemetría o un reclamo de autoridad. | Retire el campo. El adaptador pertenece al motor, por lo que un paquete proporciona los pesos y nunca el código que los ejecuta; un punto final colocaría el modelo en un lugar donde podría cambiarse después de la revisión, y la telemetría informaría lo que pidió un jugador. Trae las pesas y deja que el motor las haga. |
inference_load_refused | La declaración está bien y esta compilación no trae ningún adaptador de inferencia para cargarla, por lo que respondió la heurística determinista. | No hay nada que arreglar en su paquete. Esta compilación no incluye ningún adaptador de inferencia, por lo que no se carga ningún modelo de ningún formato y responde la heurística determinista. La declaración se valida de todos modos, por lo que un modelo portado hoy es un modelo que un adaptador podría cargar sin modificaciones. |
inference_missing_field | A una declaración de modelo le falta algo que el adaptador necesita antes de gastar nada en una ejecución. | Agregue el campo a la declaración del modelo. Cada uno es algo que el adaptador necesita antes de gastar algo en una ejecución: el resumen es la identidad del modelo, los patrones son lo que usted alimenta y lo que aceptará, y las plataformas son donde se permite probarlo. |
inference_output_rejected | La respuesta del modelo no coincidía con el patrón de resultados declarado y fue descartada en lugar de interpretada con indulgencia. | Compare lo que devuelve el modelo con el patrón de salida declarado. Una respuesta casi correcta se descarta en lugar de interpretarse con indulgencia, porque una propuesta que se aprueba en la forma incorrecta es aquella que cada verificación posterior lee como válida. |
inference_unbounded | Falta un límite establecido o no hay un número, por lo que nada podrá excederlo. | Escriba un número para cada límite que nombra el contrato. Un límite omitido o escrito con palabras se lee tal como se indica y no se compara con nada, por lo que la ejecución que sale mal es aquella que nadie estaba midiendo. |
inference_unknown_format | El formato del modelo no es uno que implemente el adaptador del motor. | Reexporta el modelo en uno de los formatos que implementa el adaptador del motor. Un formato que no se implementa no es un camino más lento: no es nada en absoluto. |
inference_wrong_platform | El modelo no declara esta plataforma, por lo que respondió la heurística determinista. | No hay nada que arreglar, si se quiere. El modelo no declara esta plataforma, por lo que la heurística determinista respondió aquí; agregue la plataforma a la declaración solo cuando el modelo realmente haya sido construido y probado allí. |
input_binding_conflict | La clave sugerida ya fue asignada. La asignación existente lo mantuvo y la denuncia se registró en lugar de aplicarse. | No hay nada que arreglar en su paquete ni nada sacado. El botón ya estaba asignado, por lo que la asignación del jugador lo mantuvo y su acción se ofrece sin botón en la pantalla de asignación. Elija un valor predeterminado menos concurrido si desea que se mantenga durante la instalación. |
input_binding_orphaned | Una reasignación pertenece a una acción que ningún paquete instalado declara. Se mantiene en lugar de eliminarse, por lo que al reinstalarlo se encuentra donde lo dejó el reproductor. | Nada que arreglar. La reasignación pertenece a una acción que ningún paquete instalado declara y se conserva en lugar de eliminarse, por lo que al reinstalar el paquete se encuentra el botón donde lo dejó el reproductor. |
input_core_action | Un paquete nombró o intentó reemplazar una de las acciones del host. | Cambie el nombre de la acción. Las acciones del juego pertenecen al anfitrión y un paquete no puede declararlas ni reemplazarlas; tomar pause juega un juego del que no puedes salir. Declara tu acción junto a él y deja que el jugador asigne ambas. |
input_forbidden_field | La declaración conlleva una lectura directa del dispositivo, un oyente, un agarre de fuego o una tarea que el jugador no pudo cambiar. | Retire el campo. Declarar una acción es toda la interfaz: leer un dispositivo directamente, instalar un oyente, recibir disparos o forzar una tarea le quitan una decisión al jugador y son invisibles en cada pantalla que puedan revisar. |
input_foreign_namespace | La identificación de la acción no cabe en el espacio de nombres del paquete que la declara. | Cambie el nombre de la identificación de la acción al espacio de nombres de su paquete. La reasignación de jugadores está adjunta a nosotros, por lo que una identificación que pertenece a otra persona es una reasignación que cambia de maestro cuando se elimina uno de los dos paquetes. |
input_keyboard_unreachable | La acción no tiene asignación de teclado, por lo que un jugador sin controlador no puede alcanzarla. | Escriba una asignación de teclado junto a la asignación de controlador. Una asignación de solo pad es inalcanzable para un jugador sin pad, en un juego que de otro modo se puede jugar sin él, y para él falla silenciosamente. |
input_missing_field | A una declaración de acción le falta algo que la pantalla de asignación o reasignación necesita. | Agregue el campo a la declaración de acción. Cada uno es algo que una pantalla necesita: la clave de etiqueta es lo que muestra la lista de tareas en lugar de su identificación interna, y el contexto es lo que le dice al juego cuándo la acción está activa en lugar de activarla mientras alguien escribe el nombre de una partida guardada. |
input_reserved_chord | Un paquete solicitó una combinación que pertenece al sistema o ventana. | Elija otra clave. Cerrar la ventana, salir del juego y la clave de plataforma pertenecen al sistema operativo, y un paquete que contenga una podría impedir que alguien salga. |
input_unknown_context | El contexto declarado no es uno que publica esta compilación, por lo que nadie sabe cuándo está activa la acción. | Elija uno de los contextos publicados. Nadie sabe cuándo una acción está viva en un contexto no publicado, por lo que nunca se disparará o siempre se disparará, y eso no es lo que usted quiso decir. |
lore_invalid | El registro no es uno que esta compilación cargaría. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
lore_player_state_in_definition | Un campo que describe a un jugador que se encuentra dentro de una definición. | Retire el campo. Un registro de historia es una definición y lo que el jugador sabe es: cargar historia nunca otorga conocimiento, por lo que un campo que pretende hacerlo sería un campo que nadie lee. |
lore_replaced | Un paquete reemplazó una entrada existente, preservando su identificación y enlaces. | Nada que arreglar. Otro paquete reemplazó esta entrada y retuvo su identificación, por lo que todo lo que apuntaba a ella todavía apunta a algo. |
lore_unresolved_reference | Una identificación en related_to, revela o requiere que nadie la proporcione. | La identificación nombrada es aquella que no proporciona nada en la composición. O llevas el registro al que apunta o dependes del paquete que lo lleva. |
lore_verbatim_text | Texto llevado en lugar de una clave de catálogo, por lo que aparecería en un solo idioma. | Un campo que termina en _key contiene una frase. Muévelo a tu catálogo de idiomas: evita todas las demás comprobaciones aquí y trae tu historia a un solo idioma. |
map_bad_layer_data | Una capa que no cubre el mapa al que pertenece. | Vuelve a exportar la capa sin comprimir, sin bloques y sin líneas cortas. El subconjunto que aceptamos es el subconjunto que sabemos controlar. |
map_carries_path | Un mapa que nombra algo para cargar o ejecutar. | Elimina el campo que apunta a un archivo. Un mapa nombra sus mosaicos del kit; una ruta es la forma en que un paquete sale de sí mismo. |
map_duplicate_anchor | Dos objetos que afirman la misma identificación. | Dos anclajes comparten un nombre, por lo que a cuál se adjunta algo depende del orden de lectura. Cambiar el nombre de uno. |
map_invalid | El mapa no es uno que esta construcción ensamblaría. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
map_kit_mismatch | Un mapa diseñado con un kit que esta construcción no tiene. | El mapa se escribió con un kit diferente al que publica esta compilación. Vuelva a exportarlo con el kit actual: los roles y clases se han movido. |
map_layer_missing | No existe un nivel obligatorio o está mal diseñado. | Añade el nivel que requiere el contrato. El archivo de proyecto del kit los enumera y falta un mapa que se carga con un agujero. |
map_normalization_failed | El mapa no produjo ninguna forma canónica. | Elimine la construcción que nombra el informe y luego exporte nuevamente. Sin un formulario canónico no se puede demostrar que el tiempo de ejecución y el validador fuera de línea coinciden en este mapa. |
map_outside_package | Un conjunto de mosaicos o plantilla que proviene de fuera del paquete. | El mapa apunta a algo fuera de su propio paquete. Tráelo; de lo contrario, el mapa depende de lo que esté instalado. |
map_over_budget | Un mapa normalizado más allá de un límite establecido. | El informe imprime lo medido junto a lo permitido. Dividir el registro o eliminar entradas más allá de la línea: el límite es lo que una pantalla o un lector puede contener, no una sugerencia. |
map_unresolved_reference | Una identificación con nombre que nadie proporciona. | La identificación nombrada es aquella que no proporciona nada en la composición. O llevas el registro al que apunta o dependes del paquete que lo lleva. |
map_unsupported_subset | Algo en el archivo está fuera del subconjunto del formato. | El archivo utiliza una función Tiled del subconjunto que lee esta compilación: capas colapsadas, capas de imágenes, grupos, bloques o polígonos. Reexportar sin. |
pack_claims_host_surface | Una carga automática, una acción de entrada o una configuración de proyecto. | Sobrescribe el contenido en lugar del archivo. Los paquetes agregan y reemplazan contenido; las superficies necesarias para que comience el juego no se encuentran entre estas. |
pack_collision | Un reclamo que ya tiene otro paquete. | Entregue el archivo en uno de los dos paquetes. El informe los nombra a ambos, y dejarlo así ganaría el orden de asamblea. |
pack_mount_failed | No montó el motor; el conjunto anterior sigue siendo válido. | El paquete no se pudo ensamblar en absoluto. Compruebe que el archivo esté intacto y en un formato que lea esta compilación. |
pack_replaces_vanilla | Un reclamo que tiene el juego base. | Sobrescriba el contenido en lugar del archivo o solicite una capacidad de reemplazo confiable. Reemplazar un archivo de juego base no es algo que haga un paquete de datos. |
pack_restart_required | El todo ensamblado cambiaría y el cambio no puede surtir efecto en este proceso. | El cambio no se puede aplicar a un juego terrestre. Reiniciar: intercambiar contenido montado a mitad del juego deja a la mitad del juego leyendo archivos antiguos. |
progress_invalid | El registro no es uno que esta compilación cargaría. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
progress_origin_lost | Un logro obtenido cuyo paquete ha desaparecido, conservado y nombrado. | Nada que arreglar. El paquete que lo declaraba ha desaparecido y queda el que se había ganado el jugador; la identificación está ahí para que él sepa qué lo traería de regreso. |
progress_over_budget | Un paquete por encima de un techo declarado. | El informe imprime lo medido junto a lo permitido. Dividir el registro o eliminar entradas más allá de la línea: el límite es lo que una pantalla o un lector puede contener, no una sugerencia. |
progress_reaches_outside | Un paquete que intenta hacer algo o hablar en nombre de la plataforma. | Retire el campo. El hecho de que un hito alcance la plataforma se deriva de su espacio de nombres y nunca es algo que diga un registro. |
progress_reserved_namespace | Un paquete que reclama un espacio de nombres que no es el suyo. | Utilice el espacio de nombres de su paquete. Las reservadas son nuestras, y uno se creería un gol que parecía desde la tribuna. |
progress_text_not_key | Una oración donde se necesita una clave de catálogo. | Mueva la frase a su catálogo de idiomas y coloque su clave en el campo. Un campo que termina en _key contiene una clave; una frase allí hace que su paquete esté en un idioma para siempre. |
progress_unknown_step | Una condición o modificador que esta compilación no tiene. | El nombre no está en la lista publicada para esa tabla. Elija uno que esté allí: la lista es corta porque cada entrada es algo que esta compilación ya hace. |
progress_unresolved_reference | Un registro con nombre que nadie proporciona. | La identificación nombrada es aquella que no proporciona nada en la composición. O llevas el registro al que apunta o dependes del paquete que lo lleva. |
provider_forbidden_capability | Un paquete solicitaba una capacidad que ningún nivel concede, como un sistema de archivos, una red o un proceso. | Retire la capacidad. Ningún nivel otorga el sistema de archivos, red, proceso o espacio de nombres de otro paquete, y ninguna revisión o firma cambia esto: lo que hace una compilación con el sistema de archivos no es una propiedad que nadie pueda controlar leyéndola. Utilice propose_intent para pasar una propuesta al propietario canónico y write_own_namespace para el estado que debe sobrevivir. |
provider_native_extension_refused | Se encontró una extensión nativa. Tiene plena autoridad sobre el proceso antes de que se aplique cualquier política, por lo que se rechaza por su propio motivo y no como una verificación de confianza fallida. | Retire la extensión del paquete. El motor carga una GDExtension con autoridad total sobre el proceso antes de que se ejecute cualquier parte de esta política, por lo que se rechaza por lo que es y no por quién la firmó, y la ratificación del nivel de proveedor no cambiará esa respuesta. |
provider_tier_inactive | La capa de proveedores de comportamiento no está ratificada en esta compilación, por lo que no se cargó ningún ejecutable. | No hay nada que arreglar en su paquete. Esta compilación no ha ratificado la capa Behavior Vendors, por lo que un script, una escena empaquetada o una extensión nativa son rechazados por quienquiera que los haya firmado. Traiga el mecánico como registros declarativos si una de las familias publicadas puede llevarlo, y lea las notas de la versión de la compilación que ratifica el nivel antes de escribirle a un proveedor. |
provider_unknown_capability | Un paquete solicitó una capacidad que esta compilación no publica. | Elimine la capacidad del manifiesto o reemplácela con una que publique esta compilación. La lista es corta a propósito: un permiso que nadie publica es un permiso sobre el cual el anfitrión no puede razonar, por lo que se rechaza en lugar de ignorarse. |
provider_unknown_load_kind | Un paquete ofrecía algo que esta versión no clasifica. Rechazados en lugar de tratados como datos, porque equivocarse en una suposición aquí es equivocarse en la dirección de su ejecución. | Compare lo que ofrece el paquete con los cuatro tipos que clasifica esta compilación: datos declarativos, una escena empaquetada, un script o una extensión nativa. Cualquier otra cosa se rechaza en lugar de adivinarse, porque adivinar aquí significa adivinar en la dirección en que se llevará a cabo. |
provider_untrusted | El paquete está en un estado confiable que no carga nada, que es el estado en el que comienza cada paquete. | No hay nada que arreglar en su paquete y nada que un paquete pueda arreglar por sí solo. La confianza está adjunta a los bytes exactos y es el jugador quien la otorga, así que instale el paquete desde una fuente de su elección y déjelo confirmar; un resumen revocado no vuelve a ser confiable al ser detectado nuevamente. |
provider_user_trust_required | El nivel lo permitiría y ni una sola persona ha dicho sí a este contenido exacto todavía. | Lleve al jugador a la lista de modificaciones y permítale confirmar este paquete. El nivel lo permitiría y nadie ha dicho aún que sí a este contenido exacto, que es el único paso que una firma deliberadamente no reemplaza. |
quest_already_applied | Un comando que ya había sido ejecutado. | Nada que arreglar. El comando ya había sido ejecutado y no se repitió, y es lo que impide que una recarga pague recompensa dos veces. |
quest_carries_expression | Un paquete que intenta hacer algo o conservar la respuesta "una vez". | Retire el campo. El nivel 1 son los datos: lo que se ejecuta pertenece al juego y las nuevas funciones provienen de un proveedor confiable. |
quest_ending_unreachable | Un final al que nadie podrá llegar. | El final requiere una misión que su arco no contiene. Añade la misión a las etapas del arco, o solicita una que esté allí. |
quest_invalid | El registro no es uno que esta compilación cargaría. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
quest_nothing_applied | Un plan que rechazó algo, por lo que no se ejecutó nada. | Se rechazó algo del conjunto, por lo que no se aplicó nada. Coloque cualquier rechazo en el informe: una reverencia a medias es un estado que nadie puede describir. |
quest_over_budget | Un paquete por encima de un techo declarado. | El informe imprime lo medido junto a lo permitido. Dividir el registro o eliminar entradas más allá de la línea: el límite es lo que una pantalla o un lector puede contener, no una sugerencia. |
quest_text_not_key | Una oración donde se necesita una clave de catálogo. | Mueva la frase a su catálogo de idiomas y coloque su clave en el campo. Un campo que termina en _key contiene una clave; una frase allí hace que su paquete esté en un idioma para siempre. |
quest_unfinishable | Una misión que nadie puede completar. | Asigne a la misión al menos un objetivo no opcional, de lo contrario se completa en el momento en que se acepta. |
quest_unknown_step | Una meta o concesión que esta construcción no tiene. | El nombre no está en la lista publicada para esa tabla. Elija uno que esté allí: la lista es corta porque cada entrada es algo que esta compilación ya hace. |
quest_unresolved_reference | Un registro con nombre que nadie proporciona. | La identificación nombrada es aquella que no proporciona nada en la composición. O llevas el registro al que apunta o dependes del paquete que lo lleva. |
relationship_band_gap | Un intervalo con un valor que no tiene nombres de banda. | Cubre todo el rango de tu póliza, desde el suelo hasta el techo, sin huecos ni superposiciones, utilizando únicamente los nombres de rango publicados. Un valor en un agujero es un valor que ninguna pantalla puede nombrar. |
relationship_carries_behaviour_code | Un paquete que intenta proporcionar qué se ejecuta cuando cambia un informe. | Retire el campo. El nivel 1 son los datos: lo que se ejecuta pertenece al juego y las nuevas funciones provienen de un proveedor confiable. |
relationship_declares_live_state | Un paquete que intenta decir dónde está una relación ahora. | En su lugar, declare el valor inicial. La situación actual de una relación es una cuestión de tiempo de ejecución, y es el jugador quien la movió. |
relationship_invalid | El registro no es uno que esta compilación cargaría. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
relationship_leave_unreachable | Un compañero que nunca podrá irse, o que se marcha inmediatamente. | Mueva el umbral de abandono al rango de la política. En el suelo nunca podrás perder a tu pareja; Sube al tejado la primera noche. |
relationship_origin_lost | El paquete que declaraba un bono desapareció y el valor evolucionado permanece. | Nada que arreglar. El paquete que lo declaraba ha desaparecido y queda el que se había ganado el jugador; la identificación está ahí para que él sepa qué lo traería de regreso. |
relationship_pair_collision | Una pareja ordenada declaró dos veces, quedando sin conexión alguna. | Dos registros reclaman el mismo par ordenado. Elimina uno: conservar ambos haría que ganara el paquete que se cargó primero. |
relationship_unknown_relation | Un tipo de relación o ruta de reclutamiento que esta build no tiene. | Elija una relación de la lista publicada. Uno que esta construcción no tenga se reduciría a nada y la historia que escribiste no sucedería. |
relationship_unresolved_reference | Un registro con nombre que nadie proporciona. | La identificación nombrada es aquella que no proporciona nada en la composición. O llevas el registro al que apunta o dependes del paquete que lo lleva. |
resolution_cache_invalidated | Los artículos cayeron porque su proveedor ya no está activo. | Nada que arreglar. La composición ha cambiado, por lo que lo que resuelven los identificadores se ha recalculado en lugar de reutilizarse. |
resolution_missing | Nadie proporciona la identificación y no hay nada a lo que recurrir. | Reinstale el paquete que proporcionó la identificación o corrija la identificación. El informe lo guarda para que puedas entender cuál de las dos cosas pasó. |
resolution_over_budget | Un paquete o proceso sobre un presupuesto establecido. | El informe imprime lo medido junto a lo permitido. Dividir el registro o eliminar entradas más allá de la línea: el límite es lo que una pantalla o un lector puede contener, no una sugerencia. |
resolution_refused | Una solicitud que esta compilación no realiza. | Lea la regla que menciona el informe y cambie la identificación a algo que el lugar acepte. |
resolution_restart_required | Un cambio de perfil cuyos bytes antiguos no se pueden descargar. | Lo que resuelve esta identificación se cambia de una manera que un juego en ejecución no puede seguir. Reinicie para obtenerlo. |
resolution_tombstoned | Una identificación conocida que un paquete ha eliminado. | Vuelva a instalar el paquete para devolver el contenido real del desecho. La identificación se resuelve en su lápida en lugar de nada, que es exactamente por qué la reinstalación le devuelve al reproductor sus cosas. |
save_campaign_absent | La campaña bajo la cual se realizó el guardado no está instalada. | Instala la campaña que nombra el rescate. El rescate no se abre contra otro, porque sería silenciosamente otro mundo. |
save_composition_matches | Nada de lo que había registrado el rescate se movió. | Nada que arreglar. Los paquetes con los que se realizó este guardado son los paquetes instalados. |
save_content_absent | Contenido en el que los nombres guardados no están instalados. Reportado, no fatal. | Reinstale los paquetes que enumera el informe. Los identificadores permanecen guardados, por lo que lo que ahora no tiene respuesta volverá a tenerla. |
save_orphan_state_carried | Estado sin dueño instalado, arrastrado sin ser ejecutado. | Reinstale el paquete para que ese estado vuelva a significar algo. Se guardó en lugar de eliminarse precisamente para que funcionara. |
save_provider_contract_moved | Una capacidad en la que se basó el rescate ahora responde a un contrato diferente. | Vea si el informe dice migrado, ignorado o rechazado. La versión del contrato de un proveedor cambió entre el guardado y ahora, y esas son las tres respuestas. |
save_write_beside_original | La sesión escribió un nuevo archivo y dejó el original en paz. | Nada que arreglar. El archivo recuperado se escribió junto al original en lugar de encima; el modo seguro nunca sobrescribe el archivo que no pudo abrir. |
selection_campaign_missing | La campaña solicitada no está instalada y no se ha compuesto nada en su lugar. | Instale el paquete que proporciona la identificación de la campaña en el mensaje o inicie otra campaña. La identificación es la que se solicitó, escrita tal como se solicitó, así que compárela con la identificación en el archivo Campaign.json del paquete. No se cargó nada en su lugar: iniciar el juego base te daría un mundo diferente con el nombre que escribiste. |
selection_made | Se seleccionó una campaña, con el motivo por el cual lo fue. | Nada que arreglar. Es la línea que dice qué mundo es este juego y por qué fue elegido, y vale la pena leerla cuando el mundo no es lo que esperabas: la razón te dice si fue solicitado, revivido o el único instalado. |
selection_safe_mode | Los paquetes quedaron fuera, ya sea después de un arranque fallido o porque el jugador lo solicitó. | Lea el motivo antes de cambiar algo. player_asked significa que lo elegiste y no tiene nada de malo. boot_failed significa que la campaña no pudo iniciarse varias veces: desactive las modificaciones instaladas más recientemente, comience una vez y vuelva a colocarlas una a la vez. En modo seguro no se compone ningún paquete, por lo que una coincidencia que funcione aquí dice que la falla está en un paquete. |
selection_save_preserved | Un guardado recuperado se escribió junto al original en lugar de arriba. | No hay nada que arreglar y no elimines el segundo archivo. Recovery escribió su resultado al lado de su archivo guardado en lugar de arriba, por lo que el mensaje nombra ambas rutas: la original es la que no tiene el sufijo .recovery y sigue exactamente como estaba. |
setting_invalid | La declaración no es la que sacaría esta construcción. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
setting_migrated | Llegó un valor con una clave antigua y se transfirió a la actual. | Nada que arreglar. La configuración cambió a su forma actual y el valor anterior quedó atrás. |
setting_owner_missing | Un valor almacenado pertenece a un paquete que no está instalado. Conservado, no aplicado. | Nombra un propietario declarado para la configuración. Uno que esta compilación no tiene es una configuración que nadie jamás leería. |
setting_restart_required | El valor ha cambiado y no puede surtir efecto hasta el próximo arranque. | Reinicie para aplicarlo. La configuración no puede cambiar mientras el juego se está ejecutando. |
setting_secret_withheld | Se ha excluido un secreto de un guardado o informe. | Nada que arreglar. Un valor marcado como secreto se ha omitido en el informe, por lo que el informe se puede pegar en un hilo de error. |
setting_value_refused | Un valor fuera de lo que permite la declaración. En su lugar, responde el valor predeterminado. | Ingrese el valor dentro del rango impreso al lado o elija uno de la lista publicada. El informe muestra ambas cosas. |
settlement_building_unresolved | Un edificio salvado cuyo paquete desapareció, nombrado en lugar de reemplazado. | Vuelva a instalar el paquete que menciona el mensaje para recuperar el edificio, o déjelo en paz: no se perdió nada. El edificio todavía está guardado bajo su identificación y deliberadamente no fue reemplazado por el más cercano que tiene esta construcción, lo que habría puesto los bienes de otra persona dentro de una forja que usted nunca construyó. |
settlement_carries_path | Un registro que nombra una escena, guión o ubicación propia. | Elimine el campo y nombre una identificación en su lugar. Un interior es la identificación de un registro interior, nunca el camino de una escena, y un edificio se ubica nombrando un objeto en el mapa en lugar de llevar sus propias coordenadas. Los campos de ubicación se rechazan por esta segunda razón: un registro que contiene una coordenada es un registro que puede terminar quién sabe dónde cuando su mapa ya no esté allí. |
settlement_invalid | Un registro de liquidación que esta compilación no carga. | Lea el veredicto al lado del código y corrija el registro que nombra. Las causas habituales son un campo obligatorio omitido, una identificación sin el espacio de nombres del paquete al frente y un campo que pertenece a uno de los otros cinco tipos de registros. |
settlement_loot_table_absent | Un contenedor cuya mesa de botín desapareció con su paquete, por lo que está vacío en lugar de sacarlo de otro. | Vuelva a instalar el paquete que proporcionó la tabla de botín si desea que el contenedor se llene nuevamente. Está vacía en lugar de ser sacada de otra mesa, porque al tirarla se entregarían las cosas de otro mundo bajo el nombre de éste. |
settlement_over_budget | Más edificios o servicios de los que puede contener un asentamiento. | Elimine una parte de lo que contaba el mensaje o divida el acuerdo en dos. El conteo y el límite están ambos en el mensaje, por lo que la diferencia es cuántos tienen que salir. |
settlement_text_not_key | Un campo que se muestra en la pantalla que contiene una frase en lugar de una clave de catálogo. | Reemplace la frase con una clave de catálogo y coloque la frase en su tabla de idiomas. Un nombre escrito dentro del registro no se puede traducir y se ve en inglés en todos los idiomas. |
settlement_unreachable_service | Un servicio ofrecido en un fondeadero que el mapa no declara. | Agregue el ancla a la capa de anclas del mapa con la identificación que nombra el servicio, o cambie el nombre del servicio a uno que esté allí. El registro y el mapa son legítimos por sí solos, y el resultado es un contador que nadie puede soportar. |
settlement_unresolved_reference | Un registro que nombra algo que nadie proporciona. | Agregue el registro con nombre a su paquete o corrija la identificación. El mensaje nombra tanto el registro al que apunta como la identificación a la que apunta, luego lo compara con los identificadores que declaró. |
society_dimension_leak | Se descubrió que una dimensión de la identidad conduce a otra. | Elimine el campo que nombra la otra dimensión. Una cultura no tiene un campo de fe: la derivación debe ser imposible de escribir y no simplemente desaconsejable, de modo que nada pueda dar a una facción una fe que nadie escribió. |
society_heraldry_path | Un letrero que nombra un archivo en lugar de un motivo. | Una insignia heráldica llamada a. En su lugar, mencione una razón: se elige un letrero entre los que diseña esta construcción. |
society_invalid | El registro no es uno que esta compilación cargaría. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
society_mutation_in_definition | Una definición que te pide que hagas algo. | Retire el campo. Los adaptadores de definición describen; no tienen autoridad para cambiar lo que describen. |
society_relationship_collision | El mismo par ordenado declaró dos veces. | Un par ordenado ha sido declarado dos veces, por lo que el par no tiene posición. Elimine uno: conservar ambos haría que el mundo dependiera de qué paquete se cargó por última vez. |
society_relationship_one_sided | Una postura cuyo contrario nadie ha declarado; lo contrario es el valor predeterminado. | No hay nada que arreglar, si lo quisieras. Sólo se declara una dirección de este par, y la opuesta no declarada es la predeterminada: una facción que no sabe que tiene un enemigo es una premisa, y esta línea está aquí para ser una premisa elegida. |
society_unresolved_reference | Un registro con nombre que nadie proporciona. | La identificación nombrada es aquella que no proporciona nada en la composición. O llevas el registro al que apunta o dependes del paquete que lo lleva. |
state_namespace_ignored | El paquete ya no lee este estado. | Declare el espacio de nombres o elimine el estado. Quedó bajo una ley que nadie reclama y se dejó de lado en lugar de aplicarse. |
state_namespace_malformed | Un espacio de nombres guardado no es un nombre que esta compilación aceptaría. | Escriba un espacio de nombres que identifique inequívocamente un paquete. Todo lo que hay en un rescate pende de él, entonces una forma que no sabemos cómo resolver es que luego nadie puede reclamar. |
state_namespace_orphaned | Ningún paquete instalado tiene este estado y ha sido impulsado. | Reinstale el paquete para recuperar su estado. El espacio de nombres pertenece a uno que ya no existe y el estado se ha conservado en lugar de eliminarse. |
state_namespace_rejected | El paquete ha rechazado su estado guardado para esta sesión. | El paquete intentó escribir fuera del espacio de nombres que posee. Escriba dentro del suyo: no depende de usted cambiar el estado de otro paquete. |
state_namespace_reserved | Un paquete ha reclamado un espacio de nombres que pertenece al host. | El espacio de nombres es uno de los invitados. Toma el de tu paquete. |
state_schema_future | Fue escrito desde una versión de paquete más nueva que la que tiene esta compilación. | Actualiza el paquete. El estado guardado fue escrito por una versión más reciente que la instalada, y no pretendemos recuperar un estado. |
state_schema_migrated | Estado más antiguo de la construcción, entregado al paquete para su traslado. | Nada que arreglar. Un Estado más antiguo alcanzó su forma actual gracias a la migración del propio paquete. |
state_schema_too_old | Indique más antiguo que el piso que el paquete dice poder leer. | Vea qué respuesta dice el informe que eligió el paquete. El estado es más antiguo que la forma más antigua desde la que migra el paquete, por lo que decide qué hacer con él. |
state_write_outside_namespace | El escritor se dirigió a un espacio de nombres que no es el suyo. | Escribe dentro de tu espacio de nombres. Un paquete que cambia el estado de otro es la forma en que un guardado deja de pertenecer a alguien. |
strategic_carries_policy | Un paquete que intenta proporcionar la regla en sí. | Retire el campo. El nivel 1 son los datos: lo que se ejecuta pertenece al juego y las nuevas funciones provienen de un proveedor confiable. |
strategic_invalid | El registro no es uno que esta compilación cargaría. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
strategic_over_budget | Un paquete por encima de un techo declarado. | El informe imprime lo medido junto a lo permitido. Dividir el registro o eliminar entradas más allá de la línea: el límite es lo que una pantalla o un lector puede contener, no una sugerencia. |
strategic_text_not_key | Una oración donde se necesita una clave de catálogo. | Mueva la frase a su catálogo de idiomas y coloque su clave en el campo. Un campo que termina en _key contiene una clave; una frase allí hace que su paquete esté en un idioma para siempre. |
strategic_unknown_term | Una consideración, una intención o una clase que esta construcción no tiene. | La palabra no está en la lista publicada para ese campo. Elige una que exista: bajo una palabra que no tenemos, nada respondería. |
strategic_unresolved_reference | Un registro con nombre que nadie proporciona. | La identificación nombrada es aquella que no proporciona nada en la composición. O llevas el registro al que apunta o dependes del paquete que lo lleva. |
strategic_weightless | Un planificador que siempre decidiría de la misma manera. | Asigne al menos una consideración un peso distinto de cero. Los pesos todos en cero dan la misma puntuación a cada opción y eligen siempre la primera en orden alfabético. |
theme_carries_executable | Un tema que nombra una escena, un guión o una ruta de recurso. | Retire el campo. Un tema describe cómo ves las cosas; un script dentro de un tema es un programa que se ejecuta detrás de cada pantalla. |
theme_contrast_too_low | Un par de colores por debajo de la relación de contraste mínima. | Mueva el primer plano o el fondo hasta que la proporción supere el mínimo impreso junto a él. Es la única regla temática que un jugador escucha directamente. |
theme_refused | Un tema que esta compilación no registra. | Lea la propiedad que nombra el informe e infórmela dentro de lo que permite. |
tombstone_blocks_campaign | La familia declarada sin la cual la campaña no se cargará. | Esta familia lleva y falta su paquete, por lo que la campaña no inicia. Reinstalarlo: irse sin él sería un mundo en el que faltaría algo a lo que se hace referencia en todas partes. |
tombstone_placeholder_substituted | Un sustituto poseído por el motor responde en su lugar. | Reinstale el paquete para recuperar el contenido real. El informe indica qué sustituto se utilizó mientras tanto. |
tombstone_recorded | Una identificación cuyo paquete desapareció se registró en lugar de eliminarse. | Nada que arreglar. Un paquete desaparece y sus identificadores se dejan guardados, que es la única razón por la que reinstalarlo le devuelve al reproductor sus cosas. |
tombstone_reinstall_recovered | El paquete regresó y la lápida volvió a tener contenido real. | Nada que arreglar. El paquete ha vuelto y sus lápidas se resuelven nuevamente en contenido real. |
tombstone_unresolved_reference | Algo en el guardado todavía apunta a una identificación reducida a una lápida. | La identificación nombrada es aquella que no proporciona nada en la composición. O llevas el registro al que apunta o dependes del paquete que lo lleva. |
unit_carries_behaviour_code | Un paquete que intenta proporcionar algún comportamiento. | Retire el campo. El nivel 1 son los datos: lo que se ejecuta pertenece al juego y las nuevas funciones provienen de un proveedor confiable. |
unit_incomplete_for_category | Una unidad que carece de lo que requiere su categoría. | Agregue la parte que la categoría requiere. La tabla de categorías las enumera: un compañero necesita equipo, una tropa necesita comportamiento y un líder nunca recurre a uno. |
unit_invalid | El registro no es uno que esta compilación cargaría. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
unit_unknown_behaviour | Un perfil de comportamiento que esta compilación no tiene. | Elija un perfil de comportamiento de la lista publicada. Uno que esta versión no tiene se rechaza en lugar de reemplazarse por uno predeterminado, porque un jefe que silenciosamente se ha convertido en un vagabundo es una pelea que no sucede. |
unit_unresolved_reference | Un registro con nombre que nadie proporciona. | La identificación nombrada es aquella que no proporciona nada en la composición. O llevas el registro al que apunta o dependes del paquete que lo lleva. |
unit_visual_missing | Un aspecto se ha resuelto en su sustitución. | No se proporciona el aspecto que mencionaste, por lo que se utilizó el sustituto de ese tipo. Traiga el recurso o señale uno que exista. |
world_calendar_inconsistent | Un calendario o una fiesta que no puede suceder. | Coloca la pareja que menciona el informe. Las estaciones, los meses y los días festivos deben coincidir, y uno que no coincide es un calendario que el mundo lee de dos maneras. |
world_carries_clock_control | Un paquete que proporciona su propio tiempo. | Retire el campo. Un paquete declara cuánto vale una temporada y no puede mover el reloj: el reloj canónico tiene un solo dueño. |
world_carries_randomness | Un paquete que proporciona su propia aleatoriedad. | Elimine la semilla y nombre un flujo en su lugar. La semilla de la coincidencia pertenece al anfitrión y el flujo se deriva de él, por lo que un paquete que lleva su propia semilla es un mundo que ignora la coincidencia en la que se encuentra. |
world_invalid | El registro no es uno que esta compilación cargaría. | Lea el veredicto al lado del código. Nombra la regla que batió el récord, y cada una es un campo para eliminar, un campo para agregar o una palabra para cambiar. |
world_unresolved_reference | Un registro con nombre que nadie proporciona. | La identificación nombrada es aquella que no proporciona nada en la composición. O llevas el registro al que apunta o dependes del paquete que lo lleva. |
Limita, guarda y comparte
Lo que un mod nunca puede hacer
Rechazado por la construcción, no desanimado.
| Sin código | Scripts, extensiones, ejecutables, archivos shell, en cualquier parte de su paquete. |
| Sin escenas ni archivos de recursos | Un registro que apunta a uno se rechaza incluso si el archivo no está allí. |
| Sin oscurecimiento de los archivos base | Un mod agrega y cambia registros; no puede reemplazar los archivos del juego. |
| No hay nada nuevo | Un nuevo privilegio sí, un nuevo tipo de privilegio no. |
| Sin comandos, cargas automáticas ni configuraciones de proyecto | No accesible en absoluto. |
| Sin cancelaciones reales | remove elimina un registro de la circulación y lo deja resoluble. Solo vendor_inventories te quita uno. |
La lista exacta, por qué lo menciona una negativa:
- Un archivo de registro puede tener 4 MB, contener 4096 registros y anidar 16 niveles. El catálogo más grande que trae el juego contiene unos cientos de ellos, por lo que un archivo que activa uno de estos límites está mal formado en lugar de ser ambicioso.
- Archivos que su paquete no puede contener en absoluto, en ninguna parte:
.bat,.cmd,.dll,.dylib,.exe,.gd,.gdc,.gde,.gdextension,.ps1,.sh,.so,.vbs. Cada uno de ellos es un comportamiento: un script, una biblioteca nativa o algo que el host ejecutaría. - Extensiones a las que un registro no puede apuntar:
.bat,.cmd,.dll,.dylib,.exe,.gd,.gdc,.gde,.gdextension,.ps1,.res,.scn,.sh,.so,.tres,.tscn,.vbs. Es la lista anterior más escenas y recursos, porque un registro que nombra a uno le pide al juego que lo cree. - Claves rechazadas sean las que contengan:
resource_local_to_scene,resource_path,scene,scene_path,script. - Rutas rechazadas dondequiera que aparezcan: Cualquiera que comience con
res://ouser://. Un registro dirige el contenido dentro de su propio paquete.
El tamaño también tiene límites, por paquete y en todos ellos, y superarlo no siempre es un rechazo:
- ok Por debajo del límite. No se informa nada.
- advertir Más allá del umbral suave y cargado lo mismo. Los que crean están advertidos; el jugador no se detiene.
- degradar Sobre el límite de un tamaño que el huésped puede reducir en lugar de rechazar. Se llama en qué se basa, porque es peor un juego que se ejecuta diferente en silencio que uno que dice por qué.
- rechazar Cruzar la línea en una dimensión que no tiene una versión más pequeña de sí misma. El paquete no se carga y se nombra.
| Tamaño | un paquete | Todos | Si lo supera |
|---|---|---|---|
records | 20 000 | 120 000 | reject |
decoded_image_bytes | 256MB | 1GB | reject |
decoded_audio_bytes | 128MB | 512MB | reject |
map_cells | 4 194 304 | 8 388 608 | reject |
map_objects | 65 536 | 262 144 | reject |
effect_instances | 4 096 | 16 384 | degrade |
provider_frame_usec | 2 000 | 8 000 | degrade |
worker_tasks | 8 | 32 | reject |
queue_depth | 512 | 2 048 | degrade |
teardown_msec | 100 | 400 | warn |
Una revisión general duplica esas cifras y una conversión total las cuadriplica. Cuatro veces, no ilimitado: un límite que un paquete puede declarar no es un límite.
Solo se mueve la línea de retiro. Una familia acepta un remove cuando logra entregar al cargador el registro que está siendo retirado; hoy dos lo hacen. Todo lo demás sobre esta mesa es permanente.
No viene ninguna capa de secuencias de comandos. El manifiesto incluye un tipo de paquete que envía comportamiento en lugar de datos: lo único que podría autorizar su ejecución lo rechaza, no hay un entorno de pruebas detrás y un paquete que lo declara se rechaza hoy. Diseño para datos.
Lea “datos” en términos generales. Los números son datos. El equilibrio son datos. Qué hace un arma, cuánto cuesta una herida, a cuánto se vende un bien, cómo una facción sopesa una decisión: todo tuyo. Lo que no son datos es una mecánica que el juego nunca tuvo: es un código que alguien escribe y prueba. Si tu idea lo necesita, es un juego diferente y no un mod.
Guarda
Tus identificaciones terminan en el archivo guardado del jugador. Una identificación publicada es una promesa.
| Regla | Por qué |
|---|---|
| Nunca cambies el nombre de una identificación | Todos los rescates que lo utilizaron permanecen varados. Agregue uno nuevo y deje el anterior en paz. |
| Desinstalarte nunca elimina las cosas de un jugador | Guardar mantiene los identificadores que no puede resolver y los marca, por lo que la reinstalación devuelve la bóveda. |
Aumenta version cada vez que cambies algo | Es lo que un jugador puede ver. |
Cada forma en que un conjunto de paquetes puede diferir de aquel con el que se guardó tiene un nombre, y cada nombre decide una cosa: si la sesión puede escribir en ese archivo.
| Veredicto | Puede escribir tu guardado | Qué significa |
|---|---|---|
compatible | Sí | La composición corresponde a aquella bajo la cual se realizó el ahorro. |
degraded | Sí | Entendido, falta algún contenido con nombre. El juego continúa y se reporta la ausencia. |
incompatible | No, el archivo se queda solo. | La sesión no puede respetar lo que dice el guardado. El archivo original se deja solo. |
| ¿Qué es diferente? | Veredicto | Qué significa |
|---|---|---|
identical_composition | compatible | Mismos paquetes, mismas versiones, misma composición. |
mod_added | compatible | Un paquete del que el rescate nunca supo nada. Nada de lo que había grabado se movió. |
mod_missing | degraded | Un paquete cuyo nombre guardado no está instalado. Sus identificaciones todavía están en el archivo y permanecen allí. |
mod_upgraded_compatible | degraded | Un paquete ha cambiado pero permanece dentro de la compatibilidad que afirma. Informado, porque un hash modificado es una respuesta modificada incluso cuando es una respuesta legítima. |
provider_contract_incompatible | incompatible | Una capacidad con la que contaba el rescate responde a través de un proveedor cuyo contrato se ha movido. Avanzar sería adivinar lo que significa. |
conversion_missing | incompatible | La campaña en sí está ausente. Cada identificación en el archivo pertenece a un mundo que no está instalado. |
safe_mode_disabled | degraded | La sesión empezó con los paquetes apagados a propósito. El guardado es legible y su contenido modificado está ausente por elección propia. |
orphan_state_preserved | degraded | El estado cuyo paquete ha desaparecido pasa intacto. Conservado, nunca realizado. |
Lea la línea incompatible dos veces: el guardado original se deja solo. Un archivo sobrescrito por una sesión que no lo entendió es un juego perdido, y un jugador que pierde uno debido a un mod no instala otro.
Cada paquete cargado recibe una huella digital: lo mismo se hace para el mismo manifiesto y contenido, diferente cuando cambia el archivo de contenido. El resumen del conjunto compuesto también incluye el ID, la versión, el orden de carga y el resumen de contenido de cada paquete, por lo que los mismos paquetes en un orden diferente no pueden pretender tener la misma composición. modding_fingerprint_report imprime estos valores y guarda el esquema v56 registra la lista de huellas digitales activas para que una carga posterior pueda alertarlo sobre un paquete faltante o modificado. Aún es necesario aumentar su version porque es el valor que un jugador puede ver y comparar antes de instalar.
Compártelo
Comprime la carpeta en un zip. El formato de distribución está aquí. No hay catálogo dentro del juego; Ponlo en Nexus Mods.
| Paso | Qué |
|---|---|
| Controlar | Limpiar validador, con --strict, antes de cargar. |
| Cremallera | La misma carpeta, por lo que el archivo contiene my_mod/mod.json. |
| Versión | Eleva version a mod.json en cada carga. |
| Requisitos | Incluya también su dependencies en la página Nexus. |
| De' | Qué familias tocas y qué identificadores sobrescribes con override. |
Nunca cambies el id de tu paquete. Es el espacio de nombres que lleva cada uno de tus ID, lo que otro paquete nombra como dependencia y lo que un guardado pone por escrito. Cambiarle el nombre hace que todos los guardados existentes crean que su paquete ha sido desinstalado y ha aparecido otro junto a él. En su lugar, cambie el name que se muestra.
Dígale a la gente dos cosas y se ahorrará más llamadas de soporte que con cualquier otro: el game_version con el que construyó y si puso canon_safe.
La versión que se escribirá hoy es 0.0.0-dev. Es al que responde esta compilación y es el que indica cada ejemplo en esta página, y es un número único en lugar de un rango: cuando salga el juego, cambiará aquí primero.
Los archivos tienen límites, decididos por el encabezado y no después de la extracción:
- Máximo 4.096 entradas, ninguna de más de 16 MB y 128 MB extraídos en total.
- Un nombre puede tener 200 caracteres y 8 carpetas de profundidad.
- Nada puede pretender expandirse más de 200 veces, algo que ningún contenido honesto logra: el texto se comprime alrededor de quince. Unos pocos kilobytes que se extraen en gigabytes es el ataque para el cual existe este número.
- Se rechaza una entrada que no sea un simple archivo o carpeta: enlace simbólico, enlace físico, dispositivo, fifo, socket. El enlace simbólico es lo que importa, porque su nombre puede ser completamente ordinario y siguiendo se escribe hacia donde apunta.
- Se rechaza un archivo dentro de su archivo en lugar de medirse (
.7z,.bz2,.gz,.pck,.rar,.tar,.xz,.zip). El exterior declara hasta dónde se extienden sus voces; no puede declarar hasta dónde se extienden los de uno interno.
No hay ninguna tienda para publicar hoy, y esta es la forma de lo que habrá allí. La distribución ahora es el zip y la página Nexus de arriba: Nada de lo que sigue es un campo que debes completar para una carga que puedes hacer esta semana. Está aquí porque los campos ya están declarados en la compilación, por lo que una ruta a una tienda es cuestión de conectarlos en lugar de inventarlos, y porque un paquete escrito hoy no tendrá que reescribirse para viajar de esa manera.
Un paquete que pasa por una tienda lleva más cosas que las que lleva la cartera:
| ¿Qué trae? | Campos |
|---|---|
| Quién es | stable_id, version |
| de donde viene | author, license, source_url, package_hash |
| ¿Qué dice una tienda al respecto? | content_rating, content_warnings, revocation_status |
| como fue entregado | store, store_id, subscription_id |
| Estado | Se instala | Qué significa |
|---|---|---|
none | Sí | No se informó nada. |
reported | Sí | Alguien lo denunció y no se decidió nada. El jugador es notificado y elige. |
quarantined | No | Retenido en espera de decisión. No se instala y no se borra lo que ya está instalado. |
revoked | No | Retirado. No se instala y una copia instalada se desactiva en lugar de eliminarse, porque las partidas guardadas del jugador aún nombran su contenido. |
Los dos estados que bloquean una instalación aún no eliminan nada.
Lo que una nueva compilación puede hacerle a su paquete
game_version no es un adorno. El juego compara lo que construiste con lo que es:
| Veredicto | ¿Qué significa para ti? |
|---|---|
supported | La compilación que nombraste es esta, o lo suficientemente cerca. Nada que hacer. |
older_build | Has construido contra un juego más antiguo. Se carga de todos modos, y la posible sorpresa vendría por lo que se haya movido mientras tanto. |
newer_build | Has creado un juego más nuevo que el que estás ejecutando. El paquete se denomina así en lugar de estar medio cargado con la esperanza de que todo lo que utiliza ya exista. |
unreadable | El game_version que escribiste no es una versión. Esto siempre es un error tipográfico. |
Lo que hagas al respecto depende de lo que se movió:
| Clase | Qué significa | ¿Qué te debe el juego? |
|---|---|---|
| sin alterar | Nada de lo que un paquete pueda observar se ha movido. | ninguno |
| aditivo | Hay algo nuevo y todo lo que había todavía significa lo que solía significar. | un aumento menor |
| rotura | Un paquete escrito sobre la superficie anterior ahora puede ser incorrecto sin haber sido modificado. | un mayor aumento |
Un cambio cuenta como un aborto por uno de estos motivos: field_removed, default_changed, type_changed, constraint_changed, required_added, operation_removed, root_changed, format_changed, id_field_changed, catalogue_changed, family_removed, contract_major_changed_without_new_id. default_changed es el que parece aditivo y no lo es. Un campo cuyos movimientos predeterminados reescriben el comportamiento de cada paquete que nunca lo mencionó y ninguno de sus autores cambió nada. constraint_changed cubre límites y enumeraciones, mientras que la raíz, el formato, el campo de identificación, otros metadatos del catálogo y los cambios de eliminación de familia alteran dónde o si se puede leer un paquete.
Un nombre que va a desaparecer queda obsoleto antes de eliminarse y continúa funcionando durante al menos 2 versiones menores después de la versión que lo dejó obsoleto.
Política, en cuatro frases
Quien decide si dedicar cien horas a un paquete en realidad sólo se hace una pregunta: qué les sucede cuando el juego se actualiza. Aquí está la respuesta, antes de que haya una lista para leer.
| Pedido | Respuesta |
|---|---|
| ¿Aún se cargará mi paquete? | Sí, a menos que una versión se indique a continuación como de última hora, y ninguna versión se encuentra en la lista sin aparecer allí primero. |
| ¿Sobrevivirán las partidas guardadas del jugador? | Sí. Una sesión que no puede entender un guardado se niega a escribir en él en lugar de sobrescribirlo, y un guardado mantiene los identificadores que no puede resolver en lugar de descartar las cosas. Guardados. |
| ¿Con cuánto aviso recibo? | Un nombre queda obsoleto antes de eliminarlo y continúa funcionando durante al menos 2 versiones menores después de la versión que lo dejó obsoleto. |
| ¿Cómo lo sabré? | La fila aparece en la siguiente tabla, con lo que se ha movido y lo que ha cambiado, antes de la versión a la que pertenece. |
Lanzamientos que rompen paquetes
| Liberar | Fecha | que se rompe | que hacer |
|---|---|---|---|
| — | — | Todavía nada. Ningún lanzamiento rompió un paquete. | — |
La tabla está vacía y no es un marcador de posición. Existe ahora para que la primera fila tenga un lugar donde aterrizar y para que la promesa anterior se escriba antes de probarla en lugar de después. Una línea aquí nombra la versión, el día en que salió, exactamente en qué forma dejó de aceptarse y el cambio que corrige un paquete, no "cambios varios".
El trabajo entrante que podría romper algo va a la misma mesa, marcado como entrante, antes de salir.
Si el juego no comienza
Un perfil que no se inicia se vuelve a intentar un número limitado de veces, luego el juego ofrece un camino de regreso en lugar de intentarlo sin cesar.
Se reintenta un perfil 3 veces. Después de eso, el juego deja de intentarlo y ofrece uno de estos en su lugar.
- reintentar Por debajo del límite de reintentos. Se vuelve a intentar con el mismo perfil.
- last_known_good Se ofrece un perfil que se lanzó en el pasado. No se desinstala nada.
- safe_mode No se cargan paquetes para una sesión. El perfil permanece intacto y regresa cuando el jugador lo solicita.
Dónde falló le indica qué buscar:
| donde fracasó | ¿A qué apunta? |
|---|---|
discovery | Lea lo que está instalado. Un error aquí suele ser un paquete con formato incorrecto. |
provider_start | Comienza el que la composición ha seleccionado. Un fracaso aquí nombra una habilidad. |
first_scene | La primera escena que vería el jugador. Una falla aquí es el contenido, no el cableado. |
Nada de esto desinstala tu paquete ni cambia tus archivos. El modo seguro es una sesión sin paquetes cargados y tu perfil te está esperando cuando lo solicitas.
Una conversión total
Aún no es una ruta publicada para los creadores. La compilación comprende el manifiesto y trae consigo el accesorio Ashen Reach; un flujo de trabajo público y empaquetado no está disponible. Trate el dispositivo como un contrato de ingeniería, no como una promesa de que podrá publicar uno hoy.
Se declara con type: total_conversion. A continuación, fallback_policy decide si una conversión medio instalada muestra el contenido del juego o nada.
| Reemplaza | No se puede agregar |
|---|---|
| Los lugares, la gente, la guerra, los mitos, el mapa, los nombres de todo. Tus reinos, tus dioses, tu propia economía. | Un nuevo tipo de cosa. Una espada que golpea más fuerte es un número; un arma que dispara un rayo y necesita las reglas del rayo es una característica, y las características son código. |
Qué cambia y qué no
Casi nada cambia. La carpeta es la carpeta, mod.json es mod.json, las familias son las mismas familias con los mismos campos, los identificadores tienen el mismo espacio de nombres, el validador aplica las mismas reglas y la pantalla Mod informa los mismos estados. Cada tutorial en esta página es un tutorial para construir una parte de una conversión. La distancia entre un paquete que agrega un comerciante y un paquete que es un reino completo es una cantidad récord, no una habilidad diferente.
Tres cosas realmente cambian y vale la pena conocerlas antes de comenzar:
| Qué | Como |
|---|---|
| El cartel | type: total_conversion, y al lado fallback_policy, que es vanilla o none y vale vanilla si no lo escribes. vanilla significa que una conversión medio instalada muestra el contenido del juego donde falta el tuyo; none significa que no muestra nada. |
| Presupuestos | Cuatro veces el perfil ordinario... y un perfil, no una exención. Las palabras de la compilación en sí: «Cuatro veces, no ilimitadas: un límite que se puede declarar no es un límite.» Si total_conversion eliminara los límites, se convertiría en la línea que cada paquete escribe para escapar de ellos. |
| Las palabras no traducidas dejan de recaer en las del juego | Normalmente, una clave que falta se reduce a player_locale, luego al idioma predeterminado de tu paquete, luego a el catálogo de juegos y luego a la clave misma. En una conversión total, ese tercer paso se elimina. Una clave que usted no escribió se considera la clave y se informa. |
Ese tercer paso se siente como una pérdida y es todo lo contrario. Old Seat que surge en un mundo que no tiene Old Seat no es una traducción ligeramente incorrecta: es el juego básico que brilla desde debajo de lo que has construido encima. Quitar el paso significa que un agujero en tus palabras es algo de lo que te cuentan en lugar de algo que encuentra un jugador.
¿a donde va?
Vale la pena decirlo claramente, porque cambia lo que vale la pena aprender.
El motor de Bonemark fue construido para soportar más que Bonemark. El escenario son los datos: los lugares, las personas, la economía, los mitos y las palabras de todos ellos son registros del mismo tipo que esta página ha descrito. Es por eso que el tipo de conversión completo existe en el manifiesto, y es por eso que la compilación trae consigo una segunda configuración como elemento fijo en lugar de una prueba de una línea de código.
Así que la forma a largo plazo no es "añadir una espada". Es que cualquiera que aprenda estas familias está aprendiendo a construir un mundo en este motor, y la distancia entre un paquete que agrega un comerciante y un paquete que es un reino completo es una cantidad récord y no una habilidad diferente.
Steam Workshop es la dirección para hacer llegar paquetes a los jugadores, y es por eso que Compartirlo describe los campos de una tienda que todavía no vende nada. Suscribirse a un paquete en lugar de extraer uno cambia cómo llega y nada sobre cómo se escribe: la misma carpeta, el mismo mod.json, los mismos ids.
No hay fecha para ninguno de los dos y no hay un segundo escenario nombrado: uno existe como un elemento de ingeniería, que no es lo mismo que uno anunciado. Lo que aquí se dice es una dirección y lo que cuesta estar preparado: es decir, que lo que se aprende hoy no dejará de serlo cuando se abra la puerta.
Poseer un mod
Las mismas condiciones en las que se ha asentado cada escena de modding, porque son las que funcionan. No hay nada inusual aquí ni nada sofisticado.
| Tu mod es tuyo | Los discos que escribiste, las imágenes que dibujaste, el sonido que hiciste. Siguen siendo tuyos. Publicar un mod no le da a nadie derecho a tu trabajo. |
| El contenido del juego sigue siendo el juego | Consulte lo que quiera: anule una identificación, arregle un campo, viste un objeto. No lo saques, no lo vuelvas a empaquetar ni lleves copias en tu bolso. Esto es principalmente para ti: un paquete no puede ocultar los archivos del juego, por lo que es difícil cruzar la línea por accidente. |
| Los derechos de autor no se mueven en ninguna dirección | Es el nombre legal de las dos líneas anteriores, y vale la pena decirlo claramente porque es lo que la gente da por sentado a la inversa. Publicar un paquete no revela tu trabajo al estudio; instalar uno no te revela el juego. Los derechos de autor de los discos que ha escrito y del arte que ha creado son suyos, y los discos, el arte, el sonido y la configuración de Bonemark permanecen en el estudio. La conversión total es un caso que vale la pena hacer explícito: reemplazar la configuración que ve un jugador no otorga licencia para la configuración reemplazada, y un paquete aún no puede transportar los archivos del juego. |
| Las modificaciones son gratuitas | Sin ventas, sin muros de pago, sin acceso anticipado mediante pago, en cualquier tienda o plataforma. Y ni siquiera son nuestros para venderlos: la misma regla rige para el estudio. |
| Las donaciones están bien | Un tarro de propinas, un Patreon, una página de agradecimiento. Es un soporte para una persona, no un precio para un mod, y todo escenario saludable lo permite. |
| El trabajo de otra persona requiere su permiso | Un personaje, un sonido, un sprite, un conjunto de registros de otro paquete: pregunta y cita al autor donde un jugador pueda leerlo. |
| Las traducciones están permitidas de forma predeterminada | Cualquiera puede traducir su paquete y publicar la traducción, citándolo. Dígalo en su página si prefiere que le pregunten primero. |
| Reutilizar pregunta primero | Aprovechar el paquete de alguien, continuar uno abandonado, tomar sus registros y ponerlos en el tuyo: pregúntale. El silencio no es un sí. |
Porque lo gratuito no es negociable. Las modificaciones pagas se han probado a gran escala y se han retirado siempre: en el momento en que hay dinero en juego, las discusiones giran en torno a quién posee qué idea en lugar de qué construir a continuación, y la escena compartida comienza a mantenerse firme. En este ecosistema todos están al mismo nivel, y eso incluye a quienes crearon el juego.
Una cosa podemos pedir. Que se elimine un paquete, y solo por motivos concretos: contiene archivos del juego, se hace pasar por alguien o contiene material ilegal en el lugar donde está alojado. No porque no estemos de acuerdo con él.
Decidido por el estudio el 14-08-2026. El texto aquí es política; un abogado lo leerá antes de que la modificación se abra públicamente y, si esto cambia una palabra, esta página cambiará con usted.
donde preguntar
Discord, y aún no está abierto. Ahí es donde se responderán las preguntas sobre modificación, y la invitación no está escrita en ninguna parte porque no hay nada a lo que invitar a nadie. La marca Discord en la portada es aburrida por la misma razón; el día que se enciende es el día en que esta línea llevará la dirección.
Decir «Discord» antes de que exista la dirección vale más que no decir nada: te dice dónde buscar y te dice que no busques en un foro que nunca se ha abierto.
Mientras tanto, lo que responde a casi todas las preguntas sin que nadie más intervenga es [Antes de pedir ayuda a alguien] (#antes de pedir ayuda a alguien): el bloque de verificación previa nombra la compilación, los paquetes, los estados y el motivo detrás de cada rechazo, y casi todo lo que una persona respondería ya está ahí.