Usare i mod
Dov'è la cartella dei mod
Apri Mod dal menu principale. Il percorso è scritto in cima alla schermata, con accanto un pulsante che apre la cartella nel tuo gestore di file.
Sta accanto ai tuoi salvataggi, ed è la stessa cartella sia che tu stia installando il mod di qualcun altro sia che ne stia scrivendo uno tuo. Niente viene letto mentre il gioco è in esecuzione, quindi non importa se il gioco è aperto mentre sposti i file.
Installarne uno
Un mod è una cartella con mod.json in cima. La maggior parte dei download è quella cartella dentro uno zip.
| 1. Estrailo | In modo che la cartella che contiene mod.json stia direttamente dentro la cartella dei mod. Uno zip che si estrae in northern_reach/northern_reach/mod.json è di un livello troppo profondo e il gioco non lo vedrà. |
| 2. Riavvia il gioco | I pacchetti vengono letti all'avvio. Non esiste installazione a caldo. |
| 3. Accendilo | Apri Mod e usa l'interruttore. Una cartella copiata viene trovata e lasciata spenta: niente si carica per il solo fatto di essere comparso in una cartella. |
| 4. Riavvia di nuovo | La riga dice Attivo — riavvia per caricare finché non lo fai. Poi dice Caricato. |
Un mod che hai copiato dentro resta spento finché non dici tu. Il gioco rifiuta gli eseguibili senza discutere, ma un pacchetto di dati può comunque cambiare prezzi, oggetti e persone in modi che non hai chiesto, e uno che spunta da solo dentro una partita già avviata è un problema che nessuno vuole diagnosticare. Perciò il gioco chiede. È un riavvio in più la prima volta, e mai più per quel pacchetto.
Non c'è un launcher, non c'è un file di load order da modificare e non c'è niente da registrare. L'ordine di caricamento è un numero dentro ogni pacchetto, scelto dal suo autore.
Inizia una nuova partita per un pacchetto che aggiunge persone, luoghi o quest. Un salvataggio già in corso conserva il mondo con cui è stato creato. I pacchetti che cambiano solo numeri, immagini o colori sono visibili in una partita già iniziata. I file audio e dei font vengono validati, ma nessuna superficie di pacchetto in esecuzione li consuma ancora.
Si è caricato?
Mod, nel menu principale. Ogni pacchetto trovato sta su una riga, con uno stato in una parola: caricato, disattivato, non valido, in conflitto, richiede un altro mod, ignorato.
Un mod può anche spegnersi da solo, e dice perché. L'interruttore che hai messo vale per il pacchetto su cui l'hai messo, non per il suo nome nella cartella. Gli id dei mod li scelgono gli autori e non c'è niente che li coordini, quindi due mod senza rapporto fra loro chiamati entrambi northern_reach sono un incidente ordinario — e senza questo il secondo erediterebbe l'interruttore del primo. Se il mod sotto un id non è quello che avevi acceso, la riga lo dice: questo non è il mod che hai acceso. Aggiornare un mod sul posto conserva il tuo interruttore; cancellarlo e copiarne un altro no.
Se sei l'autore di un mod e vedi quella riga sul tuo pacchetto, hai una collisione di id con il mod di qualcun altro. Scegli un id meno ovvio.
Due di quelle parole riguardano un riavvio che devi tu, non il pacchetto. Attivo — riavvia per caricare vuol dire che l'hai acceso e nessuno l'ha ancora letto; Spento — riavvia per scaricare vuol dire il contrario, e il suo contenuto è ancora nel gioco finché non riavvii. Sono parole separate di proposito: una schermata che dicesse «Caricato» nel momento in cui giri un interruttore ti manderebbe a cercare nel mondo qualcosa che non c'è ancora.
Quando lo stato non è «caricato», la riga sotto dice perché, nella lingua in cui stai giocando e senza identificatori che non hai scritto tu: quale file il gioco si rifiuta di eseguire, quale pacchetto manca, quale versione vuole. Sotto, che cosa ha fatto il contenuto del pacchetto: quante voci sono entrate, quante sono state rifiutate. Mostra i dettagli apre il resto, cioè gli id e la regola esatta che ogni record rifiutato ha infranto.
| Sulla schermata | Nel resoconto | Che cosa significa |
|---|---|---|
| Caricato | active | Caricabile, nessun ostacolo. |
| Non valido | invalid | Il manifesto porta file di script o eseguibili bloccati. |
| Richiede un altro mod | skipped_missing_dependency | Una dipendenza dichiarata è assente o disattivata. |
| Richiede un altro mod | skipped_incompatible_dependency | Una dipendenza dichiarata è fuori dal suo intervallo. |
| Ignorato | incompatible | Il mod punta a una build del gioco più recente. |
| In conflitto | conflict | Due mod caricabili puntano allo stesso id di sovrascrittura (restano caricabili; vince il load_order, entrambi segnalati). |
| Disattivato | disabled | L'hai spento, oppure non l'hai mai acceso. I pacchetti sono a scelta: metterne uno nella cartella lo installa e non lo accende. |
| Attivo — riavvia per caricare | — | L'hai acceso e nessuno l'ha ancora letto. Il suo contenuto non è nel gioco finché non riavvii. |
| Spento — riavvia per scaricare | — | L'hai spento ed è ancora caricato. Il suo contenuto resta nel gioco finché non riavvii. |
Due righe condividono una parola di proposito: Richiede un altro mod è lo stesso problema per un giocatore, sia che il pacchetto che serve manchi sia che sia della versione sbagliata, e la riga sotto dice quale dei due. E quando due pacchetti reclamano lo stesso record, quello con load_order più alto scrive per ultimo e vince — ma una presa di possesso che nessuno ha dichiarato è un errore, non una nota. Entrambe le righe vengono segnalate e la riga di chi perde nomina chi vince, e il vincitore viene comunque calcolato invece di essere lasciato al caso: un rifiuto non deve essere anche un lancio di moneta. Quando due mod vogliono la stessa cosa spiega come dichiararne una di proposito.
«Caricato» non vuol ancora dire che lo puoi vedere nel mondo. Per quello, leggi i conteggi sotto la riga, e Ora trovalo nel gioco dice dove spunta ogni tipo di cosa.
I conteggi tornano sempre. Letti è applicati, più rifiutati, più sostituiti da un altro mod, più in attesa delle proprie condizioni — e gli ultimi due sono nominati invece di restare un buco. Un record che un altro pacchetto scrive per ultimo non è rifiutato, perché non ha niente che non va, e non è nemmeno applicato, perché non è quello che il gioco ha tenuto. È la differenza fra leggere una riga e passare una serata a cercare un bug in un file che non ne ha. Mostra i dettagli dice quale record, e quale pacchetto ce l'ha adesso.
Un numero sta accanto a quella somma invece che dentro: i file che nessuno ha letto. Un file la cui famiglia non è in content_types non è mai stato aperto, quindi non c'è nessun record da mettere in conto e non c'è modo di sapere quanti ce ne siano dentro. È un conteggio di file, non di record, ed è esattamente per questo che non può essere un sesto termine: la somma parte da letti, e questi non sono mai stati letti.
Prima di chiedere aiuto a qualcuno
Apri Mod e premi Copia il resoconto. Incolla tutto quanto nel tuo messaggio, poi di' che cosa ti aspettavi.
Un testo semplice, pronto per un forum, un messaggio su Discord o una segnalazione di bug: la build su cui sei, la cartella dei mod, ogni pacchetto con la sua versione, il suo load order e il suo stato, la ragione dietro ogni rifiuto, i conteggi per ogni tipo di contenuto, e quale pacchetto ha vinto ogni scontro.
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 rejectedNove volte su dieci la risposta è nel blocco e nessuno deve farti prima una sola domanda. Non legge niente al di fuori della cartella dei mod, non cambia niente e non contiene informazioni personali.
È in inglese anche quando stai giocando in un'altra lingua. È voluto: chi ti aiuta potrebbe non leggere la tua, e ogni fatto che contiene — id, versioni, conteggi — è comunque uguale in tutte le lingue.
Toglierne uno
Cancella la sua cartella e riavvia. La disinstallazione è tutta qui.
Niente di tuo viene cancellato insieme a lui. Un salvataggio conserva gli id che non riesce più a risolvere, li segnala, e restituisce le cose se il pacchetto viene reinstallato. Una sessione che non riesce a capire un salvataggio non lo sovrascrive nemmeno: il file originale resta esattamente com'era, ed è la differenza fra un pomeriggio perso e una partita persa. Salvataggi è il resoconto completo.
Se il gioco non parte più dopo che hai installato qualcosa, la via d'uscita non ha bisogno del gioco. Apri la cartella dei mod e sposta fuori l'ultima cosa che hai aggiunto. I pacchetti si leggono solo da quella cartella, quindi una cartella che non c'è è un pacchetto che non si può caricare, e l'avvio successivo è quello di prima. Non ti servono un menu, una console o un avvio funzionante per farlo.
Anche il gioco ci prova da solo — Se il gioco non parte è un numero limitato di tentativi e poi una via di rientro senza nessun pacchetto caricato — ma quella è la cintura, e spostare la cartella sono le bretelle.
Comincia da qui
Che cosa puoi costruire oggi
Ora, senza chiedere a nessuno: merci e mercanti che le vendono, oggetti, persone e dove si trovano, edifici e servizi al loro interno, luoghi sulla mappa, conversazioni, scene, piani delle quest, mappe disegnate in Tiled, immagini e colori, e tutte le loro parole in sette lingue. I file audio e dei font vengono controllati e letti, ma le loro superfici di pacchetto non li consumano ancora; la tabella dello stato lo dice chiaramente invece di chiamarli pronti. Tutte le famiglie sono l'elenco misurato, e lo stato deriva dalla build, non da una promessa.
Non ancora, e Cosa non puoi ancora fare spiega ogni caso: la famiglia quests, l'audio dei pacchetti, i font dei pacchetti, le total conversion impacchettate e un pacchetto che sia una funzionalità invece di contenuto.
Mai, per scelta di progetto: codice. Niente script, niente scene, niente file di risorsa, niente che il gioco debba eseguire. È questo che rende sicuro scaricare il mod di uno sconosciuto, e non è una fase che il progetto sta attraversando. Che cosa un mod non potrà mai fare.
Tempo per la prima cosa che puoi vedere nel gioco: circa dieci minuti, per lo più spesi a trovare la cartella. Un mod in dieci minuti è tutto il percorso, e la spada che c'è alla fine è vera.
Che cosa non puoi ancora fare, e perché
È scritto qui, vicino all'inizio, invece di lasciarlo scoprire alla fine. Queste sono le cose che la build valida senza inserirle per ora in una superficie di pacchetto rivolta al giocatore, oltre a ciò che non è affatto contenuto di un pacchetto.
| Che cosa | Perché no | Cambierà |
|---|---|---|
La famiglia quests | È riconosciuta e controllata e dietro non c'è nessun mappatore a runtime, quindi un pacchetto che la prende di mira supera ogni controllo e non installa niente. Scrivi invece Missioni tue: quest_plans è una famiglia viva ed è quella che il gioco legge davvero. | Sì, quando il mappatore sarà pubblico |
| Audio del pacchetto | I descrittori e i file audio vengono validati e letti, ma nessuna superficie in esecuzione consuma ancora un segnale audio del pacchetto; un mod può quindi contenere suoni che restano muti. | Sì |
| Font del pacchetto | I descrittori dei font e la copertura delle lingue vengono validati, ma nessun tema in esecuzione consuma ancora un font del pacchetto. | Sì |
| Una conversione totale impacchettata | La build capisce il manifesto e porta con sé il fixture Ashen Reach. Quello che manca è il flusso di lavoro impacchettato per chi crea, non il meccanismo. Una conversione totale. | Sì |
| Un pacchetto che sia una funzionalità | Deciso per intero e nessuna famiglia lo porta, quindi nessun manifesto può chiederlo. Ogni famiglia lo elenca fra le cose che non hanno ancora una cartella. | Sì |
| Qualunque cosa venga eseguita | Un livello di scripting non arriverà. Il manifesto porta un tipo di pacchetto che spedisce comportamento, l'unica cosa che potrebbe autorizzarne l'esecuzione lo rifiuta, dietro non c'è nessuna sandbox, e un pacchetto che lo dichiara viene rifiutato oggi. Che cosa un mod non potrà mai fare. | No |
Una meccanica che il gioco non ha mai avuto è la quarta riga con un altro cappello. Una spada che colpisce più forte è un numero ed è tua; un'arma che spara un raggio ha bisogno delle regole del raggio, e le regole sono codice che qualcuno scrive e prova.
Che cos'è un mod
Una cartella di file di testo. Non scrivi codice. Scrivi elenchi di cose che vuoi nel gioco, e il gioco li legge quando parte.
| Parola | Che cosa significa |
|---|---|
| Pacchetto | Il tuo mod. Una cartella con sopra il tuo nome. |
| Manifesto | mod.json, in cima a quella cartella. Chi sei, che cosa porti. |
| Record | Una cosa che aggiungi. Una spada è un record. |
| Famiglia | Un tipo di cosa. Spade, elmi e pane sono tutti items. Ogni famiglia ha la sua cartella. |
| Id | your_package:the_thing — per esempio northern_reach:frost_blade. |
L'unica regola da cui discende tutto il resto: puoi aggiungere e cambiare dati. Non puoi far eseguire codice al gioco. È questo che rende sicuro scaricare un mod: il peggio che il mod di uno sconosciuto può fare è metterti in gioco una spada sciocca.
34 famiglie sono pronte all'uso oggi, tra cui items, buildings, pois, npc_definitions, vendor_inventories, quest_plans, caravans e perks. Tutte le famiglie sono la tabella completa con ciò che fa ciascuna; Le famiglie, una per una mostra per ognuna i campi e un record da copiare.
Scegli la tua strada
Questo è l'indice di tutta la guida — dove ogni argomento è scritto, che tu lo stia costruendo oggi o no. In cima alla Parte 3 c'è un secondo indice, più corto: quello è i sei tutorial, nell'ordine in cui si appoggiano l'uno sull'altro. Se sei qui per fare qualcosa e non per cercare qualcosa, vai dritto lì.
| Vuoi | Vai a |
|---|---|
| Costruire qualcosa dall'inizio alla fine | Parti da quello che vuoi fare — i sei tutorial, un pacchetto solo |
| Far caricare un file in dieci minuti | Un mod in dieci minuti |
| Cercare i campi di una famiglia e un esempio | Le famiglie, una per una |
| Vedere tutto quello che ti è permesso fare | Ogni famiglia |
| Cambiare qualcosa che il gioco porta già con sé | Cambiare quello che il gioco ha già |
| Aggiungere arte, suono, scritte o colore tuoi | Immagini, suono, scritte, colore |
| Disegnare un luogo in Tiled | Mappe tue |
| Scrivere una missione | Missioni tue |
| Capire perché non è comparso niente | Non è comparso niente |
| Cercare un codice d'errore | Ogni codice diagnostico |
| Sapere che cosa un mod non potrà mai fare | Che cosa un mod non potrà mai fare |
| Non rompere il salvataggio di qualcuno | Salvataggi |
| Metterlo dove la gente può prenderlo | Condividerlo |
Oppure per la cosa che hai in testa. Questa guida è disposta nell'ordine in cui il lavoro succede — manifesto, poi convalida, poi contenuto, poi resoconti — che è l'ordine che sceglierebbe chi il sistema lo conosce già. Chi non lo conosce sta pensando voglio aggiungere un mercante, e cerca la parola mercante:
| Stai aggiungendo | Le famiglie che lo fanno | Dove sono scritte |
|---|---|---|
| Commercio e merci | goods, vendor_inventories, caravans, recipes | Cose, commercio e i numeri dietro uno scontro |
| Cose che un giocatore porta con sé | items, combat_balance | Cose, commercio e i numeri dietro uno scontro |
| Persone | npc_definitions, mercenary_templates, noble_houses, relationships, perks, enemy_archetypes, enemy_variants, group_archetypes | Persone, casati e quello che sanno fare |
| Luoghi ed edifici | buildings, pois, maps, world_generation | Il mondo e i luoghi che contiene |
| Parole che un giocatore legge | locales, dialogue, scenes, lore, mr_lines, quest_plans, quest_metadata, progress | Storia, missioni e le parole che un giocatore legge |
| Come si vede e come suona | images, audio, fonts, themes, effects, presentation_bindings, screens | Come si vede e si sente tutto quanto |
| Comandi e difficoltà | input_bindings, settings, adaptive | Che cosa controlla il giocatore, e che cosa lo osserva |
Che cosa ti serve
| Il gioco | Necessario | Niente Godot, niente compilatore, nessun passaggio di build. |
| Un editor di testo che capisca il JSON | Necessario | VS Code, Sublime, Notepad++ — tutti gratuiti. Il Blocco note di Windows funziona e non ti aiuterà. |
| Un editor di pixel art | Solo per l'arte tua | Aseprite (~20 €), oppure gratuiti: LibreSprite, Piskel, Krita, GIMP. |
| Un editor audio | Solo per il suono tuo | Audacity. Effetti brevi dal niente: sfxr, ChipTone. |
| Tiled | Solo per le mappe tue | Gratuito. Esporta in .tmj. |
Un editor che colora il JSON ti mostra una virgola mancante mentre ci stai ancora guardando, invece di sentirti dire dopo dal gioco che il file era illeggibile.
Python e la console sono facoltativi. Il gioco è sufficiente: inserisci il pacchetto, riavvia e apri Mods, che indica ogni record rifiutato e il motivo. Il checkout per gli autori è pubblico. Chi vuole iterare più velocemente o automatizzare le pubblicazioni può clonare il checkout pubblico di Bonemark ed eseguire gli strumenti offline in Strumenti offline; ai giocatori che installano un pacchetto pubblicato non servono Python né Godot. Lo stesso checkout pubblico contiene il validator e le dichiarazioni del runtime, quindi le due sezioni descrivono una sola catena di strumenti. Gli strumenti usano le stesse dichiarazioni del gioco — gli schemi dei record e il confine di sicurezza hanno una sola fonte ciascuno — e danno quindi una risposta prima, mai diversa. Una console di debug è utile per ispezionare un pacchetto caricato, ma non serve per scriverne uno.
Creane uno
Parti da quello che vuoi fare
Tutto quello che sta sotto questa riga è disposto nell'ordine in cui succede il lavoro: manifesto, poi file, poi famiglie, poi resoconti. È l'ordine giusto per cercare qualcosa e quello sbagliato per cominciare, perché nessuno comincia da un manifesto. Si comincia da voglio un mercante.
Quindi: scegli la frase che assomiglia a quello che stai cercando di fare.
| Vuoi | Vai a | Quanto ci vuole |
|---|---|---|
| Aggiungere qualcosa da comprare e vendere | Una merce da vendere | 15 minuti |
| Aggiungere qualcosa che un giocatore porta con sé | Un oggetto da portare | 10 minuti, dopo quello sopra |
| Aggiungere una persona che lo vende | Un mercante che lo tiene | 30 minuti |
| Aggiungere una porta in un insediamento | Il servizio di un edificio | 20 minuti |
| Aggiungere un luogo sulla mappa del mondo | Un luogo sulla mappa | 20 minuti |
| Cambiare qualcosa che il gioco ha già | Cambiare quello che c'è già | 15 minuti |
| Disegnare una mappa, scrivere una missione, portare arte | Mappe tue, Missioni tue, Immagini, suono, scritte, colore | più a lungo, e tutte e tre sono famiglie vive |
Portare la famiglia quests, una conversione totale impacchettata, o un pacchetto che sia una funzionalità | Non ancora. Che cosa non puoi ancora fare, e perché dà la ragione di ciascuno e dice quali cambieranno. | — |
| Aggiungere una regola che il gioco non ha mai avuto | Qui non lo fa niente, e niente lo farà. Che cosa un mod non potrà mai fare dice perché, in un paragrafo. | — |
I sei tutorial sono un pacchetto solo, costruito un pezzo alla volta: una candela di cera d'api, il fascio che un giocatore porta con sé, la ceraiola che la vende, la porta della sua bottega, la fossa dietro la conceria da cui viene il sego, e infine una modifica alla candela che il gioco aveva già. Falli in ordine e finisci con un mod che qualcuno potrebbe scaricare. Prendine uno in mezzo e funziona da solo.
Dove sono i numeri del gioco
Ogni tutorial qui dà il prezzo a una cosa nuova confrontandola con qualcosa che il gioco vende già, perché un numero senza niente accanto è un'ipotesi, e un'ipotesi in un'economia che commercia fra città non resta dove l'hai messa.
Non puoi aprire i file del gioco. I suoi record sono risorse Godot dentro la build impacchettata — un formato diverso dal JSON che scrivi tu, con category = 1 dove il tuo file dice "MANUFACTURED". Non c'è nessuna cartella da cui copiare, e spacchettarne una non è un flusso di lavoro che qualcuno debba documentare.
Non ne hai bisogno. Il catalogo pubblica il contenuto del gioco, generato da quegli stessi record a ogni build: 270 oggetti con la loro categoria, il peso, il valore in monete e la dimensione della pila, 49 armi, 42 pezzi d'armatura, 37 luoghi. È il riferimento a cui questa guida si àncora, non può divergere dal gioco, e il nome del campo è stampato accanto a ogni riga.
Una dozzina di valori da conoscere prima di dare un prezzo a qualcosa:
| Il gioco vende già | Monete | E |
|---|---|---|
| Argilla, pietra, canne | 1 | il pavimento. Scavate o tagliate, senza lavoro dentro |
| Grano, legno | 2 | |
| Candela | 3 | una serata di luce |
| Lana, pesce, uva | 4 | |
| Pane | 6 | il cibo di un giorno |
| Sale, miele, corda | 8 | |
| Stoffa (pezza) | 10 | tessuta da 2 lana e 1 canne |
| Ferro raffinato, pesce salato | 12 | |
| Pepe nero | 14 | un'importazione, e si sente |
| Cuoio, formaggio | 15 | |
| Vino | 25 | |
| Armi a una mano | 50–300 | la fascia, non un valore unico |
| Armi a due mani | 150–600 | |
| Piastra pesante | 500–1500 | il tetto di tutta l'economia |
Se la tua cosa nuova costa più di un'armatura di piastre, qualcosa è andato storto e il gioco non te lo dirà: diventerà in silenzio il carico più redditizio del mondo e ogni carovana lo porterà.
Una merce da vendere
Avrai una merce che l'economia sa come prezzare, ancorata alla candela che il gioco vende già, pronta perché un mercante la tenga.
Schermata: non ancora scattata. Questo spazio resta vuoto finché non ce ne sarà una vera: un disegno di come potrebbe apparire sarebbe l'unica cosa non vera della pagina.
Leggi prima: Che cos'è un mod · Un mod in dieci minuti · Nomi e id
Copia da: la cartella chiamata chandlery, che è già nella tua cartella dei mod. Il gioco ce la mette la prima volta che parte, spenta, ed è il risultato finito di questi sei tutorial: ogni record qui sotto è lì dentro. È anche il pacchetto che la corsia di prova del repository fa girare contro il caricatore, quindi qui non c'è nessun record che il gioco rifiuterebbe. Accendila per vederla funzionare, oppure copia la cartella, rinominala e falla tua.
Dove vanno i file:
where the files go
mods
└ chandlery
├ mod.json
└ content
└ economy
└ goods
└ goods.jsonParti dalla candela che il gioco ha già. Si chiama candle, costa 3, pesa 0,5, è MANUFACTURED e PRESERVED, e la fa l'apotecario. La tua è lo stesso oggetto fatto di cera migliore, quindi conserva tutte quelle risposte e ne cambia due.
Prima 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
}Poi 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 | Perché questo valore |
|---|---|
id | Il nome del tuo pacchetto, due punti, poi una parola tua. Qualunque cosa senza il tuo spazio dei nomi davanti viene rifiutata, quindi non puoi prenderti l'id di qualcun altro per sbaglio. |
display_name | Quello che legge un giocatore. Nessun articolo — «Candela di cera d'api», mai «Una candela di cera d'api»: l'articolo lo fornisce la frase intorno, e quale articolo dipende dalla lingua. Parole che un giocatore legge. |
category | MANUFACTURED, perché qualcuno la fa. I cinque sono materia prima, manufatto, consumabile, munizione ed equipaggiamento, e quello che scegli decide quali edifici di produzione e quali carovane se ne interessano. |
decay_tier | PRESERVED — 90 giorni, come la candela del gioco. La cera si conserva; non si conserva per sempre. PERISHABLE è 7 giorni e ETERNAL non marcisce mai. |
base_price | 9. La candela semplice del gioco è 3 e un vasetto di miele è 8. La cera d'api viene dalle stesse arnie del miele e brucia senza l'odore del grasso fuso, quindi sta appena sopra il miele e circa il triplo della candela di sego. Non è un'importazione: il pepe nero è 14 e ha attraversato un mare. |
weight | 0,4, un filo sotto lo 0,5 della candela semplice. Il peso è quello che una carovana può portare, quindi una merce che non pesa niente e si vende cara è un bug che stai scrivendo di proposito. |
production_class | Quale mestiere la fa. chandler è quello che usa il pacchetto di riferimento. |
daily_consumption_class | Chi la consuma. household vuol dire che le città la consumano di continuo, ed è quello che tiene un mercante a rifornirsi. |
tags | Parole libere. Altri record e i tuoi file successivi possono cercarci dentro. |
Fatto — ora trovala nel gioco. Riavvia, apri Mod, e la riga sotto la tua dice 1 entry added. È tutto quello che fa una merce da sola: ha un prezzo, è commerciabile, e non sta sul bancone di nessuno, perché ancora nessuno la tiene. Non è un fallimento ed è la cosa che confonde tutti una volta. Prosegui con Un mercante che lo tiene.
Se non compare: Non è comparso niente ha le sei ragioni in ordine. La più comune di gran lunga è content_types — una famiglia che manca da quella riga vuol dire che la cartella non viene mai aperta, qualunque cosa contenga. Poi Prima di chiedere aiuto a qualcuno, che è un pulsante solo.
Un oggetto da portare
Avrai la cosa che un giocatore raccoglie, impila nello zaino e rivende, accoppiata alla merce che hai appena scritto.
Schermata: non ancora scattata.
Leggi prima: Una merce da vendere · Nomi e id
Copia da: chandlery/content/inventory/items/items.json nella tua cartella dei mod.
Dove vanno i file:
where the files go
mods
└ chandlery
├ mod.json
└ content
├ economy
│ └ goods
│ └ goods.json
└ inventory
└ items
└ items.jsonUna merce e un oggetto sono due metà della stessa cosa. La merce è il punto di vista dell'economia: che cosa produce una città, che cosa trasporta una carovana, quanto vale. L'oggetto è il punto di vista del giocatore: che cosa sta nello zaino, che cosa si impila, che cosa espone una bottega. Il grano ha una merce e nessun oggetto, perché nessuno si porta in giro un sacco di grano. Le candele hanno entrambi.
Aggiungi "items" a content_types in mod.json, poi scrivi 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 | Perché questo valore |
|---|---|
id | Un id suo, non quello della merce. Sono record diversi in famiglie diverse e niente li obbliga a coincidere: accoppiarli è compito tuo, e la riga del mercante qui sotto è dove l'accoppiamento si fa. |
category | MATERIAL, che è quello che è la candela del gioco. Non CONSUMABLE: non si mangia niente. |
rarity | COMMON. La rarità è quello che leggono le tabelle del bottino e le botteghe quando tirano; una cosa comune capita. |
weight | 0,4, come la merce. Quando i due non concordano, lo zaino del giocatore e la carovana non concordano sullo stesso oggetto. |
max_stack | 20, come il pane e come il fascio del pacchetto di riferimento. Venti è la pila ordinaria del gioco per le cose piccole che si portano addosso; 1 è per qualcosa di unico. |
base_value | 10 contro il 9 della merce. Un fascio porta un piccolo sovrapprezzo rispetto al prezzo sfuso — il fascio di sego del pacchetto di riferimento è 4 contro una merce da 3, e questa è la stessa forma un gradino sopra. |
sellable | Vero, altrimenti un mercante non può ricomprartelo. |
Fatto — ora trovalo nel gioco. Un oggetto che nessuno consegna è caricato e raggiungibile da niente. In una build di debug item chandlery:beeswax_candle_bundle te ne mette subito uno nello zaino, ed è la prova più rapida che si è caricato — ma quel comando non esiste nel gioco che la gente scarica, quindi è una scorciatoia per te e mai la risposta per un giocatore. La risposta vera è il tutorial successivo.
Se non compare: Non è comparso niente, poi Prima di chiedere aiuto a qualcuno.
Un mercante che lo tiene
Avrai una donna con un nome in piedi a Old Seat con un banco, scorte che si rifanno ogni due giorni, e le tue candele sul bancone.
Schermata: non ancora scattata.
Leggi prima: Un oggetto da portare · Ora trovalo nel gioco
Copia da: chandlery/content/narrative/npcs/npcs.json e chandlery/content/world/vendor_inventories/vendors.json.
Dove vanno i file:
where the files go
mods
└ chandlery
├ mod.json
└ content
├ economy
│ └ goods
├ inventory
│ └ items
├ narrative
│ └ npcs
│ └ npcs.json
└ world
└ vendor_inventories
└ vendors.jsonQuesto è quello in cui due famiglie devono mettersi d'accordo. La persona porta l'id del banco, il banco porta l'id della persona, e ogni riga del banco porta l'id di un oggetto. Tre id, e ognuno va scritto esattamente come l'hai scritto nell'altro file. È l'errore che costa una serata, e la schermata Mod lo nomina: una riga che punta a un id che nessuno fornisce viene elencata come richiede un altro mod che non è installato.
Aggiungi "npc_definitions" e "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 | Perché questo valore |
|---|---|
settlement_id | Usa un id di insediamento creato dagli autori. Gli id degli insediamenti sono creati dagli autori e stabili: Durnwall, Thorngate, Valdmere, Grentham e i dodici villaggi possono essere tutti nominati. Il seed cambia il terreno e i biomi intorno a loro, la penuria dell'anno e l'assetto politico, non l'id. |
is_vendor + vendor_inventory_id | Insieme trasformano una persona in una bottega. L'uno senza l'altro è una persona che non può vendere o un banco di cui non si occupa nessuno. |
price_multiplier | 1.0 — chiede quanto valgono le cose. Sopra 1 è un posto che sa che non hai alternative; i mercanti del gioco stanno a 1.0 se non c'è una ragione sulla mappa. |
buyback_rate | 0.35: paga circa un terzo del valore per quello che le vendi. È il numero che i giocatori sentono di più ed è quello che usa il banco del pacchetto di riferimento. |
daily_stock | 6. Quante ne ha quando il banco si rifornisce. Sei è la cifra del pacchetto di riferimento per una cosa da casa a buon mercato; uno è per qualcosa che una città vede due volte l'anno. |
restock_days | 2, quindi si rifornisce ogni due giorni — e non il giorno in cui installi il mod. È per questo che un mercante nuovo all'inizio sembra vuoto. In una build di debug day fa avanzare di un giorno. |
min_standing | 0: può comprare chiunque. Sopra zero sono scorte che tiene per le persone che le stanno simpatiche. |
kind | Su che tipo di bancone sta — misc per una merce da casa. Gli altri sono weapon, armor, shield, consumable e ammo. |
Fatto — ora trovalo nel gioco. Riavvia, viaggia fino a Old Seat, trova Hesta, apri la schermata di commercio. Se il banco è vuoto, non si è ancora rifornito: è restock_days, non un bug. La catena si può rompere in tre modi e tutti e tre stanno sulla schermata Mod: la merce che nessuno tiene, il banco che punta a un id di oggetto che non esiste, la persona che punta a un id di banco che non esiste.
Può anche parlare. Un dialogue_graph il cui speaker è il suo id le dà delle battute quando un giocatore le clicca sopra, e il tuo pacchetto non deve ridefinire niente che il gioco già possiede per ottenerle — vedi Conversazioni tue. Un file locales le dà tutto questo in sette lingue.
Se non compare: controlla prima i tre id l'uno contro l'altro, poi Non è comparso niente, poi Prima di chiedere aiuto a qualcuno.
Il servizio di un edificio
Avrai una porta in un insediamento con la tua etichetta e il tuo colore sopra, che si apre su un interno che il gioco ha già.
Schermata: non ancora scattata.
Leggi prima: Un mercante che lo tiene · Che cosa un mod non potrà mai fare
Copia da: chandlery/content/world/buildings/buildings.json.
Dove vanno i file:
where the files go
mods
└ chandlery
└ content
└ world
└ buildings
└ buildings.jsonStai ricombinando, non costruendo. Un record buildings aggiunge un servizio nuovo con un'etichetta, un colore della porta e un ruolo di routine, e può riusare un interno che il gioco ha già nominandolo. Non può portare un interno. Un interno è una scena, una scena è codice, e un pacchetto che nomina un percorso res:// o un .tscn viene rifiutato prima ancora che questo record venga letto. Non è un buco in attesa di essere riempito: è la linea che rende sicuro installare il mod di uno sconosciuto.
a buildings record
[
{
"id": "chandlery:chandlery",
"label": "Chandlery",
"role": "merchant",
"color": { "r": 0.44, "g": 0.38, "b": 0.24 },
"interior_service": "shop"
}
]| Campo | Perché questo valore |
|---|---|
label | Le parole sulla porta. Se la ometti, il gioco mette la maiuscola al tuo id, e si legge come un id. |
role | Che cosa fanno tutto il giorno le persone dentro — merchant mette dietro la porta la routine di un bottegaio. Il ruolo è il vocabolario del gioco, non il tuo: uno sconosciuto si carica e si comporta come niente in particolare. |
color | Marrone cera d'api, 0.44 / 0.38 / 0.24. Ogni canale va da 0 a 1, e funziona anche una stringa esadecimale HTML. Scegli qualcosa che si legga alla dimensione con cui è disegnata una porta — Arte che sta bene. |
interior_service | shop — l'interno che il gioco disegna già per una bottega. Il trucco è tutto qui: ottieni una stanza vera e arredata senza portarne una. |
Fatto — ora trovalo nel gioco. Riavvia ed entra in un insediamento che ha il tuo servizio. Un record senza settlement è caricato e collocato da nessuna parte, il che è identico a un record fallito: la schermata Mod dirà 1 entry added e tu non troverai niente. Leggi la riga prima di cercare la porta.
Se non compare: Non è comparso niente · Prima di chiedere aiuto a qualcuno.
Un luogo sulla mappa
Avrai un punto sulla mappa del mondo in cui un giocatore può imbattersi, con una descrizione sua e un suo effetto sull'umore della compagnia.
Schermata: non ancora scattata.
Leggi prima: Il servizio di un edificio · Ora trovalo nel gioco
Copia da: chandlery/content/world/pois/pois.json.
Dove vanno i file:
where the files go
mods
└ chandlery
└ content
└ world
└ pois
└ pois.jsonLe coordinate sono assolute e il mondo viene generato attorno a luoghi creati dagli autori. La mappa misura 61 440 × 34 560 pixel del mondo e Old Seat è esattamente al centro, (30720, 17280), in ogni partita. Le città e i villaggi creati dagli autori conservano nomi e posizioni. Il seed cambia il terreno e i biomi intorno a loro, la penuria dell'anno, l'assetto politico e le strade che vale la pena percorrere. Un punto resta quindi reale e stabile; ciò che gli sta accanto cambia a ogni partita. Due modi onesti di usarla: ancora un luogo d'interesse vicino a un insediamento creato dagli autori, così un giocatore ci passerà; oppure scegli il vuoto, perché una fossa di rendering che nessuno visita da anni deve essere da nessuna parte in particolare.
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 | Perché questo valore |
|---|---|
kind | RUINS — quello che disegna la mappa e quello che il gioco crede che sia. |
world_position | (5400, 3000), molto a nord-ovest del centro: vuoto deliberato, il secondo dei due usi onesti di sopra. Spostalo entro qualche migliaio di pixel da (30720, 17280) e diventa un posto che i giocatori trovano davvero. |
discovery_radius | 2.0. Quanto vicino deve passare la compagnia. Abbastanza grande da farlo trovare lungo una strada, abbastanza piccolo da non annunciarlo da un capo all'altro di una provincia. |
morale_modifier | −1. È una fossa di grasso fuso. Il numero è piccolo di proposito: un luogo è un luogo, non un evento, e −1 è un umore, non una punizione. |
awareness_modifier | 0.0 — non aiuta a vedere. Lascia un numero a zero invece di togliere il campo, quando lo zero è una decisione. |
one_time_loot | Falso: non c'è niente da prendere, quindi niente da prendere una volta sola. |
Fatto — ora trovalo nel gioco. Vacci. Non esiste nessun comando di teletrasporto, né in una build di debug né fuori, quindi scegli coordinate fin dove sei disposto a camminare mentre provi.
Se non compare: probabilmente sei fuori dal discovery_radius, oppure la posizione è in un punto in cui il seme della partita ha messo un oceano. Non è comparso niente.
Cambiare quello che c'è già
Avrai cambiato un record che il gioco portava con sé — e l'avrai dichiarato, così il cambiamento è visibile al giocatore e a ogni altro mod.
Schermata: non ancora scattata.
Leggi prima: Cambiare quello che il gioco ha già · Quando due mod vogliono la stessa cosa
Copia da: chandlery/content/economy/goods/goods.json, che nello stesso file aggiunge un record e ne corregge uno del gioco.
Dove vanno i file: in nessun posto nuovo. Una modifica a qualcosa che il gioco ha già vive nella stessa cartella di famiglia in cui vivono i tuoi record: è il file a dire quale record intende e che cosa gli sta facendo.
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 fileDue regole prima del file. Una modifica al record di qualcun altro va nominata in overrides dentro mod.json — un record che atterra su un id che non hai dichiarato viene rifiutato, così niente può riscrivere di nascosto qualcosa che il giocatore non ha accettato. E patch, che cambia un campo e lascia stare il resto, richiede "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" }
]
}
]| Scelta | Perché |
|---|---|
patch, non replace | replace non eredita niente: dovresti riscrivere il peso della candela, il suo grado di decadimento, l'oggetto collegato e la classe di produzione, e il giorno in cui il gioco desse alle candele un campo nuovo, la tua copia sarebbe l'unica candela al mondo senza. |
| 3 → 4 | Una moneta, e la ragione è il mod stesso: il tuo è una città che fonde la cera come si deve, quindi qui la candela ordinaria vale un po' di più. Passare da 3 a 30 non sarebbe una modifica a una candela, sarebbe una modifica alla priorità di carico di ogni carovana. |
append_unique su tags | L'unica operazione che due mod possono fare entrambi senza un conflitto. Se accodano tutti e due la stessa etichetta non è uno scontro e non la raddoppia. |
| Nominare un campo, mai una posizione | tags.0 viene rifiutato. La terza etichetta di oggi è la seconda etichetta dopo che si carica il pacchetto di qualcun altro. |
Fatto — ora trovalo nel gioco. La schermata Mod nomina il record di cui ti sei impossessato. Lo fa anche la schermata dell'altro autore, se c'è: quando due pacchetti scrivono lo stesso id, la riga di chi perde adesso dice replaced: candle — 'chandlery' writes it last, invece di mostrare in silenzio una voce in meno di quelle che aveva scritto. Chi ha il load_order più alto scrive per ultimo e vince.
Vincere non è la stessa cosa che avere il permesso. Due pacchetti che si impossessano di un record senza che nessuno dei due nomini l'altro in supersedes vengono segnalati come undeclared_collision e la composizione non è a posto: il validatore offline dice la stessa cosa e rifiuta:
typed into the debug console
ERROR: conflict on goods:candle: ['early', 'late'] each supply the whole record
and none declares the others under `supersedes`Il vincitore viene comunque calcolato, perché un rifiuto non deve essere anche un lancio di moneta, ma due autori che lo volevano entrambi devono dirlo. Quando due mod vogliono la stessa cosa è quella conversazione.
Se non compare: la causa solita è overrides — l'id deve stare in quell'elenco, scritto esattamente, altrimenti il record viene rifiutato invece che applicato. Quando due mod vogliono la stessa cosa · Non è comparso niente.
Un mod in dieci minuti
1. Crea una cartella nella cartella dei mod, con il nome in minuscolo e trattini bassi: northern_reach. Tutto succede lì dentro.
2. Scrivi mod.json in cima:
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 deve coincidere con il nome della cartella. content_types elenca le famiglie che porti — una famiglia che manca da quella riga non viene mai letta, qualunque cosa ci sia nella cartella.
3. Crea le cartelle content/inventory/items e mettici dentro blades.json:
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
}
]Le parentesi quadre sono un elenco: aggiungi quante spade vuoi, separate da virgole. Ogni file .json in una cartella di famiglia viene letto, quindi dividili come preferisci.
240 non è un numero scelto per fare colpo. In questo gioco le armi a una mano vanno da 50 a 300, quindi una lama di brina a 240 è una spada cara e non una spada leggendaria, e un giocatore se la può permettere più o meno quando potrebbe permettersi quelle buone che il fabbro vende già. Dove sono i numeri del gioco è la tabella da guardare prima di scegliere qualunque numero; un prezzo senza niente accanto è un'ipotesi, e in un'economia che commercia fra città un'ipotesi non resta dove l'hai messa.
4. Avvia il gioco e apri Mod dal menu principale. Il tuo pacchetto riceve esattamente uno stato, e Si è caricato? li ha tutti e sei.
5. Leggi la riga sotto per sapere che cosa è stato letto, applicato e rifiutato, con la ragione di ogni rifiuto. Mostra i dettagli ha gli id.
6. La tua spada è nel gioco. Tutto quello che viene dopo è altro dello stesso.
Ora trovalo nel gioco
Il resoconto dice applied. Vuol dire che il record è caricato, e non è la stessa cosa che poterci camminare davanti. È qui che ogni guida si ferma e ogni autore comincia a tirare a indovinare.
| Che cosa hai aggiunto | Dove spunta | L'inghippo |
|---|---|---|
goods | Su un mercante, appena una riga di vendor_inventories la chiede. Una merce che nessuno tiene è caricata, prezzata, commerciabile da qualunque cosa la nomini, e su nessun bancone da nessuna parte. | Aggiungere la merce è metà del lavoro. L'altra metà è la riga. |
vendor_inventories | Il mercante nominato in npc_id. Ogni riga porta il proprio daily_stock e il proprio restock_days, quindi una riga con restock_days: 2 si rifornisce ogni due giorni e non il giorno in cui l'hai aggiunta. | Usa day nella console per saltare un giorno invece di aspettarlo. |
items | Ovunque qualcosa te ne consegni uno: una riga di mercante, una tabella del bottino, la ricompensa di una missione. Un oggetto che niente concede esiste ed è raggiungibile solo con item <id> nella console. | item northern_reach:frost_blade te lo mette subito nello zaino, ed è il modo più rapido per vedere che si è caricato. |
npc_definitions | L'insediamento indicato in settlement_id, nel posto indicato da location_morning / location_afternoon / location_evening. | Leggi il paragrafo qui sotto su settlement_id prima di scriverne uno. |
buildings | L'insediamento indicato in settlement, disegnato con il role e il color che gli hai dato. interior_service è quello che un giocatore trova quando entra. | Un edificio senza settlement è caricato e collocato da nessuna parte. |
pois | Sulla mappa del mondo alla world_position, scopribile entro il discovery_radius. | Leggi il paragrafo sulle coordinate qui sotto. È quello che frega tutti. |
settlement_id indica un luogo creato dagli autori. Gli id degli insediamenti sono creati dagli autori e stabili: Durnwall, Thorngate, Valdmere, Grentham e i dodici villaggi possono essere tutti nominati. Il seed cambia il terreno e i biomi intorno a loro, la penuria dell'anno e l'assetto politico, non l'id. Se vuoi che una persona incontri sicuramente il giocatore, usa un id di insediamento creato dagli autori e mantieni il nome nei dati locali del tuo pacchetto.
Le coordinate sono assolute e il mondo viene generato attorno a luoghi creati dagli autori. La mappa misura 61 440 × 34 560 pixel del mondo e Old Seat è esattamente al centro, (30720, 17280), in ogni partita. Le città e i villaggi creati dagli autori conservano nomi e posizioni. Il seed cambia il terreno e i biomi intorno a loro, la penuria dell'anno, l'assetto politico e le strade che vale la pena percorrere. Perciò una world_position di (6000, 2200) è un punto reale e stabile nel lontano nord-ovest della mappa, mentre ciò che gli sta vicino cambia a ogni partita: può essere una strada, una foresta o il nulla. Due modi onesti di usarla:
- Ancora al centro. Un punto d'interesse a qualche migliaio di pixel da (30720, 17280) è vicino a Old Seat in ogni partita, quindi è un posto che un giocatore troverà.
- Intendi il vuoto. Una rovina davanti a cui nessuno passa da cent'anni deve stare in un posto qualunque. Le coordinate assolute sono esattamente giuste per questo, e sarà il seme a decidere che vicini avrà.
I comandi di console che fanno risparmiare più tempo. day [n] e hour [n] fanno avanzare il tempo, ed è così che vedi un rifornimento senza viverlo. item <id> [count] e gold <amount> ti mettono le cose in mano. flag, quest_start e faction_rep muovono lo stato che una condizione potrebbe stare aspettando. Non c'è nessun comando di teletrasporto: per raggiungere un posto, viaggiaci.
mod.json, campo per campo
| Campo | Che cosa fa |
|---|---|
id | Nell'esempio qui sopra. Il nome del tuo pacchetto. Deve coincidere esattamente con la cartella, ed è la parola prima dei due punti in ogni id che scrivi. |
name | Nell'esempio qui sopra. Quello che vede un giocatore. Qui maiuscole e spazi vanno bene. |
version | Nell'esempio qui sopra. La scegli tu. Alzala ogni volta che cambi qualcosa. |
game_version | Nell'esempio qui sopra. La build per cui l'hai fatto. |
content_types | Nell'esempio qui sopra. Le famiglie che porti. Una famiglia che manca da questo elenco non viene mai letta, qualunque cosa ci sia nella cartella. |
dependencies | Nell'esempio qui sopra. I pacchetti di cui il tuo ha bisogno. Un nome, oppure un oggetto con optional: true. |
load_order | Nell'esempio qui sopra. Chi va per primo quando due pacchetti toccano la stessa cosa. Il più basso si carica prima. |
overrides | Nell'esempio qui sopra. Gli id del gioco base che intendi cambiare. Un id, oppure un file.json:id quando intendi la copia che ne fa un file preciso. |
canon_safe | Nell'esempio qui sopra. Se il tuo mod stia dentro la storia del gioco. Questo sei tu che lo dici ai giocatori, non il gioco che decide. |
roots | La cartella di una famiglia, quando la vuoi da un'altra parte rispetto alla predefinita in Le famiglie, una per una. Resta dentro il tuo pacchetto. |
manifest_version | Quale forma di manifesto stai scrivendo. Le operazioni di Cambiare quello che il gioco ha già richiedono la 2. Questa build legge fino alla 2. |
type | Che tipo di pacchetto è. Il quarto valore è quello che spedisce comportamento invece che dati, e l'unica cosa in questa build che possa dire sì all'esecuzione di comportamento dice no, quindi un pacchetto che lo dichiara viene rifiutato. Sta nell'elenco perché la forma è decisa, non perché la porta sia aperta; Che cosa un mod non potrà mai fare è la lettura onesta. Uno fra content, overhaul, total_conversion, feature_extension. |
capabilities | Che cosa un pacchetto chiederebbe all'ospite, se il livello superiore si aprisse mai. Un campo sconosciuto qui fallisce chiudendo, invece di essere ignorato. |
trust_tier | Non fidato, che è quello che un mod scaricato da un giocatore è e resta. È un ospite a nominare l'altro; niente di quello che un pacchetto scrive qui lo promuove. Uno fra untrusted, trusted. |
supersedes | I pacchetti che questo intende scavalcare. Un campo reclamato così smette di essere segnalato come scontro. Anche qui un campo sconosciuto fallisce chiudendo. |
fallback_policy | Su che cosa ripiega un pacchetto quando manca qualcosa che scavalca. Uno fra vanilla, none. |
campaign | La campagna che una conversione possiede. |
campaign_package | Dichiara che questo pacchetto è una campagna, con id, nome e versione propri. Un pacchetto che lo porta viene letto solo mentre la sua campagna è quella in corso, e un giocatore lo sceglie nella schermata Mod prima di una partita nuova. Una conversione totale. |
Una dipendenza può essere un oggetto invece di un nome: {"id": "some_mod", "version": "", "optional": true}.
Un valore che nomina un altro pacchetto è un riferimento fra mod, e il riferimento deve essere una dipendenza dichiarata. Se quella dipendenza è facoltativa, dài al campo un fallback, altrimenti il record viene saltato quando la dipendenza è assente:
a goods record
[
{
"op": "add",
"id": "northern_reach:alloy",
"display_name": "Alloy",
"linked_item_id": "absent_helper:ore",
"fallback": { "linked_item_id": "iron_ore" }
}
]Dove va ciascun file
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 questNomi e id
Un id è lettere minuscole, cifre e trattini bassi, e nient'altro. frost_blade, non Frost Blade, non frost-blade e non frost.blade. Non porta nemmeno un separatore suo, perché un separatore dentro un id è la cartella che trapela nel nome: sposta il file e l'id non concorda più con il disco. I : qui sopra sono l'unica eccezione, ed entrambe le metà rispettano la regola.
La parte prima dei due punti è l'id del tuo pacchetto. È così che due mod possono aggiungere entrambi una Frost Blade senza scontrarsi.
Parole che un giocatore legge
Il testo scritto dentro un record è testo in una sola lingua. Punta invece a una chiave:
a locale CSV
northern_reach.item.frost_blade.name
northern_reach.item.frost_blade.descriptionLe chiavi sono minuscole, unite da punti, con lo spazio dei nomi come gli id. Porta le parole nella famiglia locales — un .csv sotto content/locale con una colonna key e una colonna per lingua. Le famiglie, una per una ha la forma esatta.
Scrivi accanto alla chiave anche il display_name semplice. Un record che ha solo una frase va riscritto a mano il giorno in cui lo traduci, e per allora ce ne saranno quattrocento.
I due modi di sbagliare questa cosa falliscono in modi molto diversi, e solo uno dei due te lo dice. Una chiave a cui non risponde niente compare come la chiave stessa — northern_reach.item.frost_blade.name, sullo schermo, deliberatamente brutta perché qualcuno la sistemi, e contata come un buco. Un record che porta solo testo e nessuna chiave non compare mai: funziona, nella tua lingua, per ogni giocatore in ogni lingua. Niente viene rifiutato e niente manca, quindi niente lo segnala, e un giocatore che legge in portoghese legge in silenzio il tuo italiano. Il primo errore lo trovi tu. Il secondo trova i tuoi lettori.
Tradurre un mod, ed essere tradotti
Il gioco esce in sette lingue, quindi un pacchetto con l'inglese cotto dentro i record si legge come inglese per sei settimi di chi lo installa. Questo è quello che costa evitarlo, cioè quasi niente se lo fai il primo giorno e una riscrittura se lo fai al quattrocentesimo.
Le lingue che ci sono
Sette, e questa tabella è letta dalla build invece che scritta a mano qui, così una lingua che arriva o se ne va la muove lo stesso giorno:
| Scrivi questo | Lingua | Intestazione di colonna | |
|---|---|---|---|
en | English | en | la lingua di partenza |
it | Italiano | it | |
fr | Français | fr | |
de | Deutsch | de | |
es | Español | es | |
pt-BR | Português (Brasil) | pt_BR | |
zh-Hans | 简体中文 | zh_Hans |
Due dei codici hanno una seconda grafia in circolazione — pt-BR è quella che usano una vetrina digitale e questa pagina, pt_BR è quella a cui si uniforma il motore — e in un'intestazione di colonna sono accettate entrambe. Scrivi quella che hai copiato.
Portare parole in più di una lingua
Un CSV sotto content/locale, con key per prima e una colonna per lingua:
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| Regola | Perché |
|---|---|
| Ogni chiave sta nel tuo spazio dei nomi | northern_reach:GOOD_FROST_SALT, con gli stessi due punti che usano gli id. Una chiave fuori da lì viene rifiutata a meno che overrides non la dichiari — altrimenti due pacchetti che scrivono entrambi GOOD_GRAIN verrebbero risolti dal load order, in silenzio. |
| Una colonna che nomina una lingua che il gioco non porta viene rifiutata | Non ignorata. Una colonna che il caricatore lasciasse cadere in silenzio non porterebbe niente e lo verresti a sapere da un giocatore. |
| Una cella vuota non è una risposta | Viene saltata invece che memorizzata, così una lingua a cui non sei ancora arrivato cade sul gradino successivo invece di restare vuota sullo schermo. |
| Mai tutti e due | Un record che porta un campo _key e una stringa alla lettera per la stessa cosa viene rifiutato. La chiave è la promessa; la stringa è quello che la chiave ha sostituito. |
Quando una chiave non ha risposta nella lingua del giocatore il gioco scende una scala fissa: la lingua del giocatore, poi la lingua in cui il tuo pacchetto dichiara di essere stato scritto, poi il catalogo del gioco, poi la chiave stessa. L'ultimo gradino è brutto di proposito: una chiave irrisolta deve sembrare sbagliata perché qualcuno la sistemi. Una conversione totale salta il catalogo del gioco, perché Old Seat che affiora in un mondo ambientato in un altro continente non è una piccola svista di traduzione, è il gioco base che traspare.
Scrivere testo che si possa tradurre
- Niente frasi costruite a pezzi. L'ordine delle parole non è lo stesso in tutte le lingue, quindi un nome montato a runtime da una colonna di aggettivi e una di sostantivi produce Oro Cervo in italiano. Una voce scritta per ogni lingua, completa.
- Il nome di una persona non si traduce mai e non si flette mai. Aldric è Aldric in tutte le lingue. Il che vuol dire anche che una chiave non deve mettere un nome in posizione obliqua —
"of {name}","{name}'s"— perché parecchie lingue declinano i nomi propri e il gioco no. - Non c'è nessun limite di caratteri, e non è la stessa cosa che non avere limiti. Nessun campo conta i caratteri; quello che finisce è lo spazio sullo schermo. Il tedesco è circa un terzo più lungo dell'inglese ed è la lingua che rompe i pulsanti; il cinese è molto più corto e non lo fa quasi mai. Se provi una sola traduzione, prova il tedesco, e dài a un'etichetta la formulazione più corta che sia ancora quella giusta.
Qualcuno che traduce il tuo pacchetto
Aggiunge una colonna e ti rimanda il file. Il flusso di lavoro è tutto qui, ed è il motivo per cui il formato è CSV invece di qualcosa di più amichevole per un programmatore: un traduttore può aprirlo in un foglio di calcolo, e i suoi strumenti lo leggono già.
Due cose fanno la differenza fra un pacchetto che viene tradotto e uno che no. Tieni le chiavi stabili — una chiave rinominata è una traduzione persa, e il traduttore lo scopre quando lo scopre un giocatore. E di' a che cosa serve una riga: una chiave chiamata NR_MSG_01 riceve un'ipotesi, mentre northern_reach:VENDOR_HERB_GREETING riceve il saluto di una venditrice di erbe.
Se sei tu a tradurre il pacchetto di qualcun altro, ti legano le stesse regole: le colonne sono le lingue che il gioco porta, le chiavi sono le sue e non le tue, e un nome resta un nome.
Cambiare quello che il gioco ha già
| Vuoi | Operazione | Che cosa ti serve |
|---|---|---|
| Aggiungere qualcosa di nuovo | add | Un id tuo con il tuo spazio dei nomi. Nient'altro. |
| Riscrivere uno dei record del gioco | replace | L'id del record elencato in overrides. Un record completo: non eredita niente. |
| Cambiare un campo e lasciare stare il resto | patch | overrides, più "manifest_version": 2 in mod.json. |
| Ritirare un record | remove | overrides, e una famiglia che lo accetta. Vedi Togliere qualcosa. |
part of mod.json
"overrides": ["iron_sword"]overrides è una promessa. Un record che atterra su un id che non hai dichiarato viene rifiutato, quindi non puoi mai cambiare in silenzio qualcosa di cui un giocatore non sapeva niente.
a goods record
[
{
"op": "patch",
"id": "iron_ore",
"changes": [
{ "op": "set", "field": "base_price", "value": 14 }
]
}
]| Operazione | Che cosa fa | Richiede | Rifiuta |
|---|---|---|---|
add | Fornire un record nuovo e completo sotto il tuo spazio dei nomi. | id con spazio dei nomi | un id che esiste già, che venga dal gioco base o da un altro mod |
replace | Fornire un record completo per un id che esiste già, avendolo dichiarato. | sovrascrittura dichiarata, record completo | un id assente dal registro, e un id che il manifesto non elenca sotto overrides |
patch | Cambiare campi nominati di un record esistente e lasciare stare il resto. | sovrascrittura dichiarata, modifiche | un id assente dal registro, un campo che la famiglia non permette, e qualunque forma di modifica fuori da patch_operations |
remove | Ritirare un record esistente e lasciare una lapide al suo posto. | sovrascrittura dichiarata, famiglia rimovibile | un id assente dal registro, e qualunque famiglia non segnata come rimovibile qui sotto |
Una patch nomina le sue modifiche una alla volta:
- set — Scrive
valueinfield, qualunque cosa ci fosse prima. Si scrive confieldevalue. - unset — Toglie
fielddal record, così chi legge vede il valore predefinito della famiglia. Si scrive confield. - append_unique — Aggiunge
valueall'elenco infieldse non c'è già. Si scrive confieldevalue. - remove_value — Toglie ogni occorrenza di
valuedall'elenco infield. Si scrive confieldevalue.
- Nomina un campo per percorso, mai per posizione.
tags.0viene rifiutato. La terza etichetta di oggi è la seconda etichetta dopo che si carica il mod di qualcun altro. - Un percorso è fino a quattro nomi minuscoli uniti da punti. Qualunque cosa contenga un operatore viene rifiutata.
append_uniqueè quella che due mod possono condividere. Se accodano tutti e due la stessa etichetta non è un conflitto e non la raddoppia.
Solo a volte
Un record può dire quando vale. Aggiungi un when accanto all'op, in un pacchetto 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" } }
}Non c'è nessun operatore e niente da calcolare. Tutto quello che una condizione può dire sta in queste due tabelle.
| Chiedi di | Deciso | Prove | Valori |
|---|---|---|---|
packages | al caricamento | all_of, none_of | id di mod caricati accanto al tuo |
campaign | al caricamento | is, any_of, not_any_of | la campagna da cui è partita la partita |
locale | al caricamento | is, any_of, not_any_of | la lingua in cui si sta giocando |
season | mentre si gioca | is, any_of, not_any_of | spring, summer, autumn, winter |
weather | mentre si gioca | is, any_of, not_any_of | un id di tempo atmosferico che il gioco ha tirato |
day_phase | mentre si gioca | is, any_of, not_any_of | dawn, day, dusk, night |
day | mentre si gioca | at_least, at_most | quanti giorni è durata la partita |
| Prova | Prende | Vera quando |
|---|---|---|
is | un nome | la risposta è esattamente quella |
any_of | un elenco | la risposta è uno di quelli |
not_any_of | un elenco | la risposta non è nessuno di quelli |
at_least | un numero | la risposta è quella o più alta |
at_most | un numero | la risposta è quella o più bassa |
all_of | un elenco | ci sono tutti |
none_of | un elenco | non c'è nessuno |
Al massimo quattro soggetti in un when, due prove per soggetto. Due prove sullo stesso soggetto sono un intervallo: { "day": { "at_least": 10, "at_most": 30 } }.
Quale famiglia prende che cosa. Ogni famiglia prende i tre decisi al caricamento. Solo presentation_bindings ed effects prendono i quattro che si muovono mentre si gioca, perché solo quei due vengono ricostruiti quando il mondo cambia. Nominare season altrove viene rifiutato, e il messaggio dice quali soggetti quella famiglia prende davvero.
La ragione sono i salvataggi. Un record che decide un oggetto, una persona o una missione deve essere lo stesso record al caricamento successivo, e una condizione che si muove è esattamente quello che glielo impedisce.
Un aspetto stagionale va sul collegamento, non sull'immagine. Porta l'immagine una volta sola, poi due record presentation_bindings per lei: uno con un when, uno senza. images, audio e fonts rifiutano un when senza discutere.
Trattenuto non è rifiutato. Una condizione che non è soddisfatta trattiene il suo record e il resoconto di caricamento lo dice per nome:
what the game prints back
WITHHELD my_mod:snowy_cloak from my_mod: season is winter, and it is springUn pacchetto con cinquanta record stagionali è trattenuto per tre quarti in qualunque momento. È il pacchetto che funziona.
Se ogni associazione di presentazione condizionale viene negata, il report mostra comunque la famiglia come dichiarata e stampa bound=0 insieme a ciascuna riga WITHHELD; non riporta erroneamente il pacchetto come privo di superficie di presentazione. Se nessuna associazione incondizionata fornisce lo stesso slot, stampa anche NO_APPLICABLE kind/subject/slot con la condizione senza risposta, che significa "non si applica nulla in questo stato mondiale", non "il record non era valido". Testare la condizione nell'host o nella corsia di runtime con lo stato mondiale corrispondente prima di presumere che l'associazione sia stata rifiutata.
Due versioni della stessa cosa. Porta due record add con lo stesso id e condizioni diverse. Quello la cui condizione regge è quello che si carica. Se reggono entrambe, il secondo viene rifiutato come duplicato — ed è così che condizioni sovrapposte vengono segnalate invece di essere risolte dall'ordine dei file.
Togliere qualcosa
remove vuol dire fuori produzione, non fuori dall'esistenza. Il record continua a risolversi ed è marcato: da lui non viene più offerto, tenuto in scorta, fabbricato o generato niente di nuovo, e tutto quello che un giocatore ha già e che lo nomina continua a leggere esattamente quello che ha sempre letto.
| Famiglia | remove | Che cosa succede |
|---|---|---|
goods | sì | Ritirato. Si risolve ancora per id, sparito da quello che il gioco offre. |
vendor_inventories | sì | Cancellato. La riga viene tolta. |
| tutto il resto | no | Rifiutato, con la ragione. |
a goods record
{ "op": "remove", "id": "iron_ore" }vendor_inventories è l'unica famiglia che toglie il record, e solo perché le regole dei salvataggi dicono già che nessuno punta a quella riga.
Un remove non può portare un when. Un ritiro che un salvataggio potrebbe nominare deve essere deciso, altrimenti un id si risolve una sera e non quella dopo.
Una rimozione è definitiva per una composizione. Un successivo patch, replace o un secondo remove che prende di mira l'ID ritirato viene rifiutato, anche se un ritiro di merci mantiene il vecchio record risolvibile tramite la sua rimozione definitiva. Ciò impedisce al report di salvataggio di indicare "ritirato" mentre un pacchetto successivo fa sì che il record si comporti nuovamente come fornito. Aggiungi un nuovo ID dello spazio dei nomi quando hai bisogno di un nuovo record; non fare affidamento sulla rimozione seguita dalla resurrezione silenziosa.
Quando due mod vogliono la stessa cosa
Si caricano entrambi. Ogni modifica viene composta prima che si costruisca qualcosa, quindi il gioco li vede tutti e due.
| Che cosa si scontra | Che cosa succede |
|---|---|
| Campi diversi di uno stesso record | Si applicano entrambi. Non si perde niente. |
| Lo stesso campo semplice | Vince il load_order più avanti, e uno scontro non dichiarato è un errore: undeclared_collision, e la composizione non è a posto. |
| Due pacchetti che forniscono il record intero | Lo stesso. Il vincitore lo decide il load_order e il piano rifiuta comunque finché qualcuno non lo dichiara. |
Lo stesso elenco, con append_unique / remove_value | Nessun conflitto. Tutti e due dicono che cosa l'elenco deve contenere, non che cosa deve essere. |
| Un pacchetto ritira un record, un altro lo modifica o lo sostituisce | Il ritiro resta valido. L'operazione successiva viene rifiutata, qualunque sia l'ordine di caricamento. |
| Due pacchetti che vestono lo stesso soggetto | Vince il load order più avanti, chi perde è nominato nel resoconto. |
| Un pacchetto che veste il contenuto di un altro pacchetto | Refused. |
Vincere e avere il permesso sono due domande diverse, ed è la parte che sorprende. Il gioco calcola sempre quale pacchetto scrive per ultimo — lasciarlo al caso renderebbe un rifiuto anche un lancio di moneta — e segnala comunque la coppia come una collisione che nessuno ha dichiarato. Il validatore offline rifiuta la stessa coppia senza discutere, così lo scopri prima di un giocatore.
supersedes nel tuo manifesto è il modo di dire che l'hai fatto apposta. Nomina l'id dell'altro pacchetto e lo scontro diventa declared_replacement: registrato, con la ragione, e non più un errore.
Dài al tuo pacchetto un load_order suo. Due pacchetti che condividono un numero non vengono rifiutati, e allora il vincitore cade dall'ordine alfabetico dell'id del mod: un ordine che non ha scelto nessuno dei due autori e che nessun giocatore può leggere sullo schermo.
Immagini, suono, scritte, colore
Portare un file e usarlo sono due passi separati e ti servono entrambi. Un file a cui non punta niente viene letto, controllato, misurato e mai mostrato.
| Tipo | File | Installato | Che cosa vuol dire |
|---|---|---|---|
image | .png, .webp | Sì | Il file viene letto e la texture viene costruita. |
audio | .ogg, .wav | No | I descrittori vengono convalidati, l'intestazione viene letta e la durata delimitata, e non lo suona niente: nessuna famiglia di contenuto porta audio e la funzionalità audio non chiede a nessun catalogo un suono di pacchetto. Porta il suono quando la famiglia esisterà; oggi sarebbe misurato e muto. |
font | .ttf, .otf | No | I descrittori vengono convalidati e la copertura delle lingue controllata, e nessun tema risolve un carattere di pacchetto. L'interfaccia costruisce i suoi caratteri dal tema che porta con sé, quindi un carattere fornito da un pacchetto sarebbe verificato e non impostato su niente. |
Porta il file
Ogni famiglia di risorse è un file descrittore più i file che nomina. Il descrittore deve chiamarsi come la sua famiglia: images.json, audio.json, fonts.json.
where the files go
content/assets/images/
images.json
river_guard.png| Famiglia | Cartella | Accetta | Campi obbligatori |
|---|---|---|---|
images | content/assets/images | .png, .webp | id, file, format |
audio | content/assets/audio | .ogg, .wav (non compresso) | id, file, codec, role |
fonts | content/assets/fonts | .ttf, .otf | id, file, format, sizes, covers, fallback_font |
themes | content/assets/themes | gettoni di colore | id, tokens |
effects | content/assets/effects | modelli dell'ospite | id, template |
a images record
[
{
"id": "northern_reach:river_guard",
"file": "river_guard.png",
"format": "png"
}
]Tre regole che mordono:
- L'intestazione viene controllata prima che qualcosa lo decodifichi.
formatè quello che il file è, non quello che l'estensione dichiara. - Un nome di
fileche contenga..o~, o che cominci con/,\,res://ouser://, viene rifiutato sul nome. - Un id che non si risolve riceve un segnaposto e una segnalazione, mai silenzio.
Puntaci
Su un record che porti tu, con un campo che prende un id di immagine tuo:
| Famiglia | Campo | Che cos'è |
|---|---|---|
items | icon_id | L'icona su un oggetto che porti tu. |
npc_definitions | portrait_id | Il ritratto di un NPC con un nome. |
perks | icon | L'icona di un privilegio. |
Su qualunque cosa, contenuto del gioco base compreso, con un record presentation_bindings che nomina il soggetto, il suo tipo e lo slot:
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"
}
]| Slot | Tu porti | Dove compare | alternative_key | Disegnato |
|---|---|---|---|---|
portrait | image | La cornice del dialogo, per l'id di chi parla. | obbligatorio | sì |
sprite | image | Un segnalino di truppa, il terreno della mappa del mondo, o un edificio in un insediamento. | — | sì |
icon | image | Le celle dell'inventario, per qualunque oggetto — tuo o del gioco. | obbligatorio | sì |
banner | image | I colori del casato sulla sua pagina di diario. | — | sì |
voice | audio | Suona quando compare la battuta di chi parla. | obbligatorio | non ancora |
use_sound | audio | Suona quando un oggetto viene usato e l'uso ha avuto effetto. | — | non ancora |
ambience | audio | Va in ciclo mentre il giocatore sta su quel terreno. | — | non ancora |
theme | theme | Quale delle tue tavolozze indossa l'interfaccia. | — | sì |
font | font | Quale dei tuoi caratteri indossa l'interfaccia. | — | non ancora |
effect | effect | Tempo atmosferico e luce sul terreno a cui è legato. | — | sì |
alternative_key è obbligatorio dove uno slot porta informazione: è la chiave di lingua che dice la stessa cosa a un giocatore che non può ricevere l'immagine.
Suono
role è un limite, non un'etichetta: ciascuno porta la propria durata massima, il proprio tetto su quanti ne suonano insieme, e il cursore che un giocatore va a cercare.
| Ruolo | Per | Cursore |
|---|---|---|
music | Brani | Musica |
ambience | Stanze, tempo, luoghi | Ambiente |
sfx | Effetti brevi | Effetti |
voice | Battute parlate | Effetti |
Un WAV compresso viene rifiutato: decodificarlo richiede un parser, e il parser è proprio la cosa che si sta evitando.
Scritte
covers nomina le lingue per cui il tuo carattere porta i glifi, e la build si rifiuta di installarlo per qualunque altra. Un carattere a cui manca una lingua non fallisce: disegna dei quadratini, e la schermata si legge come una traduzione lasciata a metà, con il testo giusto e la colpa del font.
fallback_font è obbligatorio: nomina un altro id di carattere tuo oppure una famiglia di sistema (Segoe UI, Noto Sans). sizes è ciò su cui viene calcolata la cache dei glifi.
Un carattere solo, mai una raccolta — un .ttc ne contiene parecchi e quale arrivi dipende da un indice che il descrittore non può portare. Caratteri gratuiti con ampia copertura: Google Fonts, Font Squirrel. Controlla che la licenza ti permetta di ridistribuire il file: è il tuo pacchetto a portarlo.
Colore
Gettoni, mai una scena, uno script o un percorso di risorsa. I nomi sono quelli del gioco: bg_deep, bg_mid, bg_button, bg_hover, border, border_hi, text, text_dim, accent, gold. Un nome che questa build non conosce viene nominato nel resoconto invece di restare lì a sembrare applicato.
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" }
]
}
]Le contrast_pairs sono controllate su un rapporto di 4,5 e sotto quello il tema viene rifiutato. Il misuratore di WebAIM ti dice il rapporto di una coppia prima che tu la porti.
Spegni il pacchetto e l'interfaccia si riprende i suoi colori e le sue scritte.
Arte che sta bene
La build controlla che un'immagine sia un'immagine. Non ha niente da dire su se sembri al posto giusto, e in un mondo disegnato in grigi una spada luminosa, allegra e ad alta risoluzione non smette di essere sbagliata per il fatto di superare ogni controllo. Questo è quello che si sa oggi.
| Il registro | Pixel art, grigia e poco eroica. Smorzata, consumata, macchiata dal tempo. Una tavolozza adatta a un pomeriggio di pioggia in una città che ha avuto un brutto anno. |
| Tasselli | 16 pixel, per qualunque cosa disegnata dentro una mappa. Mappe tue. |
| Formati e limiti | .png o .webp, fino a 8192 per lato, fino a 8 MB, controllati dall'intestazione prima che qualcosa li decodifichi. |
| Colore dell'interfaccia | I dieci gettoni di themes, e un rapporto di contrast_pairs di 4,5 sotto il quale il tema viene rifiutato. |
La guida di stile completa non è ancora pubblicata. Che cosa porterà: la tavolozza stessa, le dimensioni a cui viene disegnato ogni tipo di cosa, ed esempi affiancati di che cosa sta dentro il mondo e che cosa ne esce fuori. Vale la pena aspettarla invece di tirare a indovinare, perché il fallimento che previene non è un file rifiutato: è un pacchetto che si installa alla perfezione e fa sembrare il gioco due giochi.
Finché non esiste, il metodo affidabile è quello che non ha bisogno di nessun documento: metti la tua immagine accanto a quella del gioco e guardale insieme.
Mappe tue
Disegna in Tiled, esporta in .tmj, e indicizzalo in 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"
}
]| Regola | Che cosa significa |
|---|---|
| Il corredo | Tasselli da 16 pixel, ortogonali, destra-basso, finiti. |
| I livelli sono ruoli, non nomi | ground, collision e walkable sono obbligatori. Un livello chiamato collisions viene rifiutato invece che ignorato. |
| La geometria si dichiara | La collisione e l'area calpestabile sono oggetti che disegni tu, mai dedotti dall'aspetto dei tasselli. |
| Ogni nome di oggetto ha il tuo spazio dei nomi | northern_reach:towpath, non towpath. |
world_origin | Dove sta il tuo angolo in alto a sinistra, in pixel di mondo. Si dichiara, perché un file di mappa non ha idea di dove si trovi in un mondo. |
| Una mappa dice dove, mai che cosa | Un oggetto poi sul livello bindings nomina un punto d'interesse che hai portato come record; la disposizione lo sposta dove l'hai disegnato. |
| O tutto o niente | Una disposizione che viene rifiutata non colloca proprio niente. |
| Niente percorsi | Una proprietà chiamata path, scene, script, resource o template viene rifiutata per il nome, qualunque cosa contenga. |
Un collegamento che nomina contenuto di un altro pacchetto — o del gioco base — fa rifiutare tutta la disposizione. modding_map_report nomina la disposizione e la regola che l'ha rifiutata.
Missioni tue
Una missione è un insieme di record che hanno senso solo insieme, in content/narrative/quest_plans.
| Tipo | Che cos'è |
|---|---|
arc | La storia. Elenca le missioni che contiene. |
quest | L'incarico: chi lo dà, come si chiama, quanto paga. |
objective | Una cosa che il giocatore deve fare. |
ending | Come finisce l'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"]
}
]| Obiettivo | Sorvegliato oggi |
|---|---|
collect_item | sì — stai portando abbastanza di qualcosa |
defeat_unit | sì — hai ucciso abbastanza di qualcosa |
earn_coin | sì — hai abbastanza denaro |
reach_place | sì — hai visitato un insediamento |
survive_days | sì — sono passati abbastanza giorni |
speak_to, deliver_item, defend_place, escort_unit, learn_lore | no — rifiutati per nome invece di essere accettati e poi mai completabili |
| Ricompensa | Consegnata oggi |
|---|---|
give_item, receive_coin | sì |
change_relation | sì, quando il soggetto è il giocatore |
| gli altri cinque | rifiutati ad alta voce |
- Un piano è o tutto o niente. Un record sbagliato e non se ne installa nessuno: l'alternativa è un arco che si ferma a metà con il giocatore che ha in mano la spada e non il titolo.
- Una ricompensa è un
grant, mai unkind.kinddice quale dei quattro record è questo. Una ricompensa scritta conkindsi legge benissimo e viene rifiutata.
Controlla il tuo con modding_quest_plan_report.
Conversazioni tue
Una conversazione è tre tipi di record in content/narrative/dialogue: il dialogue_graph che la nomina e dice su quale battuta si apre, le battute dialogue_node che sono le righe, e le scelte dialogue_option che ci stanno sopra.
La tua battuta è la tua battuta, e niente la riscrive. Quello che un modello locale può fare è rispondere a una domanda che il giocatore scrive al personaggio, restando dentro quello che la tua battuta dice — e quando non riesce a restarci dentro, dice che non lo sa. È il giocatore a decidere se quella superficie esista del tutto; con il modello spento, il personaggio dice la tua frase e si ferma. La traduzione della tua battuta passa dai file di lingua, come tutto il resto che scrivi.
Il grafo nomina uno speaker, e l'innesco è tutto lì. Ogni personaggio del gioco chiede a questa famiglia quali conversazioni gli stiano sopra quando lo si clicca, quindi puoi dare al fabbro qualcosa da dire senza ridefinire il fabbro.
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"
}
]Tu scrivi la conversazione, mai le parole: ogni battuta è una chiave di lingua, così lo stesso pacchetto si legge in tutte le lingue che il giocatore ha. Un pacchetto che porta prosa viene rifiutato al file invece che allo schermo.
Una battuta e una scelta possono portare ciascuna delle condizioni, e una scelta può portare dei comandi. Una condizione decide se al giocatore la cosa venga mostrata del tutto; un comando è quello che succede quando la prende.
| Controllo | Prende | Chiede | Risposto oggi |
|---|---|---|---|
companion_present | companion | Quel compagno è lì presente a sentirlo. | sì |
faction_stance | faction, stance | Una fazione sta dove l'opzione si aspetta. | sì, per hostile — qualunque altro valore viene rifiutato prima della prima battuta |
has_coin | coin | Il giocatore se lo può permettere. | sì |
has_item | item, count | Il giocatore lo sta portando con sé. | sì |
has_knowledge | lore | Al giocatore questo è stato detto. | sì |
has_trait | trait | Il giocatore è stato costruito così. | sì |
lacks_knowledge | lore | Al giocatore questo non è stato ancora detto. | sì |
quest_state | quest, state | Una missione sta dove l'opzione si aspetta. | sì |
relation_at_least | subject, target, regard | Una parte pensa almeno questo dell'altra. | sì |
season | season | Siamo in quella parte dell'anno. | sì |
time_of_day | phase | Siamo in quella parte della giornata. | sì |
| Comando | Prende | Fa | Eseguito oggi |
|---|---|---|---|
change_relation | subject, target, delta | Modifica una reputazione rispettando le regole sulle relazioni pubblicate dall'host. | sì |
give_item | item, count | Consegna qualcosa. | sì |
grant_knowledge | lore | Dice qualcosa al giocatore. | sì |
open_shop | vendor | Mette sullo schermo le scorte di un mercante. | sì |
pay_coin | coin | Il giocatore paga. | sì |
receive_coin | coin | Il giocatore viene pagato. | sì |
recruit_companion | companion | Aggiungi qualcuno al gruppo quando lo consentono le regole di reclutamento pubblicate dall'host. | sì |
set_quest_state | quest, state | Porta una missione in uno stato che il suo record permette. | sì, per active e failed — qualunque altro valore viene rifiutato prima della prima battuta |
start_combat | encounter | Chiude la conversazione. | sì |
take_item | item, count | Toglie qualcosa. | sì |
travel_to | destination | Sposta la compagnia. | sì |
- Una conversazione che nomina qualcosa che questa build non sa fare non si apre mai. Non la scelta che lo usa: tutta la conversazione, prima della sua prima battuta. Un discorso che si ferma alla terza opzione ha già preso le monete del giocatore.
- Niente muove più di quanto ce ne sia. Chiedi prima con
has_coinohas_item; un pacchetto che se ne dimentica non può mettere il giocatore a meno quaranta monete, perché nessuno ha accettato un debito e nessuna schermata ne spiega uno. - Ogni battuta ha bisogno di una via d'uscita. Una battuta a cui un giocatore può arrivare e da cui non può andarsene viene rifiutata quando il grafo si carica.
Controlla il tuo con modding_dialogue_report.
Scene tue
Una scena è l'unico tipo di contenuto che toglie i comandi al giocatore, quindi è anche l'unico con una regola sul finire. Le scene vivono in content/narrative/scenes e ciascuna nomina un where, il posto in cui si gioca. Entra in quel posto e la scena parte.
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" }
]
}
]| Battuta | Prende | Tempi | Giocata oggi |
|---|---|---|---|
ask_name | prompt_key | la scena la aspetta | sì |
end | — | la scena prosegue | sì |
fade_in | seconds | la scena la aspetta | sì |
fade_out | seconds | la scena la aspetta | sì |
lock_player | — | la scena prosegue | sì |
narrate | line_key, seconds | la scena la aspetta | sì |
play_cue | cue | la scena prosegue | sì |
remove_actor | actor | la scena prosegue | sì |
say | actor, line_key | la scena la aspetta | sì |
show_exit | — | la scena prosegue | sì |
start_dialogue | graph | la scena la aspetta | sì |
unlock_player | — | la scena prosegue | sì |
wait | seconds | la scena la aspetta | sì |
walk_to | actor, anchor | la scena la aspetta | sì |
- Una scena che toglie i comandi deve restituirli. Una sequenza che finisce senza
unlock_playerviene rifiutata, perché l'alternativa è portare una stanza da cui il giocatore può uscire solo chiudendo il gioco. - Le battute vanno in ordine e una battuta bloccante viene aspettata. È questo che fa di una scena una scena invece di un elenco di cose che succedono tutte insieme.
Controlla la tua con modding_scene_report.
Schermate tue
La disposizione di una schermata dice quali sezioni stiano in quale pannello di una schermata che il gioco ha già, e in che ordine. Dispone pezzi che questa build disegna; non può aggiungerne uno, perché una sezione che non ha scritto nessuno non ha niente da disegnare.
Le disposizioni vivono in content/ui/screens. Le famiglie, una per una ha i campi e un record da copiare.
Controlla la tua con modding_screen_report.
Non è comparso niente
Leggi prima lo stato sulla schermata Mod. Quasi tutti gli stati nominano il problema apertamente, sulla riga, e lo fa anche l'errore più comune di tutti: quello che una volta era il primo di questo elenco.
La famiglia che manca da content_types. Scrivi goods.json, ti dimentichi "goods" nell'elenco del manifesto, e la cartella non viene mai aperta: niente viene rifiutato, perché niente è stato letto. Il pacchetto si carica vuoto. Adesso la schermata dice davanti a quale file è passata e che cosa aggiungere:
what the game prints back
content/economy/goods/goods.json was not read — add "goods" to content_types in mod.jsonIl validatore offline stampa la stessa frase, così i due non possono essere in disaccordo. Solo se la riga dice caricato e non nomina nessun file non letto, scendi lungo questo elenco. È in ordine di quanto spesso ciascuno sia il colpevole.
| # | Sintomo | Che cosa dice il validatore |
|---|---|---|
| 1 | Il percorso della cartella è sbagliato | WARN: declared goods root missing: …/content/economy/goods. Un avviso, non un errore: il pacchetto passa lo stesso, ed è per questo che --strict prima di pubblicare è il consiglio che è. Le famiglie, una per una ha la cartella esatta di ogni famiglia. |
| 2 | L'id non ha i due punti | ERROR: add needs an id under your own namespace. frost_blade viene rifiutato; northern_reach:frost_blade viene accettato. |
| 3 | Il JSON è rotto | ERROR: invalid json goods.json: Expecting ',' delimiter: line 6 column 5. Una virgola che manca rende illeggibile tutto il file, e ti viene detta la riga. |
| 4 | Il file è nel pacchetto sbagliato | Lo stesso messaggio del n. 2. Un id con lo spazio dei nomi di qualcun altro non sta a te scriverlo, e il controllo non riesce a distinguerlo da un errore di battitura: sa soltanto che il prefisso non è l'id del tuo pacchetto. |
| 5 | Manca un campo obbligatorio | Il resoconto lo nomina — per i campi che una famiglia richiede davvero, che sono meno di quanti immagineresti. È comparso, ed è sbagliato è il caso in cui non viene segnalato proprio niente. |
I resoconti non tirano mai a indovinare. Un record rifiutato viene nominato, con che cosa aveva che non andava, e di solito con un codice — vedi Ogni codice diagnostico.
È comparso, ed è sbagliato
Il caso più difficile, perché non viene segnalato proprio niente. Due cose superano ogni controllo e ti danno comunque un record che non hai scritto.
Un campo che hai omesso non è un errore: è un valore predefinito. Lo schema di ogni famiglia dice senza quali campi un record non si può installare, e per quasi tutte le famiglie quell'elenco è corto. goods ne richiede esattamente uno: id. Ometti base_price ed è 1. Ometti weight ed è 1.0. Ometti category e la merce è una materia prima. Niente ti avvisa, perché non c'è niente che non va: hai chiesto una merce e ne hai avuta una.
Anche un valore che non è fra le scelte è un valore predefinito. Chi legge mette tutto in maiuscolo prima di cercare, quindi manufactured e MANUFACTURED sono lo stesso valore e le maiuscole non sono mai il problema: non metterti a riscrivere file per quello. Il problema è MANUFACTURED_GOODS: non è un membro, quindi diventa RAW_MATERIAL. SLOW per un decay_tier diventa ETERNAL. Il record si installa, la schermata dice applicato, e la tua candela ha il prezzo e la deperibilità di un'altra cosa.
Niente nel gioco lo dice, perché non c'è niente da dire: il campo è dichiarato come stringa e una stringa scritta male è comunque una stringa. Il validatore è l'unico posto in cui si può prendere, e adesso lo prende:
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=1Un avviso e non un errore, perché il record si carica davvero e rifiutarlo adesso romperebbe pacchetti che già funzionano. --strict lo trasforma in un errore, ed è tutta la ragione per cui si esegue --strict prima di pubblicare.
Un campo che hai omesso resta muto, e quello non si può prendere: omettere category e scrivere RAW_MATERIAL sono la stessa richiesta. Perciò le tabelle dei campi in Le famiglie, una per una segnano Obbligatorio e danno la colonna dei valori come la forma che il caricatore controlla. Quando un record si carica e si comporta come qualcos'altro, confronta prima i tuoi campi con quella tabella: quello che stai cercando è un campo che non hai scritto, o una parola che il caricatore non ha riconosciuto.
Riferimento
Ogni famiglia
Una cartella e un resoconto per famiglia. La colonna dello stato è misurata sulla build, quindi non è mai una promessa che il gioco non mantiene. Che cos'è è solo la riga d'apertura, così che la tabella resti una cosa che si può scorrere con l'occhio; la descrizione completa di ogni famiglia, con i suoi campi e un record da copiare, è la sua voce in Le famiglie, una per una.
| Famiglia | Stato | Cartella nel tuo pacchetto | Comando di resoconto | Che cos'è |
|---|---|---|---|---|
adaptive | Pronta all'uso | content/player/adaptive | modding_adaptive_report | Profili che guardano come sta andando una partita e ne suggeriscono un'impostazione diversa. |
audio | Validato, non viene ancora consumato da nulla | content/assets/audio | modding_audio_report | Suoni che un pacchetto porta, nominati per id: musica, ambiente, effetti e voce, ciascuno che punta a un file dentro la propria cartella e che dichiara il ruolo che lo delimita. |
buildings | Pronta all'uso | content/world/buildings | modding_building_report | Definizioni di edifici e di servizi dell'insediamento: etichetta, colore, ruolo e un interno riusato. |
caravans | Pronta all'uso | content/logistics/caravans | modding_caravan_report | Rotte commerciali che una carovana percorre: da dove parte, dove sta andando, che cosa porta, quanto è ben scortata e quanto va veloce. |
combat_balance | Pronta all'uso | content/combat/balance | modding_combat_balance_report | Valori di bilanciamento del combattimento, delimitati, che regolano parametri del risolutore già esistenti senza aggiungere regole, operazioni o meccaniche. |
dialogue | Pronta all'uso | content/narrative/dialogue | modding_dialogue_report | Conversazioni come record: il grafo, le sue battute e le scelte che ci stanno sopra. |
effects | Pronta all'uso | content/assets/effects | modding_effect_report | Tempo atmosferico, polvere, scintille e luci, composti a partire dai modelli che l'ospite mette a disposizione. |
enemy_archetypes | Pronta all'uso | content/threat/enemy_archetypes | modding_enemy_archetype_report | Tipi di nemico che il livello strategico conosce: grado, quali varianti schierano, dove si accampano, quanto è grande la guarnigione e ogni quanto fanno razzia. |
enemy_variants | Pronta all'uso | content/combat/enemy_variants | modding_enemy_variant_report | Blocchi di statistiche per un tipo di corpo nemico sul campo: classe, grado, i cinque attributi e gli id dell'arma, della mano secondaria e dello scudo che porta. |
fonts | Validato, non viene ancora consumato da nulla | content/assets/fonts | modding_font_report | Caratteri tipografici che un pacchetto porta, nominati per id: il file, le dimensioni a cui vengono disegnati, e le lingue di cui portano i glifi. |
goods | Pronta all'uso | content/economy/goods | modding_goods_report | Merci commerciabili e le loro proprietà economiche. |
group_archetypes | Pronta all'uso | content/strategic/group_archetypes | modding_group_archetype_report | Parametri di strategia regolabili per un gruppo che vive sulla mappa del mondo: raggio d'allarme, preferenza di bersaglio, numero di membri, soglie di rifornimento e di ritirata. |
images | Pronta all'uso | content/assets/images | modding_image_report | Immagini che un pacchetto porta, nominate per id: icone, ritratti e fogli di sprite, ciascuna che punta a un file dentro la propria cartella. |
input_bindings | Pronta all'uso | content/input | modding_input_report | Azioni proprie di un pacchetto, con il tasto che vorrebbero. |
items | Pronta all'uso | content/inventory/items | modding_items_report | Oggetti d'inventario, armi e armature comprese. |
locales | Pronta all'uso | content/locale | modding_locale_report | Le parole che un giocatore legge, in CSV con una colonna per lingua: le chiavi proprie del pacchetto, e quelle del gioco dove il pacchetto dichiara la sovrascrittura. |
lore | Pronta all'uso | content/narrative/lore | modding_lore_report | Voci del Codex: luoghi, persone, eventi, usanze e cose su cui un mondo racconta storie. |
maps | Pronta all'uso | content/world/maps | modding_map_report | Disposizioni che un pacchetto disegna in Tiled, nominate per id: il file, dove sta nel mondo, e la chiave di lingua con cui è conosciuta. |
mercenary_templates | Pronta all'uso | content/character/mercenaries | modding_mercenary_report | Modelli di mercenari assoldabili: nome, classe, provenienza, salute e morale iniziali, costo d'ingaggio e il giorno in cui compaiono per la prima volta. |
mr_lines | Pronta all'uso | content/medieval_realism/structured | modding_mr_lines_report | Righe strutturate di realismo medievale, indirizzate per file e id di riga invece che per un campo id nel JSON. |
noble_houses | Pronta all'uso | content/politics/noble_houses | modding_noble_house_report | Dati iniziali di un casato nobiliare: il signore, l'erede, quali insediamenti rispondono al casato, e chi conta come rivale o alleato. |
npc_definitions | Pronta all'uso | content/narrative/npcs | modding_npc_report | Definizioni di NPC con un nome. |
perks | Pronta all'uso | content/character/perks | modding_perk_report | Privilegi dichiarativi: inneschi ed effetti, senza nessun gestore scritto in codice. |
pois | Pronta all'uso | content/world/pois | modding_poi_report | Punti d'interesse collocati per coordinate sulla mappa del mondo scritta a mano. |
presentation_bindings | Pronta all'uso | content/presentation/bindings | - | Quale risorsa del pacchetto riempia quale slot su quale soggetto: l'icona su un oggetto, lo sprite su un'unità o un tassello, lo stendardo su una fazione, tanto per il contenuto del pacchetto quanto per quello del gioco base. |
progress | Pronta all'uso | content/player/progress | - | Record di progressione del giocatore: obiettivi, profili di difficoltà sicuri e profili di partita entro le regole dell'ospite. |
quest_metadata | Pronta all'uso | content/narrative/quest_metadata | modding_quest_metadata_report | Record di metadati delle missioni, indicizzati per quest_id invece che per id. |
quest_plans | Pronta all'uso | content/narrative/quest_plans | modding_quest_plan_report | Piani di missione come record: gli archi, le missioni, gli obiettivi e i finali che un pacchetto scrive e da cui il gioco costruisce missioni sue. |
quests | Controllata, non ancora installata | content/narrative/quests | - | Risorse di missione scritte a mano, caricate per percorso invece che interpretate come record. |
recipes | Pronta all'uso | content/economy/recipes | - | Ricette di artigianato: che cosa si consuma, che cosa ne esce, dove si lavora, quanto costa e quanto è probabile che vada male. |
relationships | Pronta all'uso | content/companion/relationships | - | Modelli di compagni, politiche di rapporto delimitate, condizioni di reclutamento e legami dichiarativi. |
scenes | Pronta all'uso | content/narrative/scenes | modding_scene_report | Scene messe in scena: la stanza, chi ci sta dentro e le battute che si svolgono in ordine. |
screens | Pronta all'uso | content/ui/screens | modding_screen_report | Disposizioni di schermata: quali sezioni stiano in quale pannello di una schermata che il gioco ha già, e in che ordine. |
settings | Pronta all'uso | content/settings | modding_settings_report | Opzioni che un giocatore può cambiare, dichiarate invece che disegnate. |
themes | Pronta all'uso | content/assets/themes | modding_theme_report | Tavolozze dell'interfaccia come gettoni: colori con un nome, dimensioni e spaziature, con le coppie il cui contrasto un giocatore deve poter leggere. |
vendor_inventories | Pronta all'uso | content/world/vendor_inventories | modding_vendor_inventory_report | Tabelle delle scorte dei mercanti. |
world_generation | Pronta all'uso | content/world/generation | - | Profili di generazione fatti di soli dati: scelte pesate di bioma e di collocazione, possedute dall'ospite. |
- Pronta all'uso — forma pubblicata, il gioco installa i tuoi record, esiste un esempio, e i tuoi id sopravvivono a un salvataggio e a un ricaricamento.
- Validato, non viene ancora consumato da nulla — il loader legge e controlla la famiglia, ma nessuna superficie di pacchetto rivolta al giocatore la consuma. I pacchetti audio e font sono in questo livello: un report pulito non fa comparire nel gioco un segnale muto o un font inutilizzato.
- Controllata, non ancora installata — il gioco riconosce la famiglia e controlla il tuo file, e niente lo mette dentro una partita in corso. Un pacchetto che la prende di mira supera ogni controllo e non carica niente. Sta nella pagina di proposito: l'alternativa è che qualcuno ci passi una serata senza mai scoprire di non aver sbagliato niente.
Decise per intero, senza nessuna famiglia che le porti, quindi nessun manifesto può chiederle:
| Sarebbe | Dove andrebbe | Che cos'è |
|---|---|---|
feature_extension | ancora nessuna cartella | Un pacchetto che sia una funzionalità invece che contenuto. Che cosa un mod non potrà mai fare è la lettura onesta di questo. |
Questi non sono rifiuti. Che cosa un mod non potrà mai fare è quell'elenco.
Le famiglie, una per una
Ogni famiglia che la build conosce, che cosa accetta, e un record che puoi copiare.
- I campi obbligatori sono quelli senza cui un record non si può installare.
- La colonna dei valori è la forma che il caricatore controlla, non un suggerimento.
- Dove una famiglia lo dice, un campo che la tabella non nomina viene rifiutato insieme al record in cui si trova. Un errore di battitura nel nome di un campo è un record che non si carica, e il resoconto della famiglia lo dice per nome.
Ogni voce dice anche che cosa succede a un salvataggio il giorno in cui un giocatore ti disinstalla:
| Risposta | Che cosa fa il salvataggio |
|---|---|
preserve_inert_reference | L'id resta, non si risolve in niente, e viene segnalato. Quello che il giocatore aveva ha ancora un nome. |
substitute_placeholder | Risponde un sostituto stabile posseduto dal motore, così il mondo si carica lo stesso, e l'id originale viene conservato accanto. |
drop_optional_presentation | Il riferimento viene lasciato cadere perché non ci dipende niente. Solo una famiglia di presentazione può dichiararlo. |
Qui non c'è niente scritto a mano. I campi vengono dallo schema pubblicato di ogni famiglia. Ogni esempio è uno dei pacchetti che la matrice di prova del framework fa girare contro il caricatore, rimesso sotto lo spazio dei nomi northern_reach, e ricontrollato contro il suo schema mentre entra in questa pagina: un esempio che il gioco rifiuterebbe fa fallire la build.
Il mondo e i luoghi che contiene
5 famiglie: buildings, caravans, maps, pois, world_generation.
buildings
Definizioni di edifici e di servizi dell'insediamento: etichetta, colore, ruolo e un interno riusato.
- Stato Pronta all'uso
- Percorsa in Il servizio di un edificio
- Cartella
content/world/buildings - Record indirizzati per il campo
id - Resoconto
modding_building_report - Se un giocatore ti disinstalla
substitute_placeholder. Un insediamento con un buco dove c'era un servizio è ingiocabile; un edificio visibilmente mancante si legge e si recupera.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
role | sì | stringa |
color | - | qualunque |
description_key | - | stringa |
interior | - | testo, id |
interior_service | - | testo, id |
label | - | stringa |
label_key | - | stringa |
map_binding | - | testo, id |
services | - | elenco |
settlement | - | testo, id |
tier | - | intero da 0 a 5 |
In un file chiamato buildings.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Rotte commerciali che una carovana percorre: da dove parte, dove sta andando, che cosa porta, quanto è ben scortata e quanto va veloce.
- Stato Pronta all'uso
- Cartella
content/logistics/caravans - Record indirizzati per il campo
id - Resoconto
modding_caravan_report - Se un giocatore ti disinstalla
preserve_inert_reference. Una rotta il cui pacchetto è sparito conserva il nome e non porta niente. Sostituire una destinazione manderebbe le merci di un giocatore in un posto che non ha mai accettato.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
origin_settlement_id | sì | stringa |
destination_settlement_id | sì | stringa |
cargo_type | - | stringa |
cargo_value | - | intero, 0 o più |
daily_progress | - | numero da 0.01 a 1.0 |
display_name | - | stringa |
group_archetype_id | - | stringa |
guard_strength | - | none, light, medium, heavy |
initial_spawn_offset_days | - | intero da 0 a 30 |
In un file chiamato caravans.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Disposizioni che un pacchetto disegna in Tiled, nominate per id: il file, dove sta nel mondo, e la chiave di lingua con cui è conosciuta. L'indice è il record; la disposizione che gli sta accanto viene letta come dati e mai come risorsa, normalizzata in forma canonica, controllata contro il corredo pubblicato e assemblata prima che si collochi qualcosa. Una disposizione che viene rifiutata non colloca proprio niente, perché mezza mappa è una regione in cui il giocatore entra senza avere modo di sapere quale metà sia arrivata.
- Stato Pronta all'uso
- Cartella
content/world/maps - Record indirizzati per il campo
id - Resoconto
modding_map_report - Se un giocatore ti disinstalla
drop_optional_presentation. Nessun salvataggio nomina una disposizione. Un salvataggio nomina il punto d'interesse che una disposizione ha spostato, e quel record conserva la propria coordinata, quindi una mappa ritirata costa la disposizione e mai il contenuto. Lasciarla cadere è quello che fa tornare il mondo a quello che dicono i suoi record, invece di tenere una posizione che nessuno fornisce più.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
file | sì | testo, fixed shape |
name_key | sì | stringa |
world_origin | sì | elenco di interi da -1000000 a 1000000 |
region_id | - | stringa |
sha256 | - | testo, fixed shape |
In un file chiamato maps.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Punti d'interesse collocati per coordinate sulla mappa del mondo scritta a mano.
- Stato Pronta all'uso
- Percorso in Un luogo sulla mappa
- Cartella
content/world/pois - Record indirizzati per il campo
id - Resoconto
modding_poi_report - Se un giocatore ti disinstalla
preserve_inert_reference. Un luogo scoperto resta scoperto. Missioni e cronologia dei viaggi puntano all'id.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
display_name | sì | stringa |
awareness_modifier | - | numero da -1 a 1 |
description | - | stringa |
discovery_radius | - | numero da 1 a 10 |
kind | - | intero o stringa |
linked_quest_id | - | stringa |
morale_modifier | - | intero da -10 a 10 |
narrative_significance_key | - | stringa |
one_time_loot | - | booleano |
world_position | - | qualunque |
In un file chiamato pois.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Profili di generazione fatti di soli dati: scelte pesate di bioma e di collocazione, possedute dall'ospite.
- Stato Pronta all'uso
- Cartella
content/world/generation - Record indirizzati per il campo
id - Resoconto nessuno suo; se ne occupa
modding_preflight_report - Se un giocatore ti disinstalla
preserve_inert_reference. Un salvataggio registra l'id del profilo scelto. Se il suo pacchetto è assente, conservare e segnalare quell'id è più sicuro che ricostruire in silenzio la partita con la mappa del gioco base.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
kind | sì | qualunque |
id | sì | testo, id |
stream | sì | testo, id |
tables | sì | oggetto |
description_key | - | stringa |
name_key | - | stringa |
In un file chiamato profiles.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
}
]
}
}
]Persone, casati e quello che sanno fare
8 famiglie: enemy_archetypes, enemy_variants, group_archetypes, mercenary_templates, noble_houses, npc_definitions, perks, relationships.
enemy_archetypes
Tipi di nemico che il livello strategico conosce: grado, quali varianti schierano, dove si accampano, quanto è grande la guarnigione e ogni quanto fanno razzia.
- Stato Pronta all'uso
- Cartella
content/threat/enemy_archetypes - Record indirizzati per il campo
id - Resoconto
modding_enemy_archetype_report - Se un giocatore ti disinstalla
preserve_inert_reference. Un accampamento punta ancora a ciò che l'ha stabilito. Sostituire cambierebbe in silenzio che cosa sta assediando un insediamento; nominare l'assenza si legge.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
aggression | - | numero da 0 a 1 |
behavior_profile_mix | - | elenco di stringhe |
camp_count | - | intero da 0 a 12 |
camp_glyph | - | stringa |
corruption_chance | - | numero da 0 a 1 |
description | - | stringa |
display_name | - | stringa |
encounter_id | - | stringa |
garrison_max | - | intero da 1 a 60 |
garrison_min | - | intero da 1 a 60 |
preferred_camp_biomes | - | elenco di stringhe |
raid_cooldown_days | - | intero da 0 a 30 |
sortie_size_max | - | intero da 1 a 30 |
sortie_size_min | - | intero da 1 a 30 |
target_preferences | - | elenco di stringhe |
tier | - | intero da 1 a 5 |
variant_ids | - | elenco di stringhe |
variant_weights | - | elenco |
In un file chiamato enemy_archetypes.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Blocchi di statistiche per un tipo di corpo nemico sul campo: classe, grado, i cinque attributi e gli id dell'arma, della mano secondaria e dello scudo che porta.
- Stato Pronta all'uso
- Cartella
content/combat/enemy_variants - Record indirizzati per il campo
id - Resoconto
modding_enemy_variant_report - Se un giocatore ti disinstalla
substitute_placeholder. Un corpo già in campo senza blocco di statistiche non si può combattere. Un sostituto stabile posseduto dal motore tiene la battaglia risolvibile e l'id originale viene conservato accanto.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
archetype_id | sì | stringa |
agility | - | numero da 0 a 12 |
ai_behavior | - | stringa |
aim | - | numero da 0 a 12 |
constitution | - | numero da 0 a 12 |
display_name | - | stringa |
main_weapon_id | - | stringa |
off_weapon_id | - | stringa |
shield_id | - | stringa |
special_ability_description | - | stringa |
special_ability_name | - | stringa |
strength | - | numero da 0 a 12 |
tier | - | intero da 1 a 4 |
variant_class | - | soldier, archer, berserker, ranger, finisher |
will | - | numero da 0 a 12 |
In un file chiamato enemy_variants.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Parametri di strategia regolabili per un gruppo che vive sulla mappa del mondo: raggio d'allarme, preferenza di bersaglio, numero di membri, soglie di rifornimento e di ritirata.
- Stato Pronta all'uso
- Cartella
content/strategic/group_archetypes - Record indirizzati per il campo
id - Resoconto
modding_group_archetype_report - Se un giocatore ti disinstalla
substitute_placeholder. L'intelligenza strategica deve leggere una soglia da qualche parte. Risponde un valore predefinito posseduto dal motore, che è la stessa cosa su cui questa famiglia già ripiega.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
aggression | - | stringa |
alarm_radius_px | - | numero da 0 a 2000 |
behavior_profile_mix | - | elenco di stringhe |
captain_archetype_id | - | stringa |
display_name | - | stringa |
faction_id | - | stringa |
kind | - | none, caravan, patrol, army, lair, camp, … |
max_members | - | intero da 1 a 60 |
member_archetype_mix | - | elenco di stringhe |
min_members | - | intero da 1 a 60 |
night_aggression_multiplier | - | numero da 0.25 a 4 |
provisions_max | - | intero da 0 a 99 |
retreat_hp_pct | - | numero da 0 a 1 |
target_preference | - | stringa |
In un file chiamato group_archetypes.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Modelli di mercenari assoldabili: nome, classe, provenienza, salute e morale iniziali, costo d'ingaggio e il giorno in cui compaiono per la prima volta.
- Stato Pronta all'uso
- Cartella
content/character/mercenaries - Record indirizzati per il campo
id - Resoconto
modding_mercenary_report - Se un giocatore ti disinstalla
preserve_inert_reference. I mercenari già ingaggiati vivono nel salvataggio come unità; solo l'elenco della taverna perde il suo modello. L'id resta nominato, così l'origine dell'organico si legge ancora.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
display_name | sì | stringa |
available_from_day | - | intero da 0 a 999 |
background | - | stringa |
class_id | - | stringa |
hire_cost | - | intero da 0 a 9999 |
hp_max | - | intero da 1 a 999 |
morale_start | - | intero da 1 a 100 |
In un file chiamato mercenaries.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Dati iniziali di un casato nobiliare: il signore, l'erede, quali insediamenti rispondono al casato, e chi conta come rivale o alleato.
- Stato Pronta all'uso
- Cartella
content/politics/noble_houses - Record indirizzati per il campo
id - Resoconto
modding_noble_house_report - Se un giocatore ti disinstalla
preserve_inert_reference. La considerazione di un giocatore verso un casato è registrata sul suo id. Sostituirne uno riscriverebbe senza dire niente a chi era leale.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
alignment | - | pro_crown, pragmatic, isolationist, hostile, neutral, opportunist, … |
ally_house_ids | - | qualunque |
apex_ambition | - | qualunque |
apex_claim_legitimacy | - | qualunque |
captain_initial_opinion | - | intero da 0 a 100 |
captain_initial_stance | - | hostile, suspicious, neutral, willing, allied |
castle_id | - | stringa |
corruption_risk | - | low, moderate, high, critical, unknown |
current_lord_id | - | stringa |
designer_hooks | - | stringa |
display_name | - | stringa |
display_name_key | - | stringa |
family_npc_ids | - | qualunque |
heir_id | - | stringa |
house_power_base | - | qualunque |
is_defunct | - | booleano |
is_minor | - | booleano |
lord_state | - | healthy, ailing, corrupted, missing, dead, none |
lore_summary | - | stringa |
predecessor_house_id | - | stringa |
rival_house_ids | - | qualunque |
secret_flags | - | qualunque |
settlement_ids | - | qualunque |
steward_npc_id | - | stringa |
strength | - | dominant, stable, reduced, weakened, vacant, extinct |
In un file chiamato noble_houses.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Definizioni di NPC con un nome.
- Stato Pronta all'uso
- Percorso in Un mercante che lo tiene
- Cartella
content/narrative/npcs - Record indirizzati per il campo
id - Resoconto
modding_npc_report - Se un giocatore ti disinstalla
preserve_inert_reference. Una persona con un nome che il mondo ricorda non è la stessa cosa di una che non è mai esistita, e i rapporti puntano all'id.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
display_name | sì | stringa |
faction | - | stringa o intero |
flag_keys | - | elenco di stringhe |
is_vendor | - | booleano |
kill_reputation_delta | - | intero da -100 a 100 |
location_afternoon | - | testo, id |
location_evening | - | testo, id |
location_morning | - | testo, id |
lore_only | - | booleano |
need_quest_ids | - | elenco di stringhe |
offers_quest_ids | - | elenco di stringhe |
personal_need | - | stringa |
personality_tags | - | elenco di stringhe |
portrait_id | - | testo, id |
price_multiplier | - | numero da 0.1 a 10 |
role | - | stringa o intero |
settlement_id | - | testo, id |
short_bio | - | stringa |
starts_hidden | - | booleano |
title | - | stringa |
vendor_inventory_id | - | testo, id |
voice_tone | - | stringa |
In un file chiamato npcs.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Privilegi dichiarativi: inneschi ed effetti, senza nessun gestore scritto in codice.
- Stato Pronta all'uso
- Cartella
content/character/perks - Record indirizzati per il campo
id - Resoconto
modding_perk_report - Se un giocatore ti disinstalla
preserve_inert_reference. Un personaggio conserva quello che si è guadagnato. Togliere un privilegio riscrive in silenzio una costruzione su cui il giocatore ha speso una partita.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
skill | sì | testo, fixed shape |
name_key | sì | stringa |
kind | sì | road, junction, lateral, capstone |
col | sì | intero da 0 a 4 |
row | sì | intero da 1 a 7 |
level | sì | intero da 1 a 300 |
description_key | - | stringa |
icon | - | testo, id |
parents | - | elenco di stringhe |
side | - | L, R |
In un file chiamato perks.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Modelli di compagni, politiche di rapporto delimitate, condizioni di reclutamento e legami dichiarativi.
- Stato Pronta all'uso
- Cartella
content/companion/relationships - Record indirizzati per il campo
id - Resoconto nessuno suo; se ne occupa
modding_preflight_report - Se un giocatore ti disinstalla
preserve_inert_reference. Il seme del rapporto di un compagno resta attaccato al suo id, così togliere un pacchetto non può azzerare in silenzio fiducia, rancori o storia degli abbandoni.
Campi. Questa famiglia contiene più di un tipo di record, e ogni tipo viene controllato contro il proprio elenco. Un campo che questa tabella non nomina viene rifiutato insieme al record.
Un record con kind: bond:
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
kind | sì | bond |
relation | sì | stringa |
subject | sì | stringa |
target | sì | stringa |
initial_regard | sì | intero da -100 a 100 |
policy | sì | stringa |
description_key | - | stringa |
name_key | - | stringa |
note_key | - | stringa |
Un record con kind: companion_template:
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
kind | sì | companion_template |
unit | sì | stringa |
recruit | sì | stringa |
loyalty | sì | stringa |
description_key | - | stringa |
leave_below | - | intero da -100 a 100 |
name_key | - | stringa |
starting_regard | - | intero da -100 a 100 |
Un record con kind: recruit_terms:
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
kind | sì | recruit_terms |
means | sì | stringa |
cost | - | intero da 0 a 1000000 |
description_key | - | stringa |
name_key | - | stringa |
requires_bond | - | stringa |
Un record con kind: relationship_policy:
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
kind | sì | relationship_policy |
relation_kinds | sì | elenco di stringhe |
bounds | sì | oggetto |
bands | sì | elenco di oggetti |
decay_per_day | - | intero da 0 a 20 |
description_key | - | stringa |
max_change_per_event | - | intero da 1 a 50 |
name_key | - | stringa |
In un file chiamato relationships.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
}
]Cose, commercio e i numeri dietro uno scontro
5 famiglie: combat_balance, goods, items, recipes, vendor_inventories.
combat_balance
Valori di bilanciamento del combattimento, delimitati, che regolano parametri del risolutore già esistenti senza aggiungere regole, operazioni o meccaniche.
- Stato Pronta all'uso
- Cartella
content/combat/balance - Record indirizzati per il campo
id - Resoconto
modding_combat_balance_report - Se un giocatore ti disinstalla
substitute_placeholder. Il bilanciamento è dato di definizione posseduto dall'ospite, non inventario del giocatore. Quando il suo pacchetto è assente risponde il bilanciamento canonico e stabile, e il caricamento successivo non si porta dietro una seconda via di salvataggio delle regolazioni.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
values | sì | oggetto |
In un file chiamato balance.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Merci commerciabili e le loro proprietà economiche.
- Stato Pronta all'uso
- Percorsa in Una merce da vendere
- Cartella
content/economy/goods - Record indirizzati per il campo
id - Resoconto
modding_goods_report - Se un giocatore ti disinstalla
preserve_inert_reference. Una scorta che nomina una merce che nessuno fornisce è onesta. Sostituirla cambierebbe in silenzio quello che un giocatore possiede.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
base_price | - | intero da 0 a 1000000 |
category | - | stringa o intero |
daily_consumption_class | - | stringa |
decay_tier | - | stringa o intero |
display_name | - | stringa |
display_name_key | - | stringa |
linked_item_id | - | stringa |
production_class | - | stringa |
tags | - | elenco di stringhe |
weight | - | numero da 0 a 10000 |
In un file chiamato goods.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Oggetti d'inventario, armi e armature comprese.
- Stato Pronta all'uso
- Percorso in Un oggetto da portare
- Cartella
content/inventory/items - Record indirizzati per il campo
id - Resoconto
modding_items_report - Se un giocatore ti disinstalla
preserve_inert_reference. Il deposito continua a nominare quello che c'era dentro, ed è l'unica ragione per cui reinstallare glielo restituisce.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
base_value | - | intero, 0 o più |
category | - | stringa o intero |
condition | - | numero da 0 a 1 |
description_key | - | stringa |
display_name | - | stringa |
display_name_key | - | stringa |
icon_id | - | testo, id |
max_stack | - | intero, 1 o più |
quality_tier | - | intero, 0 o più |
rarity | - | stringa o intero |
sellable | - | booleano |
tags | - | elenco di stringhe |
weight | - | numero, 0 o più |
In un file chiamato items.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Ricette di artigianato: che cosa si consuma, che cosa ne esce, dove si lavora, quanto costa e quanto è probabile che vada male.
- Stato Pronta all'uso
- Cartella
content/economy/recipes - Record indirizzati per il campo
id - Resoconto nessuno suo; se ne occupa
modding_preflight_report - Se un giocatore ti disinstalla
preserve_inert_reference. Niente in un salvataggio nomina una ricetta: un salvataggio nomina l'oggetto che una lavorazione ha prodotto, e ne risponde la famiglia di quell'oggetto. Quello che una ricetta ritirata lascia è una postazione che non offre più qualcosa, il che viene segnalato invece che riparato, perché inventare una ricetta sostitutiva metterebbe in mano al giocatore un oggetto che nessun pacchetto fornisce.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
inputs | sì | oggetto |
craft_tax_rate | - | numero da 0.0 a 1.0 |
description_key | - | stringa |
display_name_key | - | stringa |
enhancer_policy | - | none, consumed, preserved, damaged, transformed |
failure_policy | - | none, lose_fuel, lose_catalyst, lose_all, damaged_output |
gold_cost | - | intero da 0 a 9999 |
legality | - | legal, licensed, suspicious, forbidden, black_market |
optional_enhancer | - | stringa |
output_count | - | intero da 1 a 99 |
output_good_id | - | stringa |
output_item_id | - | stringa |
quality_policy | - | fixed, material_inputs, crafter_skill, enhancer, materials_and_crafter |
recipe_kind | - | normal, equipment, special, enhancement |
requires_perk_id | - | stringa |
requires_service | - | stringa |
station_fee | - | intero da 0 a 9999 |
success_chance | - | numero da 0.0 a 1.0 |
time_cost_minutes | - | intero da 1 a 60 |
tools_required | - | elenco di stringhe |
In un file chiamato recipes.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Tabelle delle scorte dei mercanti.
- Stato Pronta all'uso
- Percorso in Un mercante che lo tiene
- Cartella
content/world/vendor_inventories - Record indirizzati per il campo
id - Resoconto
modding_vendor_inventory_report - Se un giocatore ti disinstalla
drop_optional_presentation. Le scorte si rigenerano. Un mercante con lo scaffale vuoto è uno stato leggibile e alla riga non punta nient'altro.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
display_name | sì | stringa |
entries | sì | elenco di oggetti |
buyback_rate | - | numero da 0 a 1 |
description | - | stringa |
global_price_multiplier | - | numero, 0 o più |
npc_id | - | stringa |
In un file chiamato vendors.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
}
]
}
]Storia, missioni e le parole che un giocatore legge
9 famiglie: dialogue, locales, lore, mr_lines, progress, quest_metadata, quest_plans, quests, scenes.
dialogue
Conversazioni come record: il grafo, le sue battute e le scelte che ci stanno sopra. Tre tipi condividono la famiglia ed è kind a dire quale. Un pacchetto scrive la conversazione, mai le parole — ogni battuta è una chiave di lingua — e ogni condizione e ogni conseguenza sono un controllo o un comando che questa build già esegue.
- Stato Pronta all'uso
- Cartella
content/narrative/dialogue - Record indirizzati per il campo
id - Resoconto
modding_dialogue_report - Se un giocatore ti disinstalla
preserve_inert_reference. Un salvataggio registra quello che una conversazione ha fatto — una missione che si è mossa, un oggetto che ha cambiato mano, una verità appresa — mai la conversazione stessa, che è finita nel momento in cui si scrive qualcosa. Quando il pacchetto se ne va, le conseguenze restano perché non sono mai state del dialogo, e la conversazione semplicemente non viene più offerta. Sostituirla metterebbe in bocca a un personaggio parole che il suo autore non ha mai scritto.
Campi. Questa famiglia contiene più di un tipo di record, e ogni tipo viene controllato contro il proprio elenco. Un campo che questa tabella non nomina viene rifiutato insieme al record.
Un record con kind: dialogue_graph:
| Campo | Necessario | Valori |
|---|---|---|
kind | sì | dialogue_graph |
id | sì | stringa |
entry | sì | stringa |
description_key | - | testo, fixed shape |
name_key | - | testo, fixed shape |
speaker | - | stringa |
Un record con kind: dialogue_node:
| Campo | Necessario | Valori |
|---|---|---|
kind | sì | dialogue_node |
id | sì | stringa |
graph | sì | qualunque |
voice | sì | line |
speaker | sì | stringa |
line_key | sì | qualunque |
conditions | - | qualunque |
description_key | - | qualunque |
name_key | - | qualunque |
reveals | - | qualunque |
Un record con kind: dialogue_node:
| Campo | Necessario | Valori |
|---|---|---|
kind | sì | dialogue_node |
id | sì | stringa |
graph | sì | qualunque |
voice | sì | narration |
line_key | sì | qualunque |
conditions | - | qualunque |
description_key | - | qualunque |
name_key | - | qualunque |
reveals | - | qualunque |
Un record con kind: dialogue_node:
| Campo | Necessario | Valori |
|---|---|---|
kind | sì | dialogue_node |
id | sì | stringa |
graph | sì | qualunque |
voice | sì | end |
conditions | - | qualunque |
description_key | - | qualunque |
line_key | - | qualunque |
name_key | - | qualunque |
reveals | - | qualunque |
Un record con kind: dialogue_option:
| Campo | Necessario | Valori |
|---|---|---|
kind | sì | dialogue_option |
id | sì | stringa |
node | sì | stringa |
label_key | sì | testo, fixed shape |
goto | sì | stringa |
commands | - | elenco di qualunque cosa |
conditions | - | elenco di qualunque cosa |
description_key | - | testo, fixed shape |
name_key | - | testo, fixed shape |
In un file chiamato gate_toll.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
}
]
}
]Il fixture contiene 12 record; ne sono mostrati 3.
locales
Le parole che un giocatore legge, in CSV con una colonna per lingua: le chiavi proprie del pacchetto, e quelle del gioco dove il pacchetto dichiara la sovrascrittura.
- Stato Pronta all'uso
- Cartella
content/locale - Resoconto
modding_locale_report - Se un giocatore ti disinstalla
preserve_inert_reference. Un salvataggio nomina il record, mai le parole che lo dicono, quindi un pacchetto ritirato fra due sessioni costa una traduzione e non una cosa. La chiave viene conservata e si mostra, il che si legge come una traduzione mancante invece che come contenuto sparito.
Colonne. Una colonna che questa tabella non nomina viene rifiutata insieme al record.
| Colonna | Necessario | Valori |
|---|---|---|
key | sì | testo, id |
en | - | stringa |
In un file chiamato words.csv. Il nome del file è metà dell'indirizzo e l'id della riga è l'altra metà, quindi due file possono contenere lo stesso id di riga senza scontrarsi:
a locales file
key,en,it
word_pack:GOOD_FROST_SALT,Frost Salt,Sale di Brinalore
Voci del Codex: luoghi, persone, eventi, usanze e cose su cui un mondo racconta storie. Una voce caricata non è una voce conosciuta.
- Stato Pronta all'uso
- Cartella
content/narrative/lore - Record indirizzati per il campo
id - Resoconto
modding_lore_report - Se un giocatore ti disinstalla
preserve_inert_reference. Una voce del Codex che un giocatore ha letto è qualcosa che ha visto. Toglierla cancella una parte di quello che sa di un mondo in cui ha passato del tempo, e missioni e altre voci puntano all'id.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
category | sì | place, person, event, custom, thing |
title_key | sì | stringa |
body_key | sì | stringa |
chronology_index | - | intero |
citation_key | - | stringa |
content_warnings | - | elenco di stringhe |
era | - | stringa |
relates_to | - | elenco di stringhe |
requires | - | elenco di stringhe |
reveals | - | elenco di stringhe |
In un file chiamato lore.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Righe strutturate di realismo medievale, indirizzate per file e id di riga invece che per un campo id nel JSON.
- Stato Pronta all'uso
- Cartella
content/medieval_realism/structured - Resoconto
modding_mr_lines_report - Se un giocatore ti disinstalla
drop_optional_presentation. Una battuta di colore a cui non si riferisce niente. Toglierla non costa niente e tenerla mostrerebbe una stringa vuota.
Colonne. Una colonna che questa tabella non nomina è permessa, e deve essere un valore semplice invece di un elenco o di un oggetto.
| Colonna | Necessario | Valori |
|---|---|---|
line_id | sì | testo, id |
mechanical_hint | - | stringa |
public_label | - | stringa |
public_line | - | stringa |
public_summary_line | - | stringa |
speaker | - | stringa |
tone | - | stringa |
voice | - | stringa |
Ogni record ha bisogno di almeno uno fra public_line, public_label, public_summary_line.
Questi nomi vengono rifiutati senza discutere, qualunque cosa contengano: unsafe_example, unsafe_reason, audit_note, expected_block_reason, script, scene, resource_path. Alcuni sono le colonne di verifica con cui scrive chi fa il gioco e gli altri sono i nomi a forma di codice che Che cosa un mod non potrà mai fare rifiuta ovunque. Un record che ne porta uno viene rifiutato invece di essere ripulito in silenzio.
In un file chiamato MR_L03_TAVERN_INN_LINES.csv. Il nome del file è metà dell'indirizzo e l'id della riga è l'altra metà, quindi due file possono contenere lo stesso id di riga senza scontrarsi:
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
Record di progressione del giocatore: obiettivi, profili di difficoltà sicuri e profili di partita entro le regole dell'ospite.
- Stato Pronta all'uso
- Cartella
content/player/progress - Record indirizzati per il campo
id - Resoconto nessuno suo; se ne occupa
modding_preflight_report - Se un giocatore ti disinstalla
preserve_inert_reference. Gli obiettivi guadagnati e i profili di partita scelti restano nominati quando il loro pacchetto è assente; toglierli in silenzio riscriverebbe la storia del giocatore o il contratto della partita.
Campi. Questa famiglia contiene più di un tipo di record, e ogni tipo viene controllato contro il proprio elenco. Un campo che questa tabella non nomina viene rifiutato insieme al record.
Un record con kind: achievement:
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
kind | sì | achievement |
name_key | sì | stringa |
description_key | sì | stringa |
condition | sì | elenco di oggetti |
campaign | - | stringa |
hidden | - | booleano |
icon | - | banner, blade, coin, crown, hand, road, … |
Un record con kind: difficulty_profile:
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
kind | sì | difficulty_profile |
name_key | sì | stringa |
modifiers | sì | oggetto |
campaign | - | stringa |
description_key | - | stringa |
permadeath | - | booleano |
Un record con kind: run_profile:
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
kind | sì | run_profile |
name_key | sì | stringa |
difficulty | sì | stringa |
campaign | - | stringa |
description_key | - | stringa |
seed_stream | - | stringa |
starting_origin | - | stringa |
In un file chiamato progress.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Record di metadati delle missioni, indicizzati per quest_id invece che per id.
- Stato Pronta all'uso
- Cartella
content/narrative/quest_metadata - Record indirizzati per il campo
quest_id - Resoconto
modding_quest_metadata_report - Se un giocatore ti disinstalla
preserve_inert_reference. Descrive missioni che potrebbero a loro volta essere già ridotte a lapide; toglierlo le lascerebbe senza descrizione invece che assenti.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
quest_id | sì | testo, id |
arc_id | - | testo, id |
choice_valence | - | stringa |
consequence_hooks | - | elenco di stringhe |
difficulty_band | - | stringa |
faction_context | - | stringa |
failure_consequence | - | stringa |
moral_pressure | - | stringa |
notification_policy | - | stringa |
novelty_tags | - | elenco di stringhe |
player_model_tags | - | elenco di stringhe |
quest_role | - | stringa |
replay_suppression_key | - | stringa |
reward_intent | - | stringa |
story_turn_role | - | stringa |
urgency_band | - | stringa |
world_reason | - | stringa |
In un file chiamato quests.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Piani di missione come record: gli archi, le missioni, gli obiettivi e i finali che un pacchetto scrive e da cui il gioco costruisce missioni sue. La forma a record di una missione, accanto alle risorse scritte a mano invece che al loro posto.
- Stato Pronta all'uso
- Cartella
content/narrative/quest_plans - Record indirizzati per il campo
id - Resoconto
modding_quest_plan_report - Se un giocatore ti disinstalla
preserve_inert_reference. Un piano costruisce le stesse missioni che il gioco fa girare, quindi uno ritirato lascia lo stesso buco che lascerebbe una scritta a mano. Il progresso è l'unica cosa che un giocatore non può ricostruire: una missione che non si risolve viene segnalata e mai completata o cancellata in silenzio.
Campi. Questa famiglia contiene più di un tipo di record, e ogni tipo viene controllato contro il proprio elenco. Un campo che questa tabella non nomina viene rifiutato insieme al record.
Un record con kind: arc:
| Campo | Necessario | Valori |
|---|---|---|
kind | sì | qualunque |
id | sì | testo, id |
stages | sì | elenco |
description_key | - | testo, fixed shape |
name_key | - | testo, fixed shape |
Un record con kind: ending:
| Campo | Necessario | Valori |
|---|---|---|
kind | sì | qualunque |
id | sì | testo, id |
arc | sì | stringa |
requires | sì | elenco |
description_key | - | testo, fixed shape |
epilogue_key | - | testo, fixed shape |
name_key | - | testo, fixed shape |
Un record con kind: objective:
| Campo | Necessario | Valori |
|---|---|---|
kind | sì | qualunque |
id | sì | testo, id |
quest | sì | stringa |
goal | sì | collect_item, defeat_unit, defend_place, deliver_item, earn_coin, escort_unit, … |
count | - | intero da 1 a 999 |
description_key | - | testo, fixed shape |
name_key | - | testo, fixed shape |
optional_step | - | booleano |
target | - | stringa |
Un record con kind: quest:
| Campo | Necessario | Valori |
|---|---|---|
kind | sì | qualunque |
id | sì | testo, id |
name_key | sì | testo, fixed shape |
giver | sì | stringa |
objectives | sì | elenco |
deadline_days | - | intero da 1 a 3650 |
description_key | - | testo, fixed shape |
forfeits | - | elenco di qualunque cosa |
in_arc | - | stringa |
rewards | - | elenco di qualunque cosa |
In un file chiamato the_long_winter.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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"
}
]Il fixture contiene 5 record; ne sono mostrati 3.
quests
Risorse di missione scritte a mano, caricate per percorso invece che interpretate come record. Un pacchetto che vuole una missione sua scrive quest_plans.
- Stato Controllata, non ancora installata
- Cartella
content/narrative/quests - Resoconto nessuno suo; se ne occupa
modding_preflight_report - Se un giocatore ti disinstalla
preserve_inert_reference. Il progresso è l'unica cosa che un giocatore non può ricostruire. Una missione che non si risolve viene segnalata e mai completata o cancellata in silenzio.
Questa famiglia viene caricata per percorso invece che letta come record, e un pacchetto non può portare il file che vorrebbe; vedi Che cosa un mod non potrà mai fare. Scrivi invece quest_plans.
scenes
Scene messe in scena: la stanza, chi ci sta dentro e le battute che si svolgono in ordine. È l'unico contenuto che toglie i comandi al giocatore, ed è per questo che una sequenza che non arriva mai a end viene rifiutata invece che giocata. Battute e oggetti di scena sono nomi presi da elenchi pubblicati; qui non si carica nessuna scena Godot, nessuna risorsa e nessuno script.
- Stato Pronta all'uso
- Cartella
content/narrative/scenes - Record indirizzati per il campo
id - Resoconto
modding_scene_report - Se un giocatore ti disinstalla
preserve_inert_reference. Un salvataggio registra quello che una scena ha fatto — un nome scelto, una missione mossa, una porta aperta — mai il fatto che sia stata guardata. Si gioca e finisce dentro una sola sessione, quindi un pacchetto che se ne va costa la scena e mai una conseguenza dell'averla vista. Sostituirla metterebbe in scena qualcosa che l'autore non ha mai scritto sotto il nome di qualcosa che ha scritto.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
beats | sì | elenco di qualunque cosa |
cast | - | elenco di qualunque cosa |
name_key | - | qualunque |
stage | - | oggetto |
where | - | stringa |
In un file chiamato scenes.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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"
}
]
}
]Come si vede e si sente tutto quanto
7 famiglie: audio, effects, fonts, images, presentation_bindings, screens, themes.
audio
Suoni che un pacchetto porta, nominati per id: musica, ambiente, effetti e voce, ciascuno che punta a un file dentro la propria cartella e che dichiara il ruolo che lo delimita.
- Stato Validato, non viene ancora consumato da nulla
- Cartella
content/assets/audio - Record indirizzati per il campo
id - Resoconto
modding_audio_report - Se un giocatore ti disinstalla
preserve_inert_reference. Un salvataggio nomina il soggetto e mai il suono che gli sta sopra, quindi un pacchetto ritirato fra due sessioni costa un'atmosfera e non una cosa. Il riferimento viene conservato e segnalato: il silenzio senza niente che ne dica il perché è proprio lo stato che questa famiglia esiste per evitare.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
file | sì | testo, fixed shape |
codec | sì | ogg, wav |
role | sì | music, ambience, sfx, voice |
duration_seconds | - | numero, 0 o più |
sha256 | - | testo, fixed shape |
subtitle_key | - | stringa |
Nel file audio.json, che è l'unico file attraverso cui questa cartella viene letta:
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
Tempo atmosferico, polvere, scintille e luci, composti a partire dai modelli che l'ospite mette a disposizione. Un pacchetto nomina un modello e imposta parametri dentro intervalli dichiarati; non c'è nessun campo, da nessuna parte, che porti uno shader, una scena o uno script — ed è questo che permette al pacchetto di uno sconosciuto di chiedere del fuoco senza poter chiedere un programma.
- Stato Pronta all'uso
- Cartella
content/assets/effects - Record indirizzati per il campo
id - Resoconto
modding_effect_report - Se un giocatore ti disinstalla
preserve_inert_reference. Niente in un salvataggio nomina un effetto. L'aria torna a quello che disegna il gioco base quando il pacchetto se ne va, il che costa un aspetto e niente di quello che un giocatore possiede.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
template | sì | dust_drift, lightning_flash, rain_sheet, smoke_column, snow_drift, spark_burst, … |
parameters | - | oggetto |
priority | - | intero da 0 a 100 |
In un file chiamato effects.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Caratteri tipografici che un pacchetto porta, nominati per id: il file, le dimensioni a cui vengono disegnati, e le lingue di cui portano i glifi. La copertura si dichiara invece di essere scoperta, perché un carattere a cui mancano i glifi di una lingua non fallisce: disegna dei quadratini, e la schermata si legge come una traduzione lasciata a metà da qualcuno.
- Stato Validato, non viene ancora consumato da nulla
- Cartella
content/assets/fonts - Record indirizzati per il campo
id - Resoconto
modding_font_report - Se un giocatore ti disinstalla
preserve_inert_reference. Niente in un salvataggio nomina un carattere. L'interfaccia torna al carattere del toolkit quando il pacchetto se ne va, che è l'unico che nessun autore ha dovuto scegliere.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
file | sì | testo, fixed shape |
format | sì | ttf, otf |
sizes | sì | elenco di interi da 8 a 96 |
covers | sì | elenco |
fallback_font | sì | stringa |
glyphs | - | elenco |
oversampling | - | intero da 1 a 4 |
sha256 | - | testo, fixed shape |
Nel file fonts.json, che è l'unico file attraverso cui questa cartella viene letta:
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
Immagini che un pacchetto porta, nominate per id: icone, ritratti e fogli di sprite, ciascuna che punta a un file dentro la propria cartella.
- Stato Pronta all'uso
- Cartella
content/assets/images - Record indirizzati per il campo
id - Resoconto
modding_image_report - Se un giocatore ti disinstalla
preserve_inert_reference. Un salvataggio nomina oggetti e persone, mai l'immagine di uno di loro, quindi un'immagine che smette di risolversi costa un disegno e non una cosa. Il riferimento viene conservato e segnalato: sostituirlo con l'arte di un altro pacchetto mostrerebbe al giocatore qualcosa che nessun autore ha scelto, e togliere l'id in silenzio farebbe sembrare l'icona mancante un difetto di disegno.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
file | sì | testo, fixed shape |
format | sì | png, webp |
frame_columns | - | intero da 1 a 256 |
frame_rows | - | intero da 1 a 256 |
sha256 | - | testo, fixed shape |
Nel file images.json, che è l'unico file attraverso cui questa cartella viene letta:
a images record, under content/assets/images
[
{
"id": "northern_reach:salt_pouch",
"file": "salt_pouch.png",
"format": "png"
}
]presentation_bindings
Quale risorsa del pacchetto riempia quale slot su quale soggetto: l'icona su un oggetto, lo sprite su un'unità o un tassello, lo stendardo su una fazione, tanto per il contenuto del pacchetto quanto per quello del gioco base.
- Stato Pronta all'uso
- Cartella
content/presentation/bindings - Record indirizzati per il campo
id - Resoconto nessuno suo; se ne occupa
modding_preflight_report - Se un giocatore ti disinstalla
preserve_inert_reference. Un salvataggio nomina il soggetto — l'oggetto, la persona, il tassello — e mai quale immagine lo vestisse, quindi un collegamento che smette di risolversi costa un disegno e non una cosa. Il riferimento viene conservato e segnalato: il soggetto torna all'arte che la build aveva già, che è l'unica risposta che nessun autore ha dovuto scegliere.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
subject | sì | testo, id |
kind | sì | building, faction, interface, item, region, tile, … |
slot | sì | ambience, banner, effect, font, icon, portrait, … |
cue | sì | testo, id |
alternative_key | - | stringa |
In un file chiamato bindings.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Disposizioni di schermata: quali sezioni stiano in quale pannello di una schermata che il gioco ha già, e in che ordine. Dispone pezzi che questa build disegna e non può aggiungerne uno: una schermata nuova avrebbe bisogno di widget, sorgenti di dati e gestori di clic, che insieme sono un linguaggio di programmazione.
- Stato Pronta all'uso
- Cartella
content/ui/screens - Record indirizzati per il campo
id - Resoconto
modding_screen_report - Se un giocatore ti disinstalla
preserve_inert_reference. Niente in un salvataggio nomina una disposizione. Decide come viene disegnata una pagina mentre il pacchetto è caricato, e la pagina torna alla disposizione che questa build porta con sé quando se ne va: costa un aspetto e niente di quello che un giocatore possiede.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
screen | sì | character_sheet |
panels | sì | oggetto |
In un file chiamato screens.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Tavolozze dell'interfaccia come gettoni: colori con un nome, dimensioni e spaziature, con le coppie il cui contrasto un giocatore deve poter leggere. Mai una scena, uno script o un percorso di risorsa.
- Stato Pronta all'uso
- Cartella
content/assets/themes - Record indirizzati per il campo
id - Resoconto
modding_theme_report - Se un giocatore ti disinstalla
preserve_inert_reference. Niente in un salvataggio nomina un tema. L'interfaccia torna ai colori del toolkit quando il pacchetto se ne va, che è l'unica tavolozza che nessun autore ha dovuto scegliere.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
id | sì | testo, id |
tokens | sì | oggetto |
contrast_pairs | - | elenco di oggetti |
In un file chiamato themes.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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"
}
]
}
]Che cosa controlla il giocatore, e che cosa lo osserva
3 famiglie: adaptive, input_bindings, settings.
adaptive
Profili che guardano come sta andando una partita e ne suggeriscono un'impostazione diversa. Il risultato è un consiglio e mai un cambiamento: un profilo che potesse agire sarebbe l'unica cosa che un pacchetto porta capace di alterare una partita senza che il giocatore o l'ospite l'abbiano chiesto, e in un diff sembrerebbe esattamente una tabella di regolazioni. Gli ingressi sono un elenco pubblicato di aggregati di gioco, ciascuno un conteggio o una media che la partita già tiene su se stessa.
- Stato Pronta all'uso
- Cartella
content/player/adaptive - Record indirizzati per il campo
id - Resoconto
modding_adaptive_report - Se un giocatore ti disinstalla
drop_optional_presentation. Nessun salvataggio nomina un profilo. Quello che un profilo ha toccato è un moltiplicatore ricalcolato dai mutatori attivi ogni volta che cambiano, quindi un pacchetto ritirato smette di essere consultato e la partita torna esattamente a quello che il giocatore aveva scelto. Non si conserva niente, quindi non c'è niente da preservare.
Campi. Questa famiglia contiene più di un tipo di record, e ogni tipo viene controllato contro il proprio elenco. Un campo che questa tabella non nomina viene rifiutato insieme al record.
Un record con kind: adaptive_profile:
| Campo | Necessario | Valori |
|---|---|---|
kind | sì | qualunque |
id | sì | testo, id |
name_key | sì | testo, fixed shape |
policy | sì | enemy_composition, event_cadence, hint_frequency, pace_economy, pace_encounters, weather_variety |
reads | sì | elenco |
fallback_policy | sì | enemy_composition, event_cadence, hint_frequency, pace_economy, pace_encounters, weather_variety |
confidence_floor_percent | - | intero da 1 a 100 |
description_key | - | testo, fixed shape |
sample_days | - | intero da 1 a 365 |
Un record con kind: threshold_set:
| Campo | Necessario | Valori |
|---|---|---|
kind | sì | qualunque |
id | sì | testo, id |
profile | sì | testo, id |
thresholds | sì | elenco di oggetti |
description_key | - | testo, fixed shape |
name_key | - | testo, fixed shape |
In un file chiamato adaptive.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Azioni proprie di un pacchetto, con il tasto che vorrebbero. Decide il giocatore: un suggerimento che finisce su una combinazione che aveva già assegnato perde, e l'azione arriva senza tasto, perché un tasto che fa in silenzio un'altra cosa è peggio di un tasto che non fa niente.
- Stato Pronta all'uso
- Cartella
content/input - Record indirizzati per il campo
action_id - Resoconto
modding_input_report - Se un giocatore ti disinstalla
preserve_inert_reference. La riassegnazione di un giocatore resta archiviata sotto l'id dell'azione, così reinstallare il pacchetto ritrova il tasto dove l'aveva messo. L'azione in sé viene tolta dalla mappa dei comandi quando il pacchetto se ne va, così la schermata delle assegnazioni non elenca mai qualcosa a cui non risponde niente.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
action_id | sì | testo, id |
label_key | sì | stringa |
context | sì | exploration, combat, menu, global |
suggested_keyboard | sì | stringa |
suggested_controller | - | stringa |
In un file chiamato bindings.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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
Opzioni che un giocatore può cambiare, dichiarate invece che disegnate. Un pacchetto dice qual è l'opzione, che valori può avere e dove vive il valore; il controllo lo costruisce l'ospite. Niente di quello che attraversa questo confine è un Control o uno script, ed è l'unica ragione per cui un menu delle impostazioni può mostrare le opzioni di uno sconosciuto senza eseguirne il codice.
- Stato Pronta all'uso
- Cartella
content/settings - Record indirizzati per il campo
key - Resoconto
modding_settings_report - Se un giocatore ti disinstalla
preserve_inert_reference. Un valore memorizzato resta sotto la sua chiave, così reinstallare il pacchetto ritrova la scelta del giocatore dove l'aveva lasciata. Quello che il pacchetto si lascia dietro è una riga in un profilo che nessuno legge: non costa niente e conserva una scelta che il giocatore ha fatto.
Campi. Un campo che questa tabella non nomina viene rifiutato insieme al record.
| Campo | Necessario | Valori |
|---|---|---|
key | sì | testo, id |
type | sì | bool, int, float, string, enum |
default | sì | qualunque |
scope | sì | installation, campaign, presentation |
label_key | sì | stringa |
help_key | - | stringa |
max_length | - | intero da 1 a 4096 |
maximum | - | numero |
migrates_from | - | testo, id |
minimum | - | numero |
options | - | elenco di stringhe |
requires_restart | - | booleano |
secret | - | booleano |
In un file chiamato settings.json, o con qualunque altro nome .json ti piaccia dentro quella cartella:
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"
}
]Scorciatoie da console
Queste sono una scorciatoia, non un passaggio. Tutto quello che c'è qui sotto ha un posto sulla schermata Mod, che è dove passa la strada normale e dove guarderà chi ha scaricato il tuo pacchetto. La console è più rapida quando stai iterando ed è già aperta, ed esiste solo in una build di debug: una copia pubblicata del gioco non ha nessuna console, quindi niente di ciò che serve all'autore di un pacchetto può vivere solo qui.
| Comando | La stessa cosa sulla schermata Mod |
|---|---|
modding_open_folder | il percorso in cima, e il pulsante accanto |
modding_manifest_report | la colonna dello stato, e la riga sotto ciascuna riga |
modding_<family>_report | i conteggi sotto ogni pacchetto, e Mostra i dettagli |
modding_preflight_report | Verifica compatibilità |
modding_roots_report, modding_safety_report | Copia il resoconto |
modding_reload | Nessun pulsante sulla schermata. Riavviare il gioco fa la stessa cosa ed è l'unica strada che ha una build pubblicata; questo ti risparmia il riavvio mentre iteri. È l'unica riga qui che è una comodità invece che una scorciatoia per qualcosa che la schermata già fa. |
Comincia da modding_manifest_report — il gioco vede il tuo pacchetto, e in che stato? — poi modding_preflight_report per un verdetto unico su tutto quello che è installato. Poi il resoconto della singola famiglia.
modding_reload rilegge i tuoi file senza riavviare. Modifica, fai Alt-Tab, digita il comando e guarda. Ricostruisce ciò che nulla sta trattenendo — binding, effetti e immagini — e nomina ogni famiglia lasciata intatta, perché una partita poggia sui record che un salvataggio può nominare:
what the game prints back
HELD BY THE RUN items: edited files are read on the next loadmodding_reload all rilegge tutto ed è per una schermata iniziale senza nessuna partita in corso. modding_condition_report stampa a che cosa il gioco sa rispondere adesso per un when, e a che cosa no.
| Comando | Che cosa ti dice |
|---|---|
modding_roots_report | Radici e impronte dei mod di dati |
modding_manifest_report | Stati dei mod (attivo/non valido/ignorato/in conflitto) |
modding_fingerprint_report | Impronte deterministiche dei salvataggi (save_wired=no) |
modding_safety_report | Postura di sicurezza (mod di comportamento spenti, file bloccati) |
modding_preflight_report | Verdetto VERDE/ROSSO sull'insieme dei mod attivi |
modding_packaging_report | Rilevamento PCK/ZIP di livello 2 (disattivato per impostazione predefinita) |
modding_campaign_report | Modding_campaign_report [id] - campagne installate in sola lettura; con un id, ci si passa |
modding_condition_report | Che cosa pubblica il mondo per le condizioni dei record |
modding_reload | Modding_reload [all] - rilegge i pacchetti; all solo se non c'è nessuna partita in corso |
modding_binding_report | Collegamenti di presentazione: legati/rifiutati/scavalcati |
modding_open_folder | Crea (se serve) e apre la cartella dei mod dell'utente |
Strumenti offline
Questi strumenti sono per autori e automazione delle pubblicazioni. Sono inclusi nel checkout pubblico di Bonemark; ai giocatori che installano un mod pubblicato non servono Python né Godot. Se scrivi un mod, clona la build corrispondente da github.com/tallowgames/Bonemark, tieni il pacchetto di lavoro fuori dalla cartella mods del giocatore ed esegui da questo checkout i comandi seguenti. Il gioco resta l'autorità finale del runtime.
Python 3.10 o più recente; Godot solo per la corsia di runtime. Tieni il tuo pacchetto fuori dalla cartella mods del giocatore e prova una copia.
a command line
python tools/modding/new_mod.py --list
python tools/modding/new_mod.py --id my_mod --family goods --family itemsScrive un pacchetto che passa la convalida prima ancora che tu abbia scritto qualcosa: un mod.json già compilato, un record funzionante per ogni famiglia che hai chiesto, e un README con i due comandi successivi. I record vengono dai fixture che la build già controlla per quelle famiglie, quindi uno starter che smette di funzionare fa fallire lo stesso controllo che fa fallire il fixture, invece di marcire dentro un modello. Si rifiuta di scrivere dentro una cartella chiamata 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>"Controlla mod.json, le cartelle di famiglia, gli id, gli schemi, i riferimenti, i limiti e i payload bloccati. --strict trasforma gli avvisi in fallimenti.
Confronta la superficie di modding con versione
Quando il gioco cambia, confronta l'istantanea della superficie archiviata prima di aggiornare un pacchetto. Contiene un digest più i campi e le operazioni per ogni famiglia pubblica, quindi il risultato indica quale famiglia è cambiata e perché:
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 differenza è unchanged, additive o breaking. I motivi di rottura sono espliciti: field_removed, required_added, type_changed, default_changed, constraint_changed, operation_removed e root_changed, format_changed, id_field_changed, catalogue_changed, family_removed e contract_major_changed_without_new_id. Nome modifiche compatibili field_added, required_removed, operation_added o family_added. Il comando senza --before controlla anche la baseline archiviata. Se la superficie corrente si è spostata, l'audit fallisce finché un manutentore non esamina gli esatti digest prima/dopo in tools/quality/modding_surface_contract_changes.json; una modifica di rottura deve inoltre registrare ogni motivo, la decisione, la nota di migrazione e il revisore. La promozione di uno snapshot intenzionalmente rivisto è esplicita:
a command line
python tools/quality/modding_surface_contract.py --write-baselineQuesto è un controllo del manutentore/rilascio; gli autori di mod necessitano solo del confronto --before e i giocatori che installano un pacchetto rilasciato non hanno bisogno di eseguirlo.
a command line
python tools/modding/mod_test_host.py --root "<mod-root>" --repo-root "<framework-root>" --jsonLegge il manifesto, le dipendenze, la compatibilità e l'ordine di caricamento senza avviare Godot e senza eseguire niente del tuo pacchetto.
Non apre mai un file di contenuto. Questa è la divisione del lavoro: l'host risponde questi pacchetti verranno caricati insieme, il validatore risponde questo record è corretto - ma significa che un pacchetto che il validatore rifiuta può comunque comporre in modo pulito qui. Misurati su quattordici pacchetti deliberatamente rotti, i due non sono d'accordo su ogni rifiuto: l'host li mette in scena tutti e quattordici, refused vuoti, compreso uno che trasporta scripts/payload.sh che solo il validatore trova. Comporre non equivale ad installare in sicurezza. Esegui entrambi prima di pubblicare. Ripeti --root quando il set di test è suddiviso in cartelle; l'host compone quindi l'insieme completo in un piano deterministico.
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"Fa girare il validatore, l'host di prova, il fixture di ogni famiglia pronta all'uso e la corsia di runtime di Godot. Togli --require-runtime se non hai Godot; il resoconto dirà allora che la prova a runtime è stata saltata, non superata.
Per un insieme composto, ripetere l'opzione:
a command line
python tools/modding/mod_test_matrix.py --repo-root "<framework-root>" --root "<mod-a>" --root "<mod-b>" --godot "<godot-exe>" --require-runtimeIl rapporto conserva un risultato per radice e aggiunge composed_set per il set completo. Questo blocco è il luogo in cui vengono dimostrati conflitti tra pacchetti, ID duplicati ed errori di dipendenza. Un pacchetto pulito da solo non è la prova che il set verrà caricato insieme. Il rapporto include anche surface_contract, l'attuale versione del contratto per famiglia e l'audit digest, quindi una matrice non può essere verde mentre l'istantanea di compatibilità del repository è obsoleta. Con --require-runtime, leggi runtime.reachability.loaded_families e runtime.reachability.reachable_families. Il primo dice che i record composti sono stati caricati; il secondo viene popolato solo quando un vero percorso rivolto ai giocatori nella sonda Godot li ha consumati. runtime.reachability.observations mantiene il pacchetto, la famiglia, l'ID record, il percorso e lo stato per ogni riga, mentre unreachable elenca le righe caricate che non hanno ancora alcun percorso. Una famiglia può essere convalidata e messa in scena ma essere ancora assente da reachable_families: "caricato" non è la stessa cosa di "un giocatore può raggiungerlo".
Ogni comando qui sopra viene controllato contro gli strumenti stessi mentre questa pagina viene costruita: lo script deve esistere e ogni opzione deve essere una che accetta.
Ogni codice diagnostico
Non leggere questo elenco in ordine. Sta qui perché un codice che incontri in un resoconto sia una domanda con una risposta — una parolina in minuscolo come asset_missing. Incollane uno nella casella di ricerca in cima a questa pagina.
Alcuni codici appartengono a meccanismi che un pacchetto non può ancora raggiungere. Sono qui lo stesso: un codice che non puoi far scattare costa una riga che non leggerai mai, e un codice che manca costa una serata.
| Codice | Che cosa l'ha causato | Che cosa fare |
|---|---|---|
adaptive_brings_a_model | Un pacchetto che prova a caricare qualcosa o a raggiungere qualche posto. | Togli il percorso o l'indirizzo e scegli per nome una politica pubblicata. Qui non si carica nessun file che tu abbia portato. |
adaptive_fell_back | Un profilo che non ha raggiunto il suo pavimento e ha usato la politica che aveva dichiarato. | Niente da sistemare, a meno che non la smetta mai. Il profilo non aveva abbastanza segnali fra quelli che legge, quindi ha usato la politica che aveva dichiarato come ripiego. |
adaptive_invalid | Il record non è uno di quelli che questa build caricherebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
adaptive_over_budget | Un pacchetto oltre un tetto dichiarato. | Il resoconto stampa quello che è stato misurato accanto a quello che era permesso. Dividi il record, oppure togli le voci oltre la riga: il tetto è quello che una schermata o un lettore possono reggere, non un suggerimento. |
adaptive_text_not_key | Una frase dove ci vuole una chiave di catalogo. | Sposta la frase nel tuo catalogo di lingua e metti la sua chiave nel campo. Un campo che finisce in _key contiene una chiave; una frase lì dentro porta il tuo pacchetto in una sola lingua per sempre. |
adaptive_unknown_step | Una politica, un segnale o una direzione che questa build non ha. | Il nome non è nell'elenco pubblicato per quella tabella. Scegline uno che ci sia: l'elenco è corto perché ogni voce è qualcosa che questa build fa già. |
adaptive_unresolved_reference | Un record nominato che nessuno fornisce. | L'id nominato è uno che niente nella composizione fornisce. O porti il record a cui punta, o dipendi dal pacchetto che lo porta. |
assembly_dangling_reference | Una scala, una porta o un ingresso nominano qualcosa che questa mappa non contiene. | Aggiungi a questa mappa l'oggetto nominato, oppure correggi l'id. Una scala il cui pianerottolo non è nella mappa è un piano in cui il giocatore può entrare e da cui non può uscire, e un edificio il cui ingresso non è un passaggio è una porta disegnata su un muro. Le due estremità devono stare nello stesso file. |
assembly_leaked | Lo smontaggio ha rilasciato meno nodi di quanti ne avesse presi il montaggio. | Niente da sistemare nel tuo pacchetto, e niente in un pacchetto può causarlo. Lo smontaggio ha rilasciato meno nodi di quanti ne avesse presi il montaggio, quindi qualcosa sta trattenendo una parte della mappa precedente: scrivilo insieme alla mappa che l'ha prodotto. Si vede come memoria che cresce ogni volta che si entra nello stesso posto. |
assembly_missing_aspect | Una parte obbligatoria della disposizione non ha prodotto niente, quindi nella mappa non ci si può stare. | Aggiungi la parte mancante sul suo livello ed esporta di nuovo. Il messaggio dice quale: i rettangoli calpestabili vanno sul livello walkable, i collisori su collision, e il livello dei tasselli del terreno deve coprire la mappa. Una mappa senza niente di calpestabile è un posto in cui il giocatore può entrare e non muoversi, quindi viene rifiutata invece che pubblicata. |
assembly_over_budget | La forma assemblata è oltre un tetto dichiarato. | Togli una parte di quello che il messaggio ha contato, oppure dividi la mappa. Il tetto si misura su quello che è stato assemblato e non sulla dimensione del file, quindi comprimere i livelli non cambia niente: il numero nel messaggio è quello che la macchina avrebbe dovuto tenere. |
assembly_refused | Non è stato costruito niente, perché costruire mezza mappa è peggio che non costruirne nessuna. | Sistema ogni altro messaggio di questa corsa ed esporta di nuovo. Non è stato costruito niente, di proposito: mezza mappa è una stanza in cui entri senza pareti, e non ci sarebbe modo di sapere quale metà è arrivata. |
assembly_unreachable_affordance | Un ancoraggio sta dove niente è dichiarato calpestabile, quindi nessuno può raggiungere quello che offre. | Disegna un rettangolo calpestabile che tocchi l'ancoraggio nominato dal messaggio, sullo stesso piano. Un ancoraggio è la cosa in sé e l'attore ci sta accanto, quindi un bancone tutto dentro un'area calpestabile è un bancone che il giocatore attraversa, e un bancone senza niente intorno è un servizio che nessuno può raggiungere. Controlla prima la proprietà del piano: un ancoraggio al piano di sopra non è servito dalla stanza sotto. |
asset_invalid | Un descrittore esiste e questa build lo rifiuta. Il verdetto dice quale regola. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
asset_kind_mismatch | Chi ha chiamato ha chiesto un tipo e il descrittore ne dichiara un altro. Risolverlo lo stesso consegnerebbe una texture a qualcosa che si aspetta un suono. | Lega una risorsa del tipo che lo slot prende. Nessuno disegna un ritratto per una regione, quindi il collegamento non verrebbe mai disegnato e niente ne direbbe il perché. |
asset_missing | Il pacchetto è installato e non dichiara nessun descrittore sotto quell'id. | L'id della risorsa non si risolve in niente nella composizione. Porta il file, oppure fai puntare il collegamento a uno che il tuo pacchetto contiene davvero. |
asset_package_missing | Nessun pacchetto installato risponde allo spazio dei nomi che l'id nomina. | Il pacchetto che forniva questa risorsa non è installato. Reinstallalo, oppure rilega lo slot a qualcosa che stia in un pacchetto installato. |
audio_cue_refused | Un suono o una scaletta che questa build non registra. | Leggi la regola nominata accanto al codice e ricodifica per rispettarla. Le cause solite sono un formato che non decodifichiamo e una durata oltre il tetto dichiarato. |
audio_placeholder_used | Un suono rifiutato o mancante si è risolto nel sostituto riservato, e chi ha chiamato è stato avvisato. | Niente da sistemare, se l'avevi voluto tu. Il suono mancava, quindi ha suonato il sostituto del suo tipo e la sostituzione è stata segnalata invece di essere lasciata in silenzio. |
audio_refused | Un suono che questa build non riproduce. Il verdetto dice quale regola. | Il file audio in sé è stato rifiutato prima che qualcosa lo riproducesse. Ricodificalo in un formato dichiarato entro la dimensione dichiarata, e tieni la frequenza di campionamento fra quelle dell'elenco pubblicato. |
audio_stream_overran | Un flusso che è andato oltre la durata dichiarata dal suo descrittore, fermato al limite. | Il flusso è più lungo di quanto il suo slot permetta. Accorcialo, oppure spostalo in uno slot il cui budget lo copra: un flusso che sfora è un flusso che il mixer deve tagliare a metà parola. |
binding_invalid | Un collegamento che questa build non fa. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
binding_missing_alternative | Informazione che un giocatore non può ricevere, senza nient'altro che la porti. | Un ritratto e un'icona hanno bisogno di una chiave di descrizione, e una battuta parlata di una chiave di sottotitolo. Aggiungi l'alternativa: è l'unica regola di accessibilità che un giocatore sente direttamente. |
binding_over_budget | La presentazione di un pacchetto oltre quello che uno dei totali permette. | Il resoconto stampa quello che è stato misurato accanto a quello che era permesso. Dividi il record, oppure togli le voci oltre la riga: il tetto è quello che una schermata o un lettore possono reggere, non un suggerimento. |
binding_placeholder_used | Un suono che nessuno fornisce, risolto nel sostituto del suo tipo. | Niente da sistemare, se l'avevi voluto tu. Il collegamento si è risolto nel sostituto del tipo di risorsa del suo slot, e il resoconto dice quale slot, così puoi distinguere una decisione da una dimenticanza. |
boot_attempt_recorded | Un tentativo è stato scritto prima che la composizione cominciasse. | Niente da sistemare. L'avvio è stato messo per iscritto prima di essere tentato, ed è quello che permette all'avvio successivo di sapere che qualcosa era andato storto. |
boot_last_known_good_offered | Viene offerto invece un profilo che in passato si era avviato. | La composizione che ha fallito non è quella che funzionava, quindi è stata offerta l'ultima che funzionava. Prendila, poi reinstalla i pacchetti uno alla volta per trovare quello che ha rotto tutto. |
boot_marker_unwritable | Il tentativo non è stato registrato. Il gioco si avvia con il recupero disattivato per questa sessione e lo dice. | Il segnalibro di avvio non si è potuto scrivere, quindi la prossima volta non si potrà distinguere un crash da un'uscita pulita. Controlla che la cartella dei dati del gioco sia scrivibile; non riguarda il tuo pacchetto. |
boot_package_rejected | Un pacchetto è stato rifiutato durante il recupero. Viene registrato l'id, mai il percorso. | Questo pacchetto ha impedito al gioco di avviarsi ed è stato lasciato fuori. Il resoconto nomina il rifiuto; sistemalo e reinstalla, oppure lascialo fuori. |
boot_retry_offered | Sotto il limite; si riprova lo stesso profilo. | Accetta il nuovo tentativo. Se fallisce anche il secondo avvio, il problema è la composizione e non il momento, e l'offerta successiva sarà la modalità sicura. |
boot_safe_mode_offered | Il limite è esaurito; il gioco propone di avviarsi senza nessun pacchetto. | Accetta la modalità sicura, poi togli i pacchetti uno alla volta finché non parte. Il tuo salvataggio non viene toccato: la modalità sicura lo legge e non ci scrive mai sopra. |
budget_aggregate_exceeded | L'insieme installato ha superato il limite condiviso. Il pacchetto nominato è quello che l'ha superato, in ordine di caricamento. | Togli qualcosa dalla composizione. Sono tutti i pacchetti insieme a essere oltre il tetto, non il tuo da solo, e il resoconto stampa il totale accanto al limite. |
budget_degraded | Una dimensione è stata ridotta invece che rifiutata, e viene nominato su che cosa è ripiegata. | Niente da sistemare, a meno che tu non intendessi altro. La composizione è rimasta dentro il suo budget rinunciando alla qualità e non al contenuto: non manca niente, qualcosa è più piccolo. |
budget_package_exceeded | Un pacchetto ha superato il proprio limite su una dimensione. | Leggi la dimensione nominata nel resoconto e taglia quello che misura. Stampa quanto ha usato il tuo pacchetto accanto a quanto è permesso a un pacchetto solo. |
budget_soft_warning | Oltre la soglia morbida, caricato lo stesso, segnalato a chi crea. | Niente da sistemare per ora. Sei abbastanza vicino a un tetto che un altro pacchetto lo supererebbe, ed è utile saperlo prima che lo faccia quello di qualcun altro. |
budget_unknown_dimension | È stato segnalato un consumo su una dimensione che questa build non dichiara, cioè qualcuno che scrive contro una superficie che non esiste. | Il budget nomina qualcosa che questa build non misura. Scegli una dimensione dall'elenco pubblicato: una che non misuriamo non verrebbe mai fatta rispettare. |
budget_unknown_profile | Un profilo che questa build non dichiara. Viene applicato il profilo più severo invece del più largo. | Scegli un profilo di budget dall'elenco pubblicato. I profili si scelgono invece di essere descritti, quindi uno che non pubblichiamo è uno che nessuno farebbe rispettare. |
campaign_hardcoded_identity | Un consumatore ha scritto per esteso l'id della campagna base invece di chiedere quale campagna sia selezionata. | Qualcosa è andato a prendere per nome l'id, il testo o la scena della campagna base invece di chiederlo alla campagna selezionata. Risolvilo attraverso il contesto della campagna, altrimenti una conversione riceve la risposta di questo mondo al posto di quella del suo. |
campaign_invalid | La dichiarazione non è una di quelle che questa build selezionerebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
campaign_not_found | È stata selezionata una campagna per id e nessuna dichiarazione risponde a quell'id. | L'id di campagna nominato non è installato. Controlla come l'hai scritto, oppure installa il pacchetto che lo fornisce: qui non si ripiega sulla campagna base. |
character_carries_handler | Dati pubblici che nominano un simbolo privato. | Togli il campo che nomina un metodo o una callback. Pubblicare un simbolo interno lo rende un contratto pubblico, e la rinomina che lo rompe i giocatori la segnalano come il gioco che si rompe. |
character_invalid | Il record non è uno di quelli che questa build caricherebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
character_origin_missing | Un personaggio la cui origine non è fornita da nessuno, caricato con il ripiego. | Reinstalla il pacchetto che ha scritto questa origine. Il personaggio si è caricato con il ripiego riservato e l'id che ha perso viaggia con lui, quindi reinstallare lo rimette esattamente com'era. |
character_tree_unenterable | Un ciclo o un nodo irraggiungibile in un albero di progressione. | Guarda se il resoconto dice ciclo o orfano e ricollega quella parte dell'albero. Nessuno dei due è un errore mentre si gioca: l'opzione semplicemente non viene mai offerta e il file sembra corretto. |
character_unknown_property | Una proprietà che non significherebbe niente per nessun sistema. | Usa una proprietà che questa build ha. Accettarne una che non ha metterebbe nel salvataggio un campo che non significa niente per nessun sistema e non si spiega a nessuno, per sempre. |
combat_carries_formula | Un pacchetto che prova a fornire l'aritmetica di uno scontro. | Togli il campo. Il livello 1 sono dati: quello che viene eseguito appartiene al gioco, e le funzionalità nuove passano da un fornitore fidato. |
combat_effect_expired | Uno stato salvato la cui taratura è sparita, terminato al caricamento. | Il pacchetto che tarava questo stato non è più installato, quindi lo stato è finito invece di essere applicato con numeri che nessuno ha. Reinstallalo per tenerlo. |
combat_invalid | Il record non è uno di quelli che questa build caricherebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
combat_over_budget | Un pacchetto oltre un tetto dichiarato. | Il resoconto stampa quello che è stato misurato accanto a quello che era permesso. Dividi il record, oppure togli le voci oltre la riga: il tetto è quello che una schermata o un lettore possono reggere, non un suggerimento. |
combat_phase_unreachable | Una fase scritta e mai raggiunta. | Due fasi condividono una soglia, quindi una delle due non partirebbe mai. Dài loro valori di salute residua diversi. |
combat_unknown_operation | Un'operazione o un parametro che il risolutore non ha. | Scegli l'operazione dall'elenco pubblicato e dàlle solo i suoi parametri. Uno spintone che porta un valore è una riga letta male, non uno spintone più forte. |
combat_unknown_status | Uno stato che questa build non pubblica. | Tara uno stato che questa build pubblica invece di inventarne uno. Uno stato inventato sta su un'unità dietro un'icona vuota e non c'è niente che lo tolga. |
combat_unresolved_reference | Un record nominato che nessuno fornisce. | L'id nominato è uno che niente nella composizione fornisce. O porti il record a cui punta, o dipendi dal pacchetto che lo porta. |
conversion_external_reference | Un indirizzo o un percorso che va fuori dal pacchetto. | Una conversione ha puntato fuori dal proprio pacchetto. Porta con te quello a cui fai riferimento, altrimenti il mondo va a pescare in uno che non hai scritto tu. |
conversion_fallback_allowed | Una conversione che non ha negato il ripiego sul gioco base, né nel manifesto né nella campagna. | Niente da sistemare. Questa famiglia può ricadere sul gioco base, e la riga dice perché non sia una fuga. |
conversion_family_unclassified | Una famiglia di contenuto esiste e questo catalogo non la classifica. | Dichiara la famiglia come posseduta dalla campagna o dal motore. Una famiglia non classificata è una su cui la verifica delle fughe dal gioco base non può ragionare per niente. |
conversion_missing_file | Un file che il fixture dichiara e non ha. | Un file obbligatorio che la conversione ha dichiarato non è nel pacchetto. Portalo: una conversione a cui manca una parte di sé parte e poi non può proseguire. |
conversion_partial_atomic_family | Una famiglia atomica è stata fornita solo in parte. Rifiutata invece che pubblicata con la cucitura in vista. | Porta la famiglia intera o non portarla affatto. Mezzo elenco di missioni è un mondo che si riferisce a missioni che nessuno ha scritto. |
conversion_required_family_missing | Una famiglia posseduta dalla campagna che la conversione doveva fornire è assente. | Porta la famiglia. Il catalogo dice quali sono obbligatorie per una conversione, e senza di esse il mondo è il gioco base con dell'arte nuova. |
conversion_unclaimed_family | Una famiglia per cui il pacchetto fornisce dei file e che la campagna non reclama. | Reclama la famiglia in un pacchetto, oppure dichiarala rimandata con una ragione. Lasciata non reclamata, niente dice se la sua assenza fosse voluta. |
conversion_unknown_family | La campagna ha dichiarato una famiglia che questa build non conosce. | Nomina una famiglia dal catalogo dei tipi di contenuto. Le famiglie si dichiarano lì prima che qualcuno possa fornirne una. |
conversion_vanilla_leak | Un id che non appartiene né alla conversione né allo spazio dei nomi riservato del motore. | Sostituisci l'id, il testo o la scena che il resoconto nomina. Questa conversione nega il ripiego, quindi l'alternativa è che il giocatore veda questo mondo dentro quell'altro. |
dialogue_carries_expression | Un pacchetto che prova a eseguire qualcosa, o a scrivere le parole sul posto. | Togli il campo. Il livello 1 sono dati: quello che viene eseguito appartiene al gioco, e le funzionalità nuove passano da un fornitore fidato. |
dialogue_dead_end | Una conversazione da cui un giocatore non può uscire. | Fai puntare un'opzione da questo nodo verso un percorso che arriva a una fine. Un ciclo va bene; un ciclo senza uscita è una conversazione da cui il giocatore non può uscire. |
dialogue_invalid | Il record non è uno di quelli che questa build caricherebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
dialogue_orphan_node | Un nodo a cui non può arrivare niente. | A questo nodo non va niente, quindi nessun giocatore lo leggerà. Fagli puntare contro un'opzione, oppure cancellalo. |
dialogue_over_budget | Un pacchetto oltre un tetto dichiarato. | Il resoconto stampa quello che è stato misurato accanto a quello che era permesso. Dividi il record, oppure togli le voci oltre la riga: il tetto è quello che una schermata o un lettore possono reggere, non un suggerimento. |
dialogue_text_not_key | Una frase dove ci vuole una chiave di catalogo. | Sposta la frase nel tuo catalogo di lingua e metti la sua chiave nel campo. Un campo che finisce in _key contiene una chiave; una frase lì dentro porta il tuo pacchetto in una sola lingua per sempre. |
dialogue_unguarded_reveal | Un segreto senza niente davanti. | Metti almeno una condizione sul nodo. Un elenco di condizioni vuoto conta come nessuna: il segreto andrebbe a chiunque apra la conversazione. |
dialogue_unknown_step | Un controllo o un comando che questa build non ha. | Il nome non è nell'elenco pubblicato per quella tabella. Scegline uno che ci sia: l'elenco è corto perché ogni voce è qualcosa che questa build fa già. |
dialogue_unresolved_reference | Un record nominato che nessuno fornisce. | L'id nominato è uno che niente nella composizione fornisce. O porti il record a cui punta, o dipendi dal pacchetto che lo porta. |
distribution_hash_mismatch | I file sul disco non sono quelli che il record descrive. | Il pacchetto sul disco non è quello che era stato pubblicato. Riscaricalo: una discordanza è un trasferimento andato male oppure un file che qualcun altro ha cambiato. |
distribution_invalid | Il record non è uno di quelli che questa build accetterebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
distribution_offline | La provenienza è stata controllata contro quello che era stato registrato al momento dell'installazione. | Controlla la connessione, poi riprova. I pacchetti già installati continuano a funzionare; quelli nuovi non si possono verificare finché il servizio non torna. |
distribution_reported | Qualcuno l'ha segnalato. Il giocatore viene avvisato e decide. | Leggi la segnalazione e decidi. Il pacchetto funziona lo stesso: la segnalazione esiste perché la decisione si prenda avendola davanti, non al suo posto. |
distribution_revoked | Il pacchetto è in quarantena o ritirato. Non si installa. | Togli il pacchetto. È stato ritirato dopo la pubblicazione e non viene caricato; se l'hai scritto tu, l'avviso di revoca dice perché. |
distribution_update_deferred | È disponibile una versione nuova e c'è una campagna in corso su quella vecchia. | Riavvia per prendere l'aggiornamento. Scambiare un pacchetto sotto una partita in corso è il modo in cui un salvataggio comincia a nominare cose che nessuno fornisce. |
economy_expression_refused | Un campo che porterebbe qualcosa da valutare. | Un ingresso di prezzo ha provato a portare qualcosa di valutabile. Scegli una curva per nome fra le quattro che questa build implementa: un prezzo che può essere eseguito è il confine del livello 1 raggiunto attraverso l'economia. |
economy_invalid | Il record non è uno di quelli che questa build caricherebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
economy_out_of_bounds | Un numero fuori dall'intervallo dichiarato. | Riporta il numero dentro l'intervallo dichiarato. Ogni campo numerico qui ne ha uno, e un campo senza intervallo dichiarato viene rifiutato invece che lasciato passare. |
economy_overridden | Un pacchetto ha sostituito un record dichiarato da un altro pacchetto o dal gioco base. | Niente da sistemare. Questo record se l'è preso un altro pacchetto, e il resoconto dice quale, così puoi decidere se fosse l'intenzione. |
economy_unresolved_reference | Una ricetta o un serbatoio che nominano contenuto che nessuno fornisce. | L'id nominato è uno che niente nella composizione fornisce. O porti il record a cui punta, o dipendi dal pacchetto che lo porta. |
effect_carries_source | Un descrittore che ha nominato uno shader, una scena o del codice. | Togli il campo che nomina uno shader, uno script o una scena. Gli effetti si compongono dalle primitive del motore; fornirne il sorgente è fornire un programma. |
effect_degraded | Un effetto ridotto per stare dentro il fotogramma, nominato perché la riduzione non sia un mistero. | Niente da sistemare, a meno che tu non intendessi altro. L'effetto è andato a qualità più bassa per restare dentro il budget del fotogramma: c'è ancora, ed è più piccolo. |
effect_dropped | Un effetto che non ci stava proprio. | Guarda quale dimensione il resoconto del budget dice essersi riempita, poi taglia quella. Il fotogramma ha esaurito lo spazio e questo effetto non è stato disegnato affatto. |
effect_refused | Un effetto che questa build non compone. Il verdetto dice quale regola. | Leggi il parametro nominato nel resoconto e riportalo dentro l'intervallo stampato accanto. L'effetto è stato rifiutato prima che qualcosa lo disegnasse. |
extension_forbidden_field | Il manifesto porta un campo che nessuna estensione può portare, come il percorso di uno script, un risolutore o un import privato. | Togli il campo. Il percorso di uno script, un risolutore, un import privato o una modifica alle impostazioni di progetto vanno oltre il contratto fin dentro l'ospite, e un'estensione che ne ha bisogno sta chiedendo una capacità invece di dichiarare una funzionalità: dichiara la capacità sotto requires. |
extension_foreign_namespace | Lo spazio dei nomi di stato dichiarato non è l'id del pacchetto dell'estensione, quindi il suo stato non sarebbe attribuibile una volta che se ne fosse andata. | Rinomina state_namespace con l'id del pacchetto dell'estensione. Lo stato scritto altrove non si può attribuire né togliere una volta che il pacchetto è sparito, e l'ospite si tiene i propri nomi. |
extension_missing_field | Manca un campo che serve all'ospite per installare, prendere l'impronta, tornare indietro o togliere l'estensione. | Aggiungi il campo al manifesto dell'estensione. Ognuno di essi è qualcosa che serve all'ospite prima di poter ordinare l'estensione, metterla nell'impronta della composizione, tornare indietro o toglierla di nuovo: un manifesto a cui ne manca uno descrive una funzionalità che l'ospite potrebbe installare e mai rimuovere. |
extension_teardown_incomplete | Togliere l'estensione ha restituito meno di quanto avesse preso, il che perde alla prossima installazione invece che adesso. | Restituisci tutto quello che l'estensione ha preso prima che dichiari lo smontaggio completo, e aggiorna takes se il numero vero è cambiato. Restituire meno non fallisce adesso: perde alla prossima installazione, e installare la stessa estensione due volte in una sessione è ordinario. |
extension_unbounded | Un budget dichiarato manca o non è un numero, quindi niente può mai superarlo. | Scrivi un numero per ogni budget che il contratto nomina. Un budget omesso, o scritto come una frase, si legge come dichiarato e non si confronta con niente, quindi l'estensione non può mai superarlo. |
extension_unknown_capability | L'estensione richiede o fornisce una capacità che questa build non pubblica. | Confronta gli id delle capacità con quelli che questa build pubblica, e togli o rinomina quello che non corrisponde. Rifiutare prima dell'installazione è voluto: un'estensione che scoprisse una capacità mancante mentre gira la scoprirebbe davanti a un giocatore. |
extension_would_add_autoload | Il manifesto aggiungerebbe una variabile globale. Rifiutato qualunque cosa dica il livello di fiducia, perché un pacchetto che potesse aggiungerne una disferebbe il ritiro su cui questa build è costruita. | Togli dal manifesto l'autoload, il singleton o il nome di autoload di base. Nessun livello di fiducia concede questo: tutta la migrazione su cui questa build poggia è il ritiro delle variabili globali, quindi un'estensione che potesse aggiungerne una lo disferebbe da fuori. Metti lo stato sotto lo spazio dei nomi dell'estensione e raggiungi l'ospite attraverso le capacità che pubblica. |
font_locale_fallback | Un glifo che il carattere scelto non porta, disegnato dal ripiego e segnalato. | Il carattere che hai fornito non ha glifi per questa lingua, quindi l'ha disegnata il ripiego. Porta un carattere che copra la lingua, altrimenti il testo sono quadratini. |
font_refused | Un carattere che questa build non usa. Il verdetto dice quale regola. | Il file del carattere è stato rifiutato. Controlla che il formato sia uno di quelli che carichiamo e che il file non porti dentro nessun programma. |
image_bomb_refused | Un'intestazione che dichiara più del budget di decodifica, rifiutata prima che qualunque decodificatore la vedesse. | L'immagine si decomprime in molto più di quanto la dimensione del file suggerisca. Riesportala alle sue dimensioni vere: viene rifiutata prima di essere decodificata, perché decodificarla è il danno. |
image_frame_grid | Un foglio la cui griglia dichiarata non lo divide in modo esatto. | I fotogrammi del foglio di sprite non dividono le sue dimensioni in modo esatto. Sistema la griglia, altrimenti ogni fotogramma dopo il primo viene disegnato spostato del resto. |
image_hash_mismatch | Byte cambiati dopo che il descrittore era stato convalidato. | L'immagine non è quella che era stata dichiarata. Riesporta o ridichiara: una discordanza vuol dire che il file e il manifesto non concordano su che cosa sia stato portato. |
image_placeholder_used | Un'immagine rifiutata o mancante si è risolta nel sostituto riservato, e chi ha chiamato è stato avvisato. | Niente da sistemare, se l'avevi voluto tu. L'immagine mancava ed è stato disegnato il sostituto del suo tipo, con la sostituzione segnalata invece che lasciata in bianco. |
image_refused | Un'immagine che questa build non decodifica. Il verdetto dice quale regola. | Riesporta dentro le dimensioni, il formato e il budget che il resoconto nomina. L'immagine è stata rifiutata prima che qualcosa la disegnasse. |
inference_cancelled | Un'esecuzione ha superato il suo budget di latenza ed è stata fermata. Ha risposto l'euristica, quindi chi ha chiamato non è rimasto ad aspettare. | Snellisci il modello, oppure alza max_latency_usec se il budget era davvero troppo stretto. L'esecuzione ha superato il suo budget ed è stata fermata, e ha risposto l'euristica invece di lasciare chi aveva chiamato ad aspettare: un fotogramma passato ad aspettare è un fotogramma che il giocatore ha guardato. |
inference_digest_mismatch | I byte del modello non sono quelli registrati, il che ne fa un modello diverso e non uno più vecchio. | Aggiorna il digest dichiarato allo SHA-256 del modello che stai portando, oppure porta il modello che il digest nomina. Byte diversi vogliono dire che questo è un modello diverso, e non c'è nessun altro modo di vedere la differenza. |
inference_forbidden_field | La dichiarazione porta un runtime, uno script, un endpoint, della telemetria o una pretesa di autorità. | Togli il campo. L'adattatore appartiene al motore, quindi un pacchetto fornisce i pesi e mai il codice che li esegue; un endpoint metterebbe il modello in un posto in cui si può cambiare dopo la revisione, e la telemetria riferirebbe che cosa ha chiesto un giocatore. Porta i pesi e lascia che li esegua il motore. |
inference_load_refused | La dichiarazione è a posto e questa build non porta nessun adattatore di inferenza in cui caricarlo, quindi ha risposto l'euristica deterministica. | Niente da sistemare nel tuo pacchetto. Questa build non porta nessun adattatore di inferenza, quindi non viene caricato nessun modello di nessun formato e risponde l'euristica deterministica. La dichiarazione viene convalidata lo stesso, così un modello portato oggi è un modello che un adattatore potrebbe caricare senza modifiche. |
inference_missing_field | A una dichiarazione di modello manca qualcosa che serve all'adattatore prima di spendere qualunque cosa in un'esecuzione. | Aggiungi il campo alla dichiarazione del modello. Ognuno è qualcosa che serve all'adattatore prima di spendere qualunque cosa in un'esecuzione: il digest è l'identità del modello, gli schemi sono che cosa gli si dà in pasto e che cosa gli verrà accettato indietro, e le piattaforme sono dove gli è permesso essere provato. |
inference_output_rejected | La risposta del modello non corrispondeva allo schema di uscita dichiarato ed è stata scartata invece che interpretata con indulgenza. | Confronta quello che il modello restituisce con lo schema di uscita dichiarato. Una risposta quasi giusta viene scartata invece che interpretata con indulgenza, perché una proposta che passa nella forma sbagliata è una che ogni controllo successivo legge come valida. |
inference_unbounded | Un limite dichiarato manca o non è un numero, quindi niente può mai superarlo. | Scrivi un numero per ogni limite che il contratto nomina. Un limite omesso, o scritto a parole, si legge come dichiarato e non si confronta con niente, quindi l'esecuzione che va storta è quella che nessuno stava misurando. |
inference_unknown_format | Il formato del modello non è uno di quelli che l'adattatore del motore implementa. | Riesporta il modello in uno dei formati che l'adattatore del motore implementa. Un formato che non implementa non è una strada più lenta: è niente del tutto. |
inference_wrong_platform | Il modello non dichiara questa piattaforma, quindi ha risposto invece l'euristica deterministica. | Niente da sistemare, se è voluto. Il modello non dichiara questa piattaforma, quindi qui ha risposto l'euristica deterministica; aggiungi la piattaforma alla dichiarazione solo quando il modello ci sarà stato davvero costruito e provato. |
input_binding_conflict | Il tasto suggerito era già assegnato. L'assegnazione esistente se l'è tenuto e il suggerimento è stato registrato invece che applicato. | Niente da sistemare nel tuo pacchetto, e niente è stato tolto. Il tasto era già assegnato, quindi se l'è tenuto l'assegnazione del giocatore e la tua azione viene offerta senza tasto nella schermata delle assegnazioni. Scegli un valore predefinito meno affollato se preferisci che attecchisca all'installazione. |
input_binding_orphaned | Una riassegnazione appartiene a un'azione che nessun pacchetto installato dichiara. Conservata invece che tolta, così reinstallando la si ritrova dove il giocatore l'aveva lasciata. | Niente da sistemare. La riassegnazione appartiene a un'azione che nessun pacchetto installato dichiara e viene conservata invece che tolta, così reinstallando il pacchetto si ritrova il tasto dove il giocatore l'aveva lasciato. |
input_core_action | Un pacchetto ha nominato o provato a sostituire una delle azioni dell'ospite. | Rinomina l'azione. Le azioni del gioco appartengono all'ospite e un pacchetto non può né dichiararne una né sostituirla; prendersi pause fa un gioco da cui non si può uscire. Dichiara la tua azione accanto e lascia che il giocatore le assegni entrambe. |
input_forbidden_field | La dichiarazione porta una lettura diretta del dispositivo, un ascoltatore, una presa del fuoco o un'assegnazione che il giocatore non potrebbe cambiare. | Togli il campo. Dichiarare un'azione è tutta l'interfaccia: leggere direttamente un dispositivo, installare un ascoltatore, prendersi il fuoco o forzare un'assegnazione tolgono tutti una decisione al giocatore e sono invisibili in ogni schermata che potrebbe controllare. |
input_foreign_namespace | L'id dell'azione non sta nello spazio dei nomi del pacchetto che la dichiara. | Rinomina l'id dell'azione con lo spazio dei nomi del tuo pacchetto. La riassegnazione del giocatore ci sta attaccata, quindi un id che appartiene a qualcun altro è una riassegnazione che cambia padrone quando uno dei due pacchetti viene tolto. |
input_keyboard_unreachable | L'azione non ha nessuna assegnazione da tastiera, quindi un giocatore senza controller non può raggiungerla. | Scrivi un'assegnazione da tastiera accanto a quella del controller. Un'assegnazione solo da pad è irraggiungibile per un giocatore senza pad, in un gioco che per il resto si può giocare senza, e per lui fallisce in silenzio. |
input_missing_field | A una dichiarazione di azione manca qualcosa che serve alla schermata delle assegnazioni o alla riassegnazione. | Aggiungi il campo alla dichiarazione dell'azione. Ognuno è qualcosa che serve a una schermata: la chiave dell'etichetta è quello che l'elenco delle assegnazioni mostra al posto del tuo id interno, e il contesto è quello che dice al gioco quando l'azione è viva invece di farla scattare mentre qualcuno sta scrivendo il nome di un salvataggio. |
input_reserved_chord | Un pacchetto ha chiesto una combinazione che appartiene al sistema o alla finestra. | Scegli un altro tasto. Chiudere la finestra, uscire dal gioco e il tasto di piattaforma appartengono al sistema operativo, e un pacchetto che ne tenesse uno potrebbe impedire a qualcuno di uscire. |
input_unknown_context | Il contesto dichiarato non è uno di quelli che questa build pubblica, quindi nessuno sa quando l'azione sia viva. | Scegli uno dei contesti pubblicati. Nessuno sa quando sia viva un'azione in un contesto non pubblicato, quindi o non scatterebbe mai o scatterebbe sempre, e non è né l'una né l'altra la cosa che intendevi. |
lore_invalid | Il record non è uno di quelli che questa build caricherebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
lore_player_state_in_definition | Un campo che descrive un giocatore trovato dentro una definizione. | Togli il campo. Un record di lore è una definizione e quello che il giocatore sa è stato: caricare del lore non concede mai conoscenza, quindi un campo che pretendesse di farlo sarebbe un campo che nessuno legge. |
lore_replaced | Un pacchetto ha sostituito una voce esistente, conservandone l'id e i collegamenti. | Niente da sistemare. Un altro pacchetto ha sostituito questa voce e ne ha conservato l'id, quindi tutto quello che ci puntava punta ancora a qualcosa. |
lore_unresolved_reference | Un id in relates_to, reveals o requires che nessuno fornisce. | L'id nominato è uno che niente nella composizione fornisce. O porti il record a cui punta, o dipendi dal pacchetto che lo porta. |
lore_verbatim_text | Testo portato al posto di una chiave di catalogo, quindi comparirebbe in una sola lingua. | Un campo che finisce in _key contiene una frase. Spostala nel tuo catalogo di lingua: supera ogni altro controllo qui e porta il tuo lore in una lingua sola. |
map_bad_layer_data | Un livello che non copre la mappa a cui appartiene. | Riesporta il livello non compresso, senza blocchi e senza righe corte. Il sottoinsieme che accettiamo è il sottoinsieme che sappiamo controllare. |
map_carries_path | Una mappa che nomina qualcosa da caricare o da eseguire. | Togli il campo che punta a un file. Una mappa nomina i suoi tasselli dal corredo; un percorso è il modo in cui un pacchetto arriva fuori da se stesso. |
map_duplicate_anchor | Due oggetti che reclamano lo stesso id. | Due ancoraggi condividono un nome, quindi a quale si attacchi una cosa dipende dall'ordine di lettura. Rinominane uno. |
map_invalid | La mappa non è una di quelle che questa build assemblerebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
map_kit_mismatch | Una mappa disegnata contro un corredo che questa build non ha. | La mappa è stata scritta contro un corredo diverso da quello che questa build pubblica. Riesportala contro il corredo attuale: i ruoli e le classi si sono spostati. |
map_layer_missing | Un livello obbligatorio è assente o disegnato male. | Aggiungi il livello che il contratto richiede. Il file di progetto del corredo li elenca, e uno mancante è una mappa che si carica con un buco dentro. |
map_normalization_failed | La mappa non ha prodotto nessuna forma canonica. | Togli il costrutto che il resoconto nomina, poi esporta di nuovo. Senza una forma canonica non si può dimostrare che il runtime e il validatore offline siano d'accordo su questa mappa. |
map_outside_package | Un tileset o un modello che vengono da fuori del pacchetto. | La mappa punta a qualcosa fuori dal proprio pacchetto. Portalo dentro, altrimenti la mappa dipende da qualunque cosa sia installata. |
map_over_budget | Una mappa normalizzata oltre un limite dichiarato. | Il resoconto stampa quello che è stato misurato accanto a quello che era permesso. Dividi il record, oppure togli le voci oltre la riga: il tetto è quello che una schermata o un lettore possono reggere, non un suggerimento. |
map_unresolved_reference | Un id nominato che nessuno fornisce. | L'id nominato è uno che niente nella composizione fornisce. O porti il record a cui punta, o dipendi dal pacchetto che lo porta. |
map_unsupported_subset | Qualcosa nel file è fuori dal sottoinsieme del formato. | Il file usa una funzione di Tiled fuori dal sottoinsieme che questa build legge: livelli compressi, livelli immagine, gruppi, blocchi o poligoni. Riesporta senza. |
pack_claims_host_surface | Un autoload, un'azione di input o un'impostazione di progetto. | Sovrascrivi il contenuto invece del file. I pacchetti aggiungono e sostituiscono contenuto; le superfici che servono al gioco stesso per partire non sono fra queste. |
pack_collision | Una rivendicazione che un altro pacchetto ha già. | Rinuncia al file in uno dei due pacchetti. Il resoconto li nomina entrambi, e lasciarlo così farebbe vincere l'ordine di montaggio. |
pack_mount_failed | Il motore non l'ha montato; resta valido l'insieme precedente. | Il pacchetto non si è potuto montare per niente. Controlla che l'archivio sia integro e in un formato che questa build legge. |
pack_replaces_vanilla | Una rivendicazione che ha il gioco base. | Sovrascrivi il contenuto invece del file, oppure chiedi la capacità di sostituzione fidata. Sostituire un file del gioco base non è una cosa che fa un pacchetto di dati. |
pack_restart_required | L'insieme montato cambierebbe, e il cambiamento non può avere effetto in questo processo. | Il cambiamento non si può applicare a un gioco in esecuzione. Riavvia: scambiare contenuto montato a metà partita lascia metà del gioco a leggere i vecchi file. |
progress_invalid | Il record non è uno di quelli che questa build caricherebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
progress_origin_lost | Un traguardo guadagnato il cui pacchetto è sparito, conservato e nominato. | Niente da sistemare. Il pacchetto che l'aveva dichiarato è sparito e quello che il giocatore si era guadagnato è rimasto; l'id è lì perché sappia che cosa lo riporterebbe indietro. |
progress_over_budget | Un pacchetto oltre un tetto dichiarato. | Il resoconto stampa quello che è stato misurato accanto a quello che era permesso. Dividi il record, oppure togli le voci oltre la riga: il tetto è quello che una schermata o un lettore possono reggere, non un suggerimento. |
progress_reaches_outside | Un pacchetto che prova a eseguire qualcosa, o a parlare a nome della piattaforma. | Togli il campo. Se un traguardo arrivi alla piattaforma si ricava dal suo spazio dei nomi e non è mai una cosa che dice un record. |
progress_reserved_namespace | Un pacchetto che reclama uno spazio dei nomi che non è il suo. | Usa lo spazio dei nomi del tuo pacchetto. Quelli riservati sono nostri, e a un traguardo che sembrasse della piattaforma si crederebbe. |
progress_text_not_key | Una frase dove ci vuole una chiave di catalogo. | Sposta la frase nel tuo catalogo di lingua e metti la sua chiave nel campo. Un campo che finisce in _key contiene una chiave; una frase lì dentro porta il tuo pacchetto in una sola lingua per sempre. |
progress_unknown_step | Una condizione o un modificatore che questa build non ha. | Il nome non è nell'elenco pubblicato per quella tabella. Scegline uno che ci sia: l'elenco è corto perché ogni voce è qualcosa che questa build fa già. |
progress_unresolved_reference | Un record nominato che nessuno fornisce. | L'id nominato è uno che niente nella composizione fornisce. O porti il record a cui punta, o dipendi dal pacchetto che lo porta. |
provider_forbidden_capability | Un pacchetto ha chiesto una capacità che nessun livello concede, come il filesystem, la rete o un processo. | Togli la capacità. Nessun livello concede il filesystem, la rete, un processo o lo spazio dei nomi di un altro pacchetto, e nessuna revisione o firma cambia questo: quello che una build fa con il filesystem non è una proprietà che qualcuno possa controllare leggendola. Usa propose_intent per passare una proposta al proprietario canonico, e write_own_namespace per lo stato che deve sopravvivere. |
provider_native_extension_refused | È stata trovata un'estensione nativa. Ha piena autorità sul processo prima che qualunque politica giri, quindi viene rifiutata per una ragione sua e non come un controllo di fiducia fallito. | Togli l'estensione dal pacchetto. Il motore carica una GDExtension con piena autorità sul processo prima che qualunque parte di questa politica giri, quindi viene rifiutata per quello che è e non per chi l'ha firmata, e ratificare il livello dei fornitori non cambierà quella risposta. |
provider_tier_inactive | Il livello dei fornitori di comportamento non è ratificato in questa build, quindi non è stato caricato niente di eseguibile. | Niente da sistemare nel tuo pacchetto. Questa build non ha ratificato il livello dei fornitori di comportamento, quindi uno script, una scena impacchettata o un'estensione nativa vengono rifiutati chiunque li abbia firmati. Porta la meccanica come record dichiarativi se una delle famiglie pubblicate può portarla, e leggi le note di rilascio della build che ratifica il livello prima di scrivere un fornitore contro di essa. |
provider_unknown_capability | Un pacchetto ha chiesto una capacità che questa build non pubblica. | Togli la capacità dal manifesto, oppure sostituiscila con una che questa build pubblica. L'elenco è corto di proposito: un permesso che nessuno pubblica è un permesso su cui l'ospite non può ragionare, quindi viene rifiutato invece che ignorato. |
provider_unknown_load_kind | Un pacchetto ha offerto qualcosa che questa build non classifica. Rifiutato invece che trattato come dati, perché sbagliare la supposizione qui vuol dire sbagliarla nella direzione di eseguirlo. | Confronta quello che il pacchetto ha offerto con i quattro tipi che questa build classifica: dati dichiarativi, una scena impacchettata, uno script o un'estensione nativa. Qualunque altra cosa viene rifiutata invece che indovinata, perché indovinare qui vuol dire indovinare nella direzione di eseguirla. |
provider_untrusted | Il pacchetto è in uno stato di fiducia che non carica niente, cioè lo stato in cui ogni pacchetto comincia. | Niente da sistemare nel tuo pacchetto, e niente che un pacchetto possa sistemare da solo. La fiducia è attaccata ai byte esatti ed è il giocatore a darla, quindi installa il pacchetto da una fonte che ha scelto lui e lascia che confermi; un digest revocato non torna fidato per il fatto di essere rilevato di nuovo. |
provider_user_trust_required | Il livello lo permetterebbe e nessuna persona ha ancora detto sì a questo contenuto esatto. | Porta il giocatore all'elenco dei mod e lascia che confermi questo pacchetto. Il livello lo permetterebbe e nessuno ha ancora detto sì a questo contenuto esatto, che è l'unico passaggio che una firma deliberatamente non sostituisce. |
quest_already_applied | Un comando che era già stato eseguito. | Niente da sistemare. Il comando era già stato eseguito e non è stato ripetuto, ed è quello che impedisce a un ricaricamento di pagare due volte una ricompensa. |
quest_carries_expression | Un pacchetto che prova a eseguire qualcosa, o a tenersi da sé la risposta «una volta sola». | Togli il campo. Il livello 1 sono dati: quello che viene eseguito appartiene al gioco, e le funzionalità nuove passano da un fornitore fidato. |
quest_ending_unreachable | Un finale a cui nessuno può arrivare. | Il finale richiede una missione che il suo arco non contiene. Aggiungi la missione alle tappe dell'arco, oppure richiedine una che ci sia. |
quest_invalid | Il record non è uno di quelli che questa build caricherebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
quest_nothing_applied | Un piano che ha rifiutato qualcosa, quindi non è stato eseguito niente. | Qualcosa nell'insieme è stato rifiutato, quindi non è stato applicato niente. Sistema ogni rifiuto nel resoconto: un arco applicato a metà è uno stato che nessuno sa descrivere. |
quest_over_budget | Un pacchetto oltre un tetto dichiarato. | Il resoconto stampa quello che è stato misurato accanto a quello che era permesso. Dividi il record, oppure togli le voci oltre la riga: il tetto è quello che una schermata o un lettore possono reggere, non un suggerimento. |
quest_text_not_key | Una frase dove ci vuole una chiave di catalogo. | Sposta la frase nel tuo catalogo di lingua e metti la sua chiave nel campo. Un campo che finisce in _key contiene una chiave; una frase lì dentro porta il tuo pacchetto in una sola lingua per sempre. |
quest_unfinishable | Una missione che nessuno può completare. | Dài alla missione almeno un obiettivo non facoltativo, altrimenti si completa nel momento in cui viene accettata. |
quest_unknown_step | Un obiettivo o una concessione che questa build non ha. | Il nome non è nell'elenco pubblicato per quella tabella. Scegline uno che ci sia: l'elenco è corto perché ogni voce è qualcosa che questa build fa già. |
quest_unresolved_reference | Un record nominato che nessuno fornisce. | L'id nominato è uno che niente nella composizione fornisce. O porti il record a cui punta, o dipendi dal pacchetto che lo porta. |
relationship_band_gap | Un intervallo con un valore che nessuna fascia nomina. | Copri tutto l'intervallo della tua politica, dal pavimento al tetto, senza buchi e senza sovrapposizioni, usando solo i nomi di fascia pubblicati. Un valore in un buco è un valore che nessuna schermata sa nominare. |
relationship_carries_behaviour_code | Un pacchetto che prova a fornire quello che viene eseguito quando un rapporto cambia. | Togli il campo. Il livello 1 sono dati: quello che viene eseguito appartiene al gioco, e le funzionalità nuove passano da un fornitore fidato. |
relationship_declares_live_state | Un pacchetto che prova a dire a che punto sia adesso un rapporto. | Dichiara invece il valore iniziale. A che punto stia adesso un rapporto è cosa del runtime, ed è il giocatore ad averlo mosso. |
relationship_invalid | Il record non è uno di quelli che questa build caricherebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
relationship_leave_unreachable | Un compagno che non può andarsene mai, oppure che se ne va subito. | Sposta la soglia di abbandono dentro l'intervallo della politica. Al pavimento il compagno non si può perdere mai; sopra il tetto se ne va la prima sera. |
relationship_origin_lost | Il pacchetto che dichiarava un legame è sparito e il valore evoluto è rimasto. | Niente da sistemare. Il pacchetto che l'aveva dichiarato è sparito e quello che il giocatore si era guadagnato è rimasto; l'id è lì perché sappia che cosa lo riporterebbe indietro. |
relationship_pair_collision | Una coppia ordinata dichiarata due volte, lasciata senza nessun legame. | Due record reclamano la stessa coppia ordinata. Cancellane uno: tenerli entrambi farebbe vincere il pacchetto che si è caricato per primo. |
relationship_unknown_relation | Un tipo di relazione o una via di reclutamento che questa build non ha. | Scegli una relazione dall'elenco pubblicato. Una che questa build non ha verrebbe appiattita a niente, e la storia che hai scritto non succederebbe. |
relationship_unresolved_reference | Un record nominato che nessuno fornisce. | L'id nominato è uno che niente nella composizione fornisce. O porti il record a cui punta, o dipendi dal pacchetto che lo porta. |
resolution_cache_invalidated | Voci lasciate cadere perché il loro fornitore non è più attivo. | Niente da sistemare. La composizione è cambiata, quindi in che cosa si risolvano gli id è stato ricalcolato invece che riutilizzato. |
resolution_missing | Nessuno fornisce l'id e non si può ripiegare su niente. | Reinstalla il pacchetto che forniva l'id, oppure correggi l'id. Il resoconto lo conserva così puoi capire quale delle due cose sia successa. |
resolution_over_budget | Un pacchetto o il processo oltre un budget dichiarato. | Il resoconto stampa quello che è stato misurato accanto a quello che era permesso. Dividi il record, oppure togli le voci oltre la riga: il tetto è quello che una schermata o un lettore possono reggere, non un suggerimento. |
resolution_refused | Una richiesta che questa build non fa. | Leggi la regola che il resoconto nomina e cambia l'id in qualcosa che quel posto accetti. |
resolution_restart_required | Un cambio di profilo i cui byte vecchi non si possono scaricare. | Quello in cui si risolve questo id è cambiato in un modo che un gioco in esecuzione non può seguire. Riavvia per prenderlo. |
resolution_tombstoned | Un id conosciuto che un pacchetto ha tolto. | Reinstalla il pacchetto per far tornare la lapide contenuto vero. L'id si risolve nella sua lapide invece che nel niente, ed è esattamente per questo che reinstallare restituisce al giocatore le sue cose. |
save_campaign_absent | La campagna sotto cui è stato fatto il salvataggio non è installata. | Installa la campagna che il salvataggio nomina. Il salvataggio non viene aperto contro un'altra, perché sarebbe in silenzio un altro mondo. |
save_composition_matches | Niente di quello che il salvataggio aveva registrato si è mosso. | Niente da sistemare. I pacchetti con cui è stato fatto questo salvataggio sono i pacchetti installati. |
save_content_absent | Contenuto che il salvataggio nomina non è installato. Segnalato, non fatale. | Reinstalla i pacchetti che il resoconto elenca. Gli id restano nel salvataggio, quindi quello che adesso non ha risposta torna ad averne una. |
save_orphan_state_carried | Stato senza nessun proprietario installato, portato avanti senza essere eseguito. | Reinstalla il pacchetto per far tornare quello stato a significare qualcosa. È stato conservato invece che tolto proprio perché funzionasse. |
save_provider_contract_moved | Una capacità su cui il salvataggio contava adesso risponde a un contratto diverso. | Guarda se il resoconto dice migrato, ignorato o rifiutato. La versione del contratto di un fornitore è cambiata fra il salvataggio e adesso, e quelle sono le tre risposte. |
save_write_beside_original | La sessione ha scritto un file nuovo e ha lasciato stare l'originale. | Niente da sistemare. Il salvataggio recuperato è stato scritto accanto all'originale invece che sopra: la modalità sicura non sovrascrive mai il file che non è riuscita ad aprire. |
selection_campaign_missing | La campagna richiesta non è installata e al suo posto non è stato composto niente. | Installa il pacchetto che fornisce l'id di campagna che sta nel messaggio, oppure comincia un'altra campagna. L'id è quello che è stato chiesto, scritto come è stato chiesto, quindi confrontalo con l'id nel campaign.json del pacchetto. Al suo posto non è stato caricato niente: avviare il gioco base ti consegnerebbe un mondo diverso sotto il nome che hai scritto. |
selection_made | È stata selezionata una campagna, con la ragione per cui lo è stata. | Niente da sistemare. È la riga che dice quale mondo sia questa partita e perché sia stato scelto, e vale la pena leggerla quando il mondo non è quello che ti aspettavi: la ragione ti dice se sia stato richiesto, ripreso o l'unico installato. |
selection_safe_mode | Dei pacchetti sono stati lasciati fuori, o dopo un avvio fallito o perché l'ha chiesto il giocatore. | Leggi la ragione prima di cambiare qualcosa. player_asked vuol dire che l'hai scelto tu e non c'è niente che non va. boot_failed vuol dire che l'avvio della campagna è fallito più volte: disattiva i mod installati più di recente, avvia una volta, e rimettili uno alla volta. In modalità sicura non si compone nessun pacchetto, quindi una partita che qui funziona dice che il difetto sta in un pacchetto. |
selection_save_preserved | Un salvataggio recuperato è stato scritto accanto all'originale invece che sopra. | Niente da sistemare, e non cancellare il secondo file. Il recupero ha scritto il suo risultato accanto al tuo salvataggio invece che sopra, quindi il messaggio nomina entrambi i percorsi: l'originale è quello senza il suffisso .recovered, ed è ancora esattamente com'era. |
setting_invalid | La dichiarazione non è una di quelle che questa build disegnerebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
setting_migrated | Un valore è arrivato sotto una chiave vecchia ed è stato portato su quella attuale. | Niente da sistemare. L'impostazione è passata alla sua forma attuale e il valore vecchio è venuto dietro. |
setting_owner_missing | Un valore memorizzato appartiene a un pacchetto che non è installato. Conservato, non applicato. | Nomina un proprietario dichiarato per l'impostazione. Uno che questa build non ha è un'impostazione che nessuno leggerebbe mai. |
setting_restart_required | Il valore è cambiato e non può avere effetto fino al prossimo avvio. | Riavvia per applicarlo. L'impostazione non può cambiare mentre il gioco è in esecuzione. |
setting_secret_withheld | Un segreto è stato escluso da un salvataggio o da un resoconto. | Niente da sistemare. Un valore segnato come segreto è stato lasciato fuori dal resoconto, ed è per questo che il resoconto si può incollare in una discussione su un bug. |
setting_value_refused | Un valore fuori da quello che la dichiarazione permette. Risponde invece il valore predefinito. | Riporta il valore dentro l'intervallo stampato accanto, oppure scegline uno dall'elenco pubblicato. Il resoconto mostra entrambi. |
settlement_building_unresolved | Un edificio salvato il cui pacchetto è sparito, nominato invece che sostituito. | Reinstalla il pacchetto che il messaggio nomina per riavere l'edificio, oppure lascia stare: non si è perso niente. L'edificio è ancora nel salvataggio sotto il suo id e deliberatamente non è stato sostituito con quello più simile che questa build ha, il che avrebbe messo la merce di qualcun altro dentro una fucina che non hai mai costruito. |
settlement_carries_path | Un record che nomina una scena, uno script o una posizione propria. | Togli il campo e nomina invece un id. Un interno è l'id di un record di interno, mai il percorso di una scena, e un edificio si colloca nominando un oggetto sulla mappa invece che portandosi dietro le proprie coordinate. I campi di posizione sono rifiutati per questa seconda ragione: un record che tiene una coordinata è un record che può finire chissà dove quando la sua mappa non c'è più. |
settlement_invalid | Un record di insediamento che questa build non carica. | Leggi il verdetto accanto al codice e correggi il record che nomina. Le cause solite sono un campo obbligatorio omesso, un id senza davanti lo spazio dei nomi del tuo pacchetto, e un campo che appartiene a uno degli altri cinque tipi di record. |
settlement_loot_table_absent | Un contenitore la cui tabella del bottino se n'è andata con il suo pacchetto, quindi è vuoto invece che tirato da un'altra. | Reinstalla il pacchetto che forniva la tabella del bottino se vuoi che il contenitore si riempia di nuovo. È vuoto invece che tirato da un'altra tabella, perché tirare consegnerebbe le cose di un altro mondo sotto il nome di questo. |
settlement_over_budget | Più edifici o servizi di quanti un insediamento ne possa contenere. | Togli una parte di quello che il messaggio ha contato, oppure dividi l'insediamento in due. Il conteggio e il tetto sono tutti e due nel messaggio, quindi la differenza è quanti ne devono uscire. |
settlement_text_not_key | Un campo mostrato a schermo che contiene una frase invece di una chiave di catalogo. | Sostituisci la frase con una chiave di catalogo e metti la frase nella tua tabella di lingua. Un nome scritto dentro il record non si può tradurre e si vede in inglese in tutte le lingue. |
settlement_unreachable_service | Un servizio offerto a un ancoraggio che la mappa non dichiara. | Aggiungi l'ancoraggio al livello anchors della mappa con l'id che il servizio nomina, oppure rinomina il servizio con uno che ci sia. Il record e la mappa sono ciascuno legittimi da soli, e il risultato è un bancone a cui nessuno può stare. |
settlement_unresolved_reference | Un record che nomina qualcosa che nessuno fornisce. | Aggiungi al tuo pacchetto il record nominato, oppure correggi l'id. Il messaggio nomina sia il record che puntava sia l'id a cui puntava, quindi confrontalo con gli id che hai dichiarato. |
society_dimension_leak | Una dimensione dell'identità trovata a portarne un'altra. | Togli il campo che nomina l'altra dimensione. Una cultura non ha un campo fede: la derivazione deve essere impossibile da scrivere e non semplicemente sconsigliata, così che niente possa dare a una fazione una fede che nessuno ha scritto. |
society_heraldry_path | Un'insegna che nomina un file invece di un motivo. | Un'insegna araldica ha nominato un file. Nomina invece un motivo: un'insegna si sceglie fra quelle che questa build disegna. |
society_invalid | Il record non è uno di quelli che questa build caricherebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
society_mutation_in_definition | Una definizione che chiede di eseguire qualcosa. | Togli il campo. Gli adattatori di definizione descrivono; non hanno l'autorità di cambiare quello che descrivono. |
society_relationship_collision | La stessa coppia ordinata dichiarata due volte. | Una coppia ordinata è stata dichiarata due volte, quindi la coppia non ha nessuna posizione. Cancellane una: tenerle entrambe farebbe dipendere il mondo da quale pacchetto si è caricato per ultimo. |
society_relationship_one_sided | Una posizione il cui contrario nessuno ha dichiarato; il contrario è il valore predefinito. | Niente da sistemare, se l'avevi voluto tu. Di questa coppia è dichiarata una sola direzione e il contrario non dichiarato è il valore predefinito: una fazione che non sa di avere un nemico è una premessa, e questa riga sta qui perché sia una premessa scelta. |
society_unresolved_reference | Un record nominato che nessuno fornisce. | L'id nominato è uno che niente nella composizione fornisce. O porti il record a cui punta, o dipendi dal pacchetto che lo porta. |
state_namespace_ignored | Il pacchetto non legge più questo stato. | Dichiara lo spazio dei nomi, oppure togli lo stato. È arrivato sotto uno che nessuno reclama ed è stato lasciato stare invece che applicato. |
state_namespace_malformed | Uno spazio dei nomi nel salvataggio non è un nome che questa build accetterebbe. | Scrivi uno spazio dei nomi che identifichi un pacchetto senza ambiguità. Tutto quello che sta in un salvataggio ci pende sotto, quindi una forma che non sappiamo risolvere è stato che poi nessuno può reclamare. |
state_namespace_orphaned | Nessun pacchetto installato possiede questo stato ed è stato portato avanti. | Reinstalla il pacchetto per riportare indietro il suo stato. Lo spazio dei nomi appartiene a uno che è sparito e lo stato è stato conservato invece che cancellato. |
state_namespace_rejected | Il pacchetto ha rifiutato il proprio stato salvato per questa sessione. | Il pacchetto ha provato a scrivere fuori dallo spazio dei nomi che possiede. Scrivi dentro il tuo: lo stato di un altro pacchetto non sta a te cambiarlo. |
state_namespace_reserved | Un pacchetto ha reclamato uno spazio dei nomi che appartiene all'ospite. | Lo spazio dei nomi è uno di quelli dell'ospite. Prendi quello del tuo pacchetto. |
state_schema_future | Stato scritto da una versione del pacchetto più recente di quella che questa build ha. | Aggiorna il pacchetto. Lo stato salvato è stato scritto da una versione più recente di quella installata, e non tiriamo a indovinare per riportare indietro uno stato. |
state_schema_migrated | Stato più vecchio della build, consegnato al pacchetto perché lo portasse avanti. | Niente da sistemare. Uno stato più vecchio è stato portato alla forma attuale dalla migrazione del pacchetto stesso. |
state_schema_too_old | Stato più vecchio del pavimento che il pacchetto dichiara di saper leggere. | Guarda quale risposta il resoconto dice che il pacchetto abbia scelto. Lo stato è più vecchio della forma più antica da cui il pacchetto migra, quindi decide lui che cosa farne. |
state_write_outside_namespace | Chi scriveva si è rivolto a uno spazio dei nomi che non è il suo. | Scrivi dentro il tuo spazio dei nomi. Un pacchetto che cambia lo stato di un altro è il modo in cui un salvataggio smette di appartenere a qualcuno. |
strategic_carries_policy | Un pacchetto che prova a fornire la regola stessa. | Togli il campo. Il livello 1 sono dati: quello che viene eseguito appartiene al gioco, e le funzionalità nuove passano da un fornitore fidato. |
strategic_invalid | Il record non è uno di quelli che questa build caricherebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
strategic_over_budget | Un pacchetto oltre un tetto dichiarato. | Il resoconto stampa quello che è stato misurato accanto a quello che era permesso. Dividi il record, oppure togli le voci oltre la riga: il tetto è quello che una schermata o un lettore possono reggere, non un suggerimento. |
strategic_text_not_key | Una frase dove ci vuole una chiave di catalogo. | Sposta la frase nel tuo catalogo di lingua e metti la sua chiave nel campo. Un campo che finisce in _key contiene una chiave; una frase lì dentro porta il tuo pacchetto in una sola lingua per sempre. |
strategic_unknown_term | Una considerazione, un'intenzione o una classe che questa build non ha. | La parola non è nell'elenco pubblicato per quel campo. Scegline una che ci sia: sotto una parola che non abbiamo non risponderebbe niente. |
strategic_unresolved_reference | Un record nominato che nessuno fornisce. | L'id nominato è uno che niente nella composizione fornisce. O porti il record a cui punta, o dipendi dal pacchetto che lo porta. |
strategic_weightless | Un pianificatore che deciderebbe sempre allo stesso modo. | Dài ad almeno una considerazione un peso diverso da zero. Pesi tutti a zero danno lo stesso punteggio a ogni opzione e scelgono per sempre la prima in ordine alfabetico. |
theme_carries_executable | Un tema che ha nominato una scena, uno script o il percorso di una risorsa. | Togli il campo. Un tema descrive come si vedono le cose; uno script dentro un tema è un programma che gira dietro ogni schermata. |
theme_contrast_too_low | Una coppia di colori sotto il rapporto di contrasto minimo. | Sposta il primo piano o lo sfondo finché il rapporto non supera il minimo stampato accanto. È l'unica regola dei temi che un giocatore sente direttamente. |
theme_refused | Un tema che questa build non registra. | Leggi la proprietà che il resoconto nomina e riportala dentro quello che permette. |
tombstone_blocks_campaign | La famiglia dichiarata senza la quale la campagna non si carica. | Questa famiglia è portante e il suo pacchetto è sparito, quindi la campagna non parte. Reinstallalo: partire senza sarebbe un mondo a cui manca qualcosa a cui si riferisce ovunque. |
tombstone_placeholder_substituted | Al suo posto risponde un sostituto posseduto dal motore. | Reinstalla il pacchetto per riavere il contenuto vero. Il resoconto dice quale sostituto sia stato usato nel frattempo. |
tombstone_recorded | Un id il cui pacchetto è sparito è stato registrato invece che tolto. | Niente da sistemare. Un pacchetto se n'è andato e i suoi id sono rimasti nel salvataggio, ed è l'unica ragione per cui reinstallarlo restituisce al giocatore le sue cose. |
tombstone_reinstall_recovered | Il pacchetto è tornato e la lapide si è risolta di nuovo in contenuto vero. | Niente da sistemare. Il pacchetto è tornato e le sue lapidi si risolvono di nuovo in contenuto vero. |
tombstone_unresolved_reference | Qualcosa nel salvataggio punta ancora a un id ridotto a lapide. | L'id nominato è uno che niente nella composizione fornisce. O porti il record a cui punta, o dipendi dal pacchetto che lo porta. |
unit_carries_behaviour_code | Un pacchetto che prova a fornire del comportamento. | Togli il campo. Il livello 1 sono dati: quello che viene eseguito appartiene al gioco, e le funzionalità nuove passano da un fornitore fidato. |
unit_incomplete_for_category | Un'unità a cui manca quello che la sua categoria richiede. | Aggiungi la parte che la categoria richiede. La tabella delle categorie le elenca: un compagno ha bisogno di un equipaggiamento, una truppa di un comportamento, e un capo non ripiega mai su uno. |
unit_invalid | Il record non è uno di quelli che questa build caricherebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
unit_unknown_behaviour | Un profilo di comportamento che questa build non ha. | Scegli un profilo di comportamento dall'elenco pubblicato. Uno che questa build non ha viene rifiutato invece che rimpiazzato da un valore predefinito, perché un capo diventato in silenzio un vagabondo è uno scontro che non succede. |
unit_unresolved_reference | Un record nominato che nessuno fornisce. | L'id nominato è uno che niente nella composizione fornisce. O porti il record a cui punta, o dipendi dal pacchetto che lo porta. |
unit_visual_missing | Un aspetto si è risolto nel suo sostituto. | L'aspetto che hai nominato non è fornito, quindi è stato usato il sostituto di quel tipo. Porta la risorsa oppure punta a una che esista. |
world_calendar_inconsistent | Un calendario o una festa che non possono succedere. | Sistema la coppia che il resoconto nomina. Stagioni, mesi e feste devono concordare, e una che non concorda è un calendario che il mondo legge in due modi. |
world_carries_clock_control | Un pacchetto che fornisce un proprio tempo. | Togli il campo. Un pacchetto dichiara quanto vale una stagione e non può muovere l'orologio: l'orologio canonico ha un solo proprietario. |
world_carries_randomness | Un pacchetto che fornisce una propria casualità. | Togli il seme e nomina invece un flusso. Il seme della partita appartiene all'ospite e il flusso ne deriva, quindi un pacchetto che porta un seme proprio è un mondo che ignora la partita in cui si trova. |
world_invalid | Il record non è uno di quelli che questa build caricherebbe. | Leggi il verdetto accanto al codice. Nomina l'unica regola che il record ha infranto, e ognuna di esse è un campo da togliere, un campo da aggiungere o una parola da cambiare. |
world_unresolved_reference | Un record nominato che nessuno fornisce. | L'id nominato è uno che niente nella composizione fornisce. O porti il record a cui punta, o dipendi dal pacchetto che lo porta. |
Limiti, salvataggi, condivisione
Che cosa un mod non potrà mai fare
Rifiutato dalla build, non sconsigliato.
| Niente codice | Script, estensioni, eseguibili, file di shell — in qualunque punto del tuo pacchetto. |
| Niente scene né file di risorsa | Un record che ne punta uno viene rifiutato anche se il file non c'è. |
| Niente oscuramento dei file base | Un mod aggiunge e cambia record; non può sostituire i file del gioco. |
| Nessun tipo nuovo di cosa | Un privilegio nuovo sì, un tipo nuovo di privilegio no. |
| Niente comandi, autoload o impostazioni di progetto | Non raggiungibili per niente. |
| Niente cancellazioni vere e proprie | remove ritira un record dalla circolazione e lo lascia risolvibile. Solo vendor_inventories ne toglie uno. |
L'elenco esatto, perché un rifiuto lo cita:
- Un file di record può essere 4 MB, contenere 4 096 record e annidarsi per 16 livelli. Il catalogo più grande che il gioco porta con sé ne contiene qualche centinaio, quindi un file che fa scattare uno di questi limiti è malformato più che ambizioso.
- File che il tuo pacchetto non può contenere affatto, in nessun punto:
.bat,.cmd,.dll,.dylib,.exe,.gd,.gdc,.gde,.gdextension,.ps1,.sh,.so,.vbs. Ognuno di essi è comportamento: uno script, una libreria nativa, o qualcosa che l'ospite eseguirebbe. - Estensioni a cui un record non può puntare:
.bat,.cmd,.dll,.dylib,.exe,.gd,.gdc,.gde,.gdextension,.ps1,.res,.scn,.sh,.so,.tres,.tscn,.vbs. È l'elenco di sopra più scene e risorse, perché un record che ne nomina una sta chiedendo al gioco di costruirla. - Chiavi rifiutate qualunque cosa contengano:
resource_local_to_scene,resource_path,scene,scene_path,script. - Percorsi rifiutati ovunque compaiano: qualunque cosa cominci con
res://ouser://. Un record indirizza contenuto dentro il proprio pacchetto.
Anche la dimensione ha dei tetti, per pacchetto e su tutti quanti, e superarne uno non è sempre un rifiuto:
- ok Sotto il limite. Non viene segnalato niente.
- warn Oltre la soglia morbida e caricato lo stesso. Chi crea viene avvisato; il giocatore non viene fermato.
- degrade Oltre il limite su una dimensione che l'ospite può ridurre invece di rifiutare. Viene nominato su che cosa è ripiegato, perché un gioco che gira diversamente in silenzio è peggio di uno che dice perché.
- reject Oltre il limite su una dimensione che non ha una versione più piccola di sé. Il pacchetto non si carica e viene nominato.
| Dimensione | Un pacchetto | Tutti quanti | Se lo supera |
|---|---|---|---|
records | 20 000 | 120 000 | reject |
decoded_image_bytes | 256 MB | 1 GB | reject |
decoded_audio_bytes | 128 MB | 512 MB | 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 revisione generale ottiene il doppio di quei numeri e una conversione totale il quadruplo. Quattro volte, non illimitato: un limite che un pacchetto può dichiarare via non è un limite.
Si muove solo la riga della rimozione. Una famiglia accetta un remove quando riesce a consegnare al caricatore il record che viene ritirato; oggi lo fanno in due. Tutto il resto di questa tabella è permanente.
Non sta arrivando nessun livello di scripting. Il manifesto porta un tipo di pacchetto che spedisce comportamento invece di dati: l'unica cosa che potrebbe autorizzarne l'esecuzione lo rifiuta, dietro non c'è nessuna sandbox, e un pacchetto che lo dichiara viene rifiutato oggi. Progetta per i dati.
Leggi «dati» in senso largo. I numeri sono dati. Il bilanciamento è dati. Che cosa fa un'arma, quanto costa una ferita, a quanto si vende una merce, come una fazione pesa una decisione: tutto tuo. Quello che non è dati è una meccanica che il gioco non ha mai avuto — quello è codice che qualcuno scrive e prova. Se la tua idea ne ha bisogno, è un gioco diverso e non un mod.
Salvataggi
I tuoi id finiscono nel file di salvataggio del giocatore. Un id pubblicato è una promessa.
| Regola | Perché |
|---|---|
| Non rinominare mai un id | Ogni salvataggio che lo usava resta a piedi. Aggiungine uno nuovo e lascia stare il vecchio. |
| Disinstallarti non cancella mai le cose di un giocatore | Il salvataggio conserva gli id che non riesce a risolvere e li segnala, così reinstallare restituisce il deposito. |
Alza version ogni volta che cambi qualcosa | È la cosa che un giocatore può vedere. |
Ogni modo in cui un insieme di pacchetti può differire da quello sotto cui è stato fatto un salvataggio ha un nome, e ogni nome decide una cosa: se la sessione possa scrivere sopra quel file.
| Verdetto | Può scrivere il tuo salvataggio | Che cosa significa |
|---|---|---|
compatible | Sì | La composizione corrisponde a quella sotto cui è stato fatto il salvataggio. |
degraded | Sì | Capito, con del contenuto nominato assente. Si continua a giocare e l'assenza viene segnalata. |
incompatible | No, il file viene lasciato stare | La sessione non può onorare quello che dice il salvataggio. Il file originale viene lasciato stare. |
| Che cosa differisce | Verdetto | Che cosa significa |
|---|---|---|
identical_composition | compatible | Stessi pacchetti, stesse versioni, stessa composizione. |
mod_added | compatible | Un pacchetto di cui il salvataggio non ha mai saputo niente. Niente di quello che aveva registrato si è mosso. |
mod_missing | degraded | Un pacchetto che il salvataggio nominava non è installato. I suoi id sono ancora nel file e ci restano. |
mod_upgraded_compatible | degraded | Un pacchetto è cambiato restando dentro la compatibilità che dichiara. Segnalato, perché un hash cambiato è una risposta cambiata anche quando è una risposta legittima. |
provider_contract_incompatible | incompatible | Una capacità su cui il salvataggio contava risponde attraverso un fornitore il cui contratto si è spostato. Andare avanti sarebbe tirare a indovinare che cosa significhi. |
conversion_missing | incompatible | La campagna stessa è assente. Ogni id nel file appartiene a un mondo che non è installato. |
safe_mode_disabled | degraded | La sessione è partita con i pacchetti spenti di proposito. Il salvataggio è leggibile e il suo contenuto modificato è assente per scelta. |
orphan_state_preserved | degraded | Stato il cui pacchetto è sparito passa attraverso intatto. Conservato, mai eseguito. |
Leggi due volte la riga incompatible: il salvataggio originale viene lasciato stare. Un file sovrascritto da una sessione che non l'aveva capito è una partita persa, e un giocatore che ne perde una per colpa di un mod non ne installa un altro.
Ogni pacchetto caricato riceve un'impronta digitale: la stessa viene eseguita per lo stesso manifest e contenuto, diversa nel momento in cui il file di contenuto cambia. Il digest del set composto include anche l'ID di ciascun pacchetto, la versione, l'ordine di caricamento e il digest del contenuto, quindi gli stessi pacchetti in un ordine diverso non possono fingere di avere la stessa composizione. modding_fingerprint_report stampa questi valori e salva lo schema v56 registra l'elenco delle impronte digitali attive in modo che un caricamento successivo possa avvisare di un pacchetto mancante o modificato. Aumentare il tuo version è ancora necessario perché è il valore che un giocatore può vedere e confrontare prima dell'installazione.
Condividerlo
Comprimi la cartella in uno zip. Il formato di distribuzione è tutto qui. Non c'è nessun catalogo dentro il gioco; mettilo su Nexus Mods.
| Passo | Che cosa |
|---|---|
| Controllo | Il validatore pulito, con --strict, prima di caricare. |
| Zip | La cartella stessa, così l'archivio contiene my_mod/mod.json. |
| Versione | Alza version in mod.json a ogni caricamento. |
| Requisiti | Elenca le tue dependencies anche sulla pagina di Nexus. |
| Di' | Quali famiglie tocchi e quali id sovrascrivi con override. |
Non cambiare mai l'id del tuo pacchetto. È lo spazio dei nomi che porta ogni tuo id, quello che un altro pacchetto nomina come dipendenza, e quello che un salvataggio mette per iscritto. Rinominarlo fa credere a ogni salvataggio esistente che il tuo pacchetto sia stato disinstallato e che ne sia comparso un altro accanto. Cambia invece il name visualizzato.
Di' alla gente due cose e ti risparmi più richieste di assistenza che con qualunque altra: la game_version contro cui hai costruito, e se hai messo canon_safe.
La versione da scrivere oggi è 0.0.0-dev. È quella a cui risponde questa build ed è quella che dichiara ogni esempio in questa pagina, ed è un numero solo invece di un intervallo: quando il gioco uscirà cambierà prima qui.
Gli archivi hanno dei limiti, decisi dall'intestazione invece che dopo l'estrazione:
- Al massimo 4 096 voci, nessuna più grande di 16 MB, e 128 MB estratti in tutto.
- Un nome può essere di 200 caratteri e stare 8 cartelle in profondità.
- Niente può dichiarare di espandersi più di 200 volte, cosa che nessun contenuto onesto raggiunge: il testo si comprime intorno a quindici. Qualche kilobyte che si estrae in gigabyte è l'attacco per cui questo numero esiste.
- Una voce che non sia un file semplice o una cartella viene rifiutata: link simbolico, hard link, dispositivo, fifo, socket. Il link simbolico è quello che conta, perché il suo nome può essere del tutto ordinario e seguirlo scrive dove punta lui.
- Un archivio dentro il tuo archivio viene rifiutato invece che misurato (
.7z,.bz2,.gz,.pck,.rar,.tar,.xz,.zip). Quello esterno dichiara fin dove si espandono le sue voci; non può dichiarare fin dove si espandano quelle di uno interno.
Oggi non c'è nessun negozio in cui pubblicare, e questa è la forma di quello che ci sarà. La distribuzione adesso è lo zip e la pagina di Nexus qui sopra: niente di quello che segue è un campo che compili per un caricamento che puoi fare questa settimana. Sta qui perché i campi sono già dichiarati nella build, quindi una strada verso un negozio è questione di collegarli invece che di inventarli, e perché un pacchetto scritto oggi non andrà riscritto per viaggiare in quel modo.
Un pacchetto che viaggia attraverso un negozio porta più cose di quante ne porti la cartella:
| Che cosa porta | Campi |
|---|---|
| Chi è | stable_id, version |
| Da dove viene | author, license, source_url, package_hash |
| Che cosa ne dice un negozio | content_rating, content_warnings, revocation_status |
| Come è stato consegnato | store, store_id, subscription_id |
| Stato | Si installa | Che cosa significa |
|---|---|---|
none | Sì | Non è stato segnalato niente. |
reported | Sì | Qualcuno l'ha segnalato e non è stato deciso niente. Il giocatore viene avvisato e sceglie. |
quarantined | No | Trattenuto in attesa di una decisione. Non si installa e quello che è già installato non viene cancellato. |
revoked | No | Ritirato. Non si installa, e una copia installata viene disattivata invece che rimossa, perché i salvataggi del giocatore nominano ancora il suo contenuto. |
I due stati che bloccano un'installazione continuano comunque a non cancellare niente.
Che cosa una build nuova può fare al tuo pacchetto
game_version non è un ornamento. Il gioco confronta quello contro cui hai costruito con quello che è:
| Verdetto | Che cosa significa per te |
|---|---|
supported | La build che hai nominato è questa, o abbastanza vicina. Niente da fare. |
older_build | Hai costruito contro un gioco più vecchio. Si carica lo stesso, e da quello che si è spostato nel frattempo verrebbe l'eventuale sorpresa. |
newer_build | Hai costruito contro un gioco più recente di quello in esecuzione. Il pacchetto viene nominato come tale invece che caricato a metà nella speranza che tutto quello che usa esista già. |
unreadable | La game_version che hai scritto non è una versione. Questo è sempre un errore di battitura. |
Che cosa faccia al riguardo dipende da che cosa si è spostato:
| Classe | Che cosa significa | Che cosa ti deve il gioco |
|---|---|---|
| invariato | Niente che un pacchetto possa osservare si è spostato. | nessuna |
| additivo | Esiste qualcosa di nuovo e tutto quello che c'era significa ancora quello che significava. | un incremento minore |
| rompente | Un pacchetto scritto contro la superficie vecchia adesso può essere sbagliato senza essere stato modificato. | un incremento maggiore |
Una modifica conta come interruzione per uno di questi motivi: 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 è quello che sembra additivo e non lo è. Un campo le cui mosse predefinite riscrivono il comportamento di ogni pacchetto che non lo ha mai menzionato e nessuno dei suoi autori ha cambiato nulla. constraint_changed copre limiti ed enumerazioni, mentre root, formato, campo id, altri metadati del catalogo e modifiche alla rimozione della famiglia alterano dove o se un pacchetto può essere letto.
Un nome che sta per sparire viene deprecato prima di essere tolto, e continua a funzionare per almeno 2 versioni minori dopo la release che l'ha deprecato.
La politica, in quattro frasi
Chi sta decidendo se spendere cento ore su un pacchetto in realtà fa una domanda sola: che cosa gli succede quando il gioco si aggiorna. Ecco la risposta, prima che ci sia un elenco da leggere.
| Domanda | Risposta |
|---|---|
| Il mio pacchetto si caricherà ancora? | Sì, a meno che una release non sia elencata qui sotto come rompente, e nessuna release è rompente senza comparire lì prima. |
| I salvataggi dei giocatori sopravvivranno? | Sì. Una sessione che non riesce a capire un salvataggio si rifiuta di scriverci invece di sovrascriverlo, e un salvataggio conserva gli id che non riesce a risolvere invece di lasciar cadere le cose. Salvataggi. |
| Quanto preavviso ricevo? | Un nome viene deprecato prima di essere tolto e continua a funzionare per almeno 2 versioni minori dopo la release che l'ha deprecato. |
| Come lo saprò? | La riga atterra nella tabella qui sotto, con che cosa si è spostato e che cosa cambiare, prima della release a cui appartiene. |
Release che rompono i pacchetti
| Release | Data | Che cosa si rompe | Che cosa fare |
|---|---|---|---|
| — | — | Ancora niente. Nessuna release ha rotto un pacchetto. | — |
La tabella è vuota e non è un segnaposto. Esiste adesso perché la prima riga abbia dove atterrare e perché la promessa qui sopra sia messa per iscritto prima di essere messa alla prova invece che dopo. Una riga qui nomina la release, il giorno in cui è uscita, esattamente quale forma ha smesso di essere accettata, e la modifica che sistema un pacchetto — non «varie modifiche».
Il lavoro in arrivo che romperebbe qualcosa va nella stessa tabella, segnato come in arrivo, prima di uscire.
Se il gioco non parte
Un profilo che non riesce ad avviarsi viene ritentato un numero limitato di volte, poi il gioco offre una via di rientro invece di provare all'infinito.
Un profilo viene ritentato 3 volte. Dopo, il gioco smette di provare e offre invece una di queste.
- retry Sotto il limite dei tentativi. Si riprova lo stesso profilo.
- last_known_good Viene offerto un profilo che in passato si era avviato. Non viene disinstallato niente.
- safe_mode Per una sessione non si carica nessun pacchetto. Il profilo resta intatto e torna quando il giocatore lo chiede.
Dove ha fallito ti dice che cosa guardare:
| Dove ha fallito | A che cosa punta |
|---|---|
discovery | Leggere che cosa è installato. Un fallimento qui è di solito un pacchetto malformato. |
provider_start | Avviare quello che la composizione ha selezionato. Un fallimento qui nomina una capacità. |
first_scene | La prima scena che il giocatore vedrebbe. Un fallimento qui è contenuto, non cablaggio. |
Niente di tutto questo disinstalla il tuo pacchetto o modifica i tuoi file. La modalità sicura è una sessione senza nessun pacchetto caricato, e il tuo profilo ti aspetta per quando lo richiedi.
Una conversione totale
Non è ancora una strada pubblicata per chi crea. La build capisce il manifesto e porta con sé il fixture Ashen Reach; un flusso di lavoro impacchettato e pubblico non è uscito. Tratta il fixture come un contratto d'ingegneria, non come la promessa che oggi tu ne possa pubblicare una.
Si dichiara con type: total_conversion. Accanto, fallback_policy decide se una conversione installata a metà mostri il contenuto del gioco oppure niente.
| Sostituisce | Non può aggiungere |
|---|---|
| I luoghi, i popoli, la guerra, i miti, la mappa, i nomi di ogni cosa. Regni tuoi, dèi tuoi, un'economia tua. | Un tipo nuovo di cosa. Una spada che colpisce più forte è un numero; un'arma che spara un raggio e ha bisogno delle regole del raggio è una funzionalità, e le funzionalità sono codice. |
Che cosa cambia e che cosa no
Non cambia quasi niente. La cartella è la cartella, mod.json è mod.json, le famiglie sono le stesse famiglie con gli stessi campi, gli id hanno lo spazio dei nomi allo stesso modo, il validatore applica le stesse regole e la schermata Mod riferisce gli stessi stati. Ogni tutorial di questa pagina è un tutorial per costruire un pezzo di una conversione. La distanza fra un pacchetto che aggiunge un mercante e un pacchetto che è un reame intero è una quantità di record, non un'abilità diversa.
Tre cose cambiano davvero, e vale la pena conoscerle tutte e tre prima di cominciare:
| Che cosa | Come |
|---|---|
| Il manifesto | type: total_conversion, e accanto fallback_policy, che è vanilla o none e vale vanilla se non la scrivi. vanilla vuol dire che una conversione installata a metà mostra il contenuto del gioco dove manca il tuo; none vuol dire che non mostra niente. |
| I budget | Quattro volte il profilo ordinario — e un profilo, non un'esenzione. Le parole della build stessa: «Quattro volte, non illimitato: un limite che si può dichiarare via non è un limite.» Se total_conversion togliesse i limiti, diventerebbe la riga che ogni pacchetto scrive per sfuggirvi. |
| Le parole non tradotte smettono di ripiegare su quelle del gioco | Di norma una chiave mancante scende per player_locale, poi la lingua predefinita del tuo pacchetto, poi il catalogo del gioco, poi la chiave stessa. A una conversione totale quel terzo gradino è tolto. Una chiave che non hai scritto si vede come la chiave, e viene segnalata. |
Quel terzo gradino sembra una perdita ed è il contrario. Old Seat che affiora in un mondo che non ha nessun Old Seat non è una traduzione un po' sbagliata: è il gioco base che traspare da sotto quello che ci hai costruito sopra. Togliere il gradino vuol dire che un buco nelle tue parole è una cosa di cui ti viene detto invece di una cosa che trova un giocatore.
Dove sta andando
Vale la pena dirlo chiaramente, perché cambia che cosa valga la pena imparare.
Il motore sotto Bonemark è stato costruito per reggere più di Bonemark. L'ambientazione è dati: i luoghi, i popoli, l'economia, i miti e le parole per tutto questo sono record degli stessi tipi che questa pagina ha descritto. È per questo che il tipo conversione totale esiste nel manifesto, ed è per questo che la build porta con sé una seconda ambientazione come fixture invece che come prova di una riga di codice.
Quindi la forma di lungo periodo non è «aggiungi una spada». È che chi impara queste famiglie sta imparando a costruire un mondo su questo motore, e la distanza fra un pacchetto che aggiunge un mercante e un pacchetto che è un reame intero è una quantità di record e non un'abilità diversa.
Steam Workshop è la direzione per far arrivare i pacchetti ai giocatori, ed è per questo che Condividerlo descrive i campi di un negozio che ancora non porta niente. Iscriversi a un pacchetto invece di estrarne uno cambia come arriva e niente di come è scritto: la stessa cartella, lo stesso mod.json, gli stessi id.
Nessuna data, per nessuna delle due, e nessuna seconda ambientazione nominata: una esiste come fixture d'ingegneria, che non è la stessa cosa di una annunciata. Quello che si sta dicendo qui è una direzione e quanto costa farsi trovare pronti: cioè che la cosa che impari oggi non smetterà di essere la cosa quando la porta si aprirà.
Possedere un mod
Le stesse condizioni su cui si è assestata ogni scena di modding, perché sono quelle che funzionano. Qui non c'è niente di insolito e niente di ingannevole.
| Il tuo mod è tuo | I record che hai scritto, le immagini che hai disegnato, il suono che hai fatto. Restano tuoi. Pubblicare un mod non dà a nessuno un diritto sul tuo lavoro. |
| Il contenuto del gioco resta del gioco | Riferisciti a quello che vuoi — sovrascrivi un id, correggi un campo, vesti un oggetto. Non estrarlo, non reimpacchettarlo e non portarne copie dentro la tua cartella. Questa è per lo più tenuta al posto tuo: un pacchetto non può oscurare i file del gioco, quindi la linea è difficile da attraversare per sbaglio. |
| Il diritto d'autore non si sposta in nessuna delle due direzioni | È il nome giuridico delle due righe qui sopra, e vale la pena dirlo chiaramente perché è la cosa che la gente dà per scontata al contrario. Pubblicare un pacchetto non cede il tuo lavoro allo studio; installarne uno non cede il gioco a te. Il diritto d'autore sui record che hai scritto e sull'arte che hai fatto è tuo, e i record, l'arte, il suono e l'ambientazione di Bonemark restano dello studio. La conversione totale è il caso che vale la pena esplicitare: sostituire l'ambientazione che un giocatore vede non concede in licenza l'ambientazione sostituita, e un pacchetto continua a non poter portare i file del gioco. |
| I mod sono gratuiti | Nessuna vendita, nessun muro a pagamento, nessun accesso anticipato dietro un pagamento, su nessun negozio o piattaforma. E non sono nemmeno nostri da vendere: la stessa regola lega lo studio. |
| Le donazioni vanno bene | Un barattolo per le mance, un Patreon, una pagina di ringraziamenti. È sostegno a una persona, non un prezzo su un mod, e ogni scena sana lo permette. |
| Il lavoro di qualcun altro richiede il suo permesso | Un carattere, un suono, uno sprite, un insieme di record da un altro pacchetto: chiedi, e cita l'autore dove un giocatore possa leggerlo. |
| Le traduzioni sono permesse per impostazione predefinita | Chiunque può tradurre il tuo pacchetto e pubblicare la traduzione, citandoti. Dillo sulla tua pagina se preferisci che te lo chiedano prima. |
| Il riuso chiede prima | Costruire sul pacchetto di qualcuno, proseguirne uno abbandonato, prendere i suoi record e metterli nel tuo: chiediglielo. Il silenzio non è un sì. |
Perché il gratuito non è negoziabile. I mod a pagamento sono stati provati su larga scala e ritirati ogni volta: nel momento in cui c'è di mezzo il denaro, le discussioni sono su chi possieda quale idea invece che su che cosa costruire dopo, e la scena che condivideva comincia a tenersi le cose. In questo ecosistema stanno tutti sullo stesso piano, e questo include chi ha fatto il gioco.
Una cosa possiamo chiederla. Che un pacchetto venga tolto, e solo per ragioni ristrette: porta i file del gioco, si spaccia per qualcuno, o contiene materiale illegale dove è ospitato. Non perché non siamo d'accordo con lui.
Deciso dallo studio il 2026-08-14. Il testo qui è la politica; un legale lo leggerà prima che il modding apra pubblicamente, e se questo cambia una parola questa pagina cambia con lei.
Dove chiedere
Discord, e non è ancora aperto. È lì che verranno risposte le domande sul modding, e l'invito non è scritto da nessuna parte perché non c'è niente a cui invitare qualcuno. Il marchio Discord in prima pagina è spento per la stessa ragione; il giorno in cui si accende è il giorno in cui questa riga porterà l'indirizzo.
Dire «Discord» prima che l'indirizzo esista vale più che non dire niente: ti dice dove guardare e ti dice di non andare a caccia in un forum che non è mai stato aperto.
Nel frattempo, la cosa che risponde a quasi tutte le domande senza che sia coinvolto nessun altro è Prima di chiedere aiuto a qualcuno: il blocco di verifica preliminare nomina la build, i pacchetti, gli stati e la ragione dietro ogni rifiuto, e quasi tutto quello che una persona avrebbe risposto è già lì dentro.