← Bonemark

Modding

Aggiungi contenuti scrivendo piccoli file di testo. Non serve programmare né compilare. In cinque parti: installare la mod di un altro, la tua prima mod, cambiare il gioco che c'è già, un riferimento con ogni famiglia e ogni codice diagnostico, e conviverci. La tabella di ciò che puoi creare è misurata sulla build, non promessa.

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. EstrailoIn 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 giocoI pacchetti vengono letti all'avvio. Non esiste installazione a caldo.
3. AccendiloApri 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 nuovoLa 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 schermataNel resocontoChe cosa significa
CaricatoactiveCaricabile, nessun ostacolo.
Non validoinvalidIl manifesto porta file di script o eseguibili bloccati.
Richiede un altro modskipped_missing_dependencyUna dipendenza dichiarata è assente o disattivata.
Richiede un altro modskipped_incompatible_dependencyUna dipendenza dichiarata è fuori dal suo intervallo.
IgnoratoincompatibleIl mod punta a una build del gioco più recente.
In conflittoconflictDue mod caricabili puntano allo stesso id di sovrascrittura (restano caricabili; vince il load_order, entrambi segnalati).
DisattivatodisabledL'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 caricareL'hai acceso e nessuno l'ha ancora letto. Il suo contenuto non è nel gioco finché non riavvii.
Spento — riavvia per scaricareL'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 rejected

Nove 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 cosaPerché noCambierà
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 pacchettoI 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.
Font del pacchettoI descrittori dei font e la copertura delle lingue vengono validati, ma nessun tema in esecuzione consuma ancora un font del pacchetto.
Una conversione totale impacchettataLa 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.
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.
Qualunque cosa venga eseguitaUn 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.

ParolaChe cosa significa
PacchettoIl tuo mod. Una cartella con sopra il tuo nome.
Manifestomod.json, in cima a quella cartella. Chi sei, che cosa porti.
RecordUna cosa che aggiungi. Una spada è un record.
FamigliaUn tipo di cosa. Spade, elmi e pane sono tutti items. Ogni famiglia ha la sua cartella.
Idyour_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ì.

VuoiVai a
Costruire qualcosa dall'inizio alla fineParti da quello che vuoi fare — i sei tutorial, un pacchetto solo
Far caricare un file in dieci minutiUn mod in dieci minuti
Cercare i campi di una famiglia e un esempioLe famiglie, una per una
Vedere tutto quello che ti è permesso fareOgni famiglia
Cambiare qualcosa che il gioco porta già con séCambiare quello che il gioco ha già
Aggiungere arte, suono, scritte o colore tuoiImmagini, suono, scritte, colore
Disegnare un luogo in TiledMappe tue
Scrivere una missioneMissioni tue
Capire perché non è comparso nienteNon è comparso niente
Cercare un codice d'erroreOgni codice diagnostico
Sapere che cosa un mod non potrà mai fareChe cosa un mod non potrà mai fare
Non rompere il salvataggio di qualcunoSalvataggi
Metterlo dove la gente può prenderloCondividerlo

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 aggiungendoLe famiglie che lo fannoDove sono scritte
Commercio e mercigoods, vendor_inventories, caravans, recipesCose, commercio e i numeri dietro uno scontro
Cose che un giocatore porta con séitems, combat_balanceCose, commercio e i numeri dietro uno scontro
Personenpc_definitions, mercenary_templates, noble_houses, relationships, perks, enemy_archetypes, enemy_variants, group_archetypesPersone, casati e quello che sanno fare
Luoghi ed edificibuildings, pois, maps, world_generationIl mondo e i luoghi che contiene
Parole che un giocatore leggelocales, dialogue, scenes, lore, mr_lines, quest_plans, quest_metadata, progressStoria, missioni e le parole che un giocatore legge
Come si vede e come suonaimages, audio, fonts, themes, effects, presentation_bindings, screensCome si vede e si sente tutto quanto
Comandi e difficoltàinput_bindings, settings, adaptiveChe cosa controlla il giocatore, e che cosa lo osserva

Che cosa ti serve

Il giocoNecessarioNiente Godot, niente compilatore, nessun passaggio di build.
Un editor di testo che capisca il JSONNecessarioVS Code, Sublime, Notepad++ — tutti gratuiti. Il Blocco note di Windows funziona e non ti aiuterà.
Un editor di pixel artSolo per l'arte tuaAseprite (~20 €), oppure gratuiti: LibreSprite, Piskel, Krita, GIMP.
Un editor audioSolo per il suono tuoAudacity. Effetti brevi dal niente: sfxr, ChipTone.
TiledSolo per le mappe tueGratuito. 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.

VuoiVai aQuanto ci vuole
Aggiungere qualcosa da comprare e vendereUna merce da vendere15 minuti
Aggiungere qualcosa che un giocatore porta con séUn oggetto da portare10 minuti, dopo quello sopra
Aggiungere una persona che lo vendeUn mercante che lo tiene30 minuti
Aggiungere una porta in un insediamentoIl servizio di un edificio20 minuti
Aggiungere un luogo sulla mappa del mondoUn luogo sulla mappa20 minuti
Cambiare qualcosa che il gioco ha giàCambiare quello che c'è già15 minuti
Disegnare una mappa, scrivere una missione, portare arteMappe tue, Missioni tue, Immagini, suono, scritte, colorepiù 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 avutoQui 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àMoneteE
Argilla, pietra, canne1il pavimento. Scavate o tagliate, senza lavoro dentro
Grano, legno2
Candela3una serata di luce
Lana, pesce, uva4
Pane6il cibo di un giorno
Sale, miele, corda8
Stoffa (pezza)10tessuta da 2 lana e 1 canne
Ferro raffinato, pesce salato12
Pepe nero14un'importazione, e si sente
Cuoio, formaggio15
Vino25
Armi a una mano50–300la fascia, non un valore unico
Armi a due mani150–600
Piastra pesante500–1500il 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.json

Parti 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"]
  }
]
CampoPerché questo valore
idIl 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_nameQuello 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.
categoryMANUFACTURED, 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_tierPRESERVED — 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_price9. 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.
weight0,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_classQuale mestiere la fa. chandler è quello che usa il pacchetto di riferimento.
daily_consumption_classChi la consuma. household vuol dire che le città la consumano di continuo, ed è quello che tiene un mercante a rifornirsi.
tagsParole 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.json

Una 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"]
  }
]
CampoPerché questo valore
idUn 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.
categoryMATERIAL, che è quello che è la candela del gioco. Non CONSUMABLE: non si mangia niente.
rarityCOMMON. La rarità è quello che leggono le tabelle del bottino e le botteghe quando tirano; una cosa comune capita.
weight0,4, come la merce. Quando i due non concordano, lo zaino del giocatore e la carovana non concordano sullo stesso oggetto.
max_stack20, 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_value10 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.
sellableVero, 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.json

Questo è 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
      }
    ]
  }
]
CampoPerché questo valore
settlement_idUsa 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_idInsieme 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_multiplier1.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_rate0.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_stock6. 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_days2, 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_standing0: può comprare chiunque. Sopra zero sono scorte che tiene per le persone che le stanno simpatiche.
kindSu 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.json

Stai 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"
  }
]
CampoPerché questo valore
labelLe parole sulla porta. Se la ometti, il gioco mette la maiuscola al tuo id, e si legge come un id.
roleChe 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.
colorMarrone 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_serviceshop — 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.json

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. 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
  }
]
CampoPerché questo valore
kindRUINS — 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_radius2.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_modifier0.0 — non aiuta a vedere. Lascia un numero a zero invece di togliere il campo, quando lo zero è una decisione.
one_time_lootFalso: 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 file

Due 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" }
    ]
  }
]
SceltaPerché
patch, non replacereplace 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 → 4Una 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 tagsL'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 posizionetags.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 aggiuntoDove spuntaL'inghippo
goodsSu 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_inventoriesIl 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.
itemsOvunque 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_definitionsL'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.
buildingsL'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.
poisSulla 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

CampoChe cosa fa
idNell'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.
nameNell'esempio qui sopra. Quello che vede un giocatore. Qui maiuscole e spazi vanno bene.
versionNell'esempio qui sopra. La scegli tu. Alzala ogni volta che cambi qualcosa.
game_versionNell'esempio qui sopra. La build per cui l'hai fatto.
content_typesNell'esempio qui sopra. Le famiglie che porti. Una famiglia che manca da questo elenco non viene mai letta, qualunque cosa ci sia nella cartella.
dependenciesNell'esempio qui sopra. I pacchetti di cui il tuo ha bisogno. Un nome, oppure un oggetto con optional: true.
load_orderNell'esempio qui sopra. Chi va per primo quando due pacchetti toccano la stessa cosa. Il più basso si carica prima.
overridesNell'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_safeNell'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.
rootsLa 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_versionQuale forma di manifesto stai scrivendo. Le operazioni di Cambiare quello che il gioco ha già richiedono la 2. Questa build legge fino alla 2.
typeChe 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.
capabilitiesChe cosa un pacchetto chiederebbe all'ospite, se il livello superiore si aprisse mai. Un campo sconosciuto qui fallisce chiudendo, invece di essere ignorato.
trust_tierNon 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.
supersedesI pacchetti che questo intende scavalcare. Un campo reclamato così smette di essere segnalato come scontro. Anche qui un campo sconosciuto fallisce chiudendo.
fallback_policySu che cosa ripiega un pacchetto quando manca qualcosa che scavalca. Uno fra vanilla, none.
campaignLa campagna che una conversione possiede.
campaign_packageDichiara 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 quest

Nomi 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.description

Le 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 questoLinguaIntestazione di colonna
enEnglishenla lingua di partenza
itItalianoit
frFrançaisfr
deDeutschde
esEspañoles
pt-BRPortuguê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
RegolaPerché
Ogni chiave sta nel tuo spazio dei nominorthern_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 rifiutataNon 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 rispostaViene 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 dueUn 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à

VuoiOperazioneChe cosa ti serve
Aggiungere qualcosa di nuovoaddUn id tuo con il tuo spazio dei nomi. Nient'altro.
Riscrivere uno dei record del giocoreplaceL'id del record elencato in overrides. Un record completo: non eredita niente.
Cambiare un campo e lasciare stare il restopatchoverrides, più "manifest_version": 2 in mod.json.
Ritirare un recordremoveoverrides, 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 }
    ]
  }
]
OperazioneChe cosa faRichiedeRifiuta
addFornire un record nuovo e completo sotto il tuo spazio dei nomi.id con spazio dei nomiun id che esiste già, che venga dal gioco base o da un altro mod
replaceFornire un record completo per un id che esiste già, avendolo dichiarato.sovrascrittura dichiarata, record completoun id assente dal registro, e un id che il manifesto non elenca sotto overrides
patchCambiare campi nominati di un record esistente e lasciare stare il resto.sovrascrittura dichiarata, modificheun id assente dal registro, un campo che la famiglia non permette, e qualunque forma di modifica fuori da patch_operations
removeRitirare un record esistente e lasciare una lapide al suo posto.sovrascrittura dichiarata, famiglia rimovibileun id assente dal registro, e qualunque famiglia non segnata come rimovibile qui sotto

Una patch nomina le sue modifiche una alla volta:

  • set — Scrive value in field, qualunque cosa ci fosse prima. Si scrive con field e value.
  • unset — Toglie field dal record, così chi legge vede il valore predefinito della famiglia. Si scrive con field.
  • append_unique — Aggiunge value all'elenco in field se non c'è già. Si scrive con field e value.
  • remove_value — Toglie ogni occorrenza di value dall'elenco in field. Si scrive con field e value.
  • Nomina un campo per percorso, mai per posizione. tags.0 viene 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 diDecisoProveValori
packagesal caricamentoall_of, none_ofid di mod caricati accanto al tuo
campaignal caricamentois, any_of, not_any_ofla campagna da cui è partita la partita
localeal caricamentois, any_of, not_any_ofla lingua in cui si sta giocando
seasonmentre si giocais, any_of, not_any_ofspring, summer, autumn, winter
weathermentre si giocais, any_of, not_any_ofun id di tempo atmosferico che il gioco ha tirato
day_phasementre si giocais, any_of, not_any_ofdawn, day, dusk, night
daymentre si giocaat_least, at_mostquanti giorni è durata la partita
ProvaPrendeVera quando
isun nomela risposta è esattamente quella
any_ofun elencola risposta è uno di quelli
not_any_ofun elencola risposta non è nessuno di quelli
at_leastun numerola risposta è quella o più alta
at_mostun numerola risposta è quella o più bassa
all_ofun elencoci sono tutti
none_ofun elenconon 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 spring

Un 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.

FamigliaremoveChe cosa succede
goodsRitirato. Si risolve ancora per id, sparito da quello che il gioco offre.
vendor_inventoriesCancellato. La riga viene tolta.
tutto il restonoRifiutato, 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 scontraChe cosa succede
Campi diversi di uno stesso recordSi applicano entrambi. Non si perde niente.
Lo stesso campo sempliceVince 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 interoLo 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_valueNessun 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 sostituisceIl ritiro resta valido. L'operazione successiva viene rifiutata, qualunque sia l'ordine di caricamento.
Due pacchetti che vestono lo stesso soggettoVince il load order più avanti, chi perde è nominato nel resoconto.
Un pacchetto che veste il contenuto di un altro pacchettoRefused.

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.

TipoFileInstallatoChe cosa vuol dire
image.png, .webpIl file viene letto e la texture viene costruita.
audio.ogg, .wavNoI 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, .otfNoI 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
FamigliaCartellaAccettaCampi obbligatori
imagescontent/assets/images.png, .webpid, file, format
audiocontent/assets/audio.ogg, .wav (non compresso)id, file, codec, role
fontscontent/assets/fonts.ttf, .otfid, file, format, sizes, covers, fallback_font
themescontent/assets/themesgettoni di coloreid, tokens
effectscontent/assets/effectsmodelli dell'ospiteid, 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 file che contenga .. o ~, o che cominci con /, \, res:// o user://, 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:

FamigliaCampoChe cos'è
itemsicon_idL'icona su un oggetto che porti tu.
npc_definitionsportrait_idIl ritratto di un NPC con un nome.
perksiconL'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"
  }
]
SlotTu portiDove comparealternative_keyDisegnato
portraitimageLa cornice del dialogo, per l'id di chi parla.obbligatorio
spriteimageUn segnalino di truppa, il terreno della mappa del mondo, o un edificio in un insediamento.
iconimageLe celle dell'inventario, per qualunque oggetto — tuo o del gioco.obbligatorio
bannerimageI colori del casato sulla sua pagina di diario.
voiceaudioSuona quando compare la battuta di chi parla.obbligatorionon ancora
use_soundaudioSuona quando un oggetto viene usato e l'uso ha avuto effetto.non ancora
ambienceaudioVa in ciclo mentre il giocatore sta su quel terreno.non ancora
themethemeQuale delle tue tavolozze indossa l'interfaccia.
fontfontQuale dei tuoi caratteri indossa l'interfaccia.non ancora
effecteffectTempo atmosferico e luce sul terreno a cui è legato.

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.

RuoloPerCursore
musicBraniMusica
ambienceStanze, tempo, luoghiAmbiente
sfxEffetti breviEffetti
voiceBattute parlateEffetti

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 registroPixel 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.
Tasselli16 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'interfacciaI 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"
  }
]
RegolaChe cosa significa
Il corredoTasselli da 16 pixel, ortogonali, destra-basso, finiti.
I livelli sono ruoli, non nomiground, collision e walkable sono obbligatori. Un livello chiamato collisions viene rifiutato invece che ignorato.
La geometria si dichiaraLa 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 nominorthern_reach:towpath, non towpath.
world_originDove 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 cosaUn 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 nienteUna disposizione che viene rifiutata non colloca proprio niente.
Niente percorsiUna 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.

TipoChe cos'è
arcLa storia. Elenca le missioni che contiene.
questL'incarico: chi lo dà, come si chiama, quanto paga.
objectiveUna cosa che il giocatore deve fare.
endingCome 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"]
  }
]
ObiettivoSorvegliato oggi
collect_itemsì — stai portando abbastanza di qualcosa
defeat_unitsì — hai ucciso abbastanza di qualcosa
earn_coinsì — hai abbastanza denaro
reach_placesì — hai visitato un insediamento
survive_dayssì — sono passati abbastanza giorni
speak_to, deliver_item, defend_place, escort_unit, learn_loreno — rifiutati per nome invece di essere accettati e poi mai completabili
RicompensaConsegnata oggi
give_item, receive_coin
change_relationsì, quando il soggetto è il giocatore
gli altri cinquerifiutati 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 un kind. kind dice quale dei quattro record è questo. Una ricompensa scritta con kind si 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.

ControlloPrendeChiedeRisposto oggi
companion_presentcompanionQuel compagno è lì presente a sentirlo.
faction_stancefaction, stanceUna fazione sta dove l'opzione si aspetta.sì, per hostile — qualunque altro valore viene rifiutato prima della prima battuta
has_coincoinIl giocatore se lo può permettere.
has_itemitem, countIl giocatore lo sta portando con sé.
has_knowledgeloreAl giocatore questo è stato detto.
has_traittraitIl giocatore è stato costruito così.
lacks_knowledgeloreAl giocatore questo non è stato ancora detto.
quest_statequest, stateUna missione sta dove l'opzione si aspetta.
relation_at_leastsubject, target, regardUna parte pensa almeno questo dell'altra.
seasonseasonSiamo in quella parte dell'anno.
time_of_dayphaseSiamo in quella parte della giornata.
ComandoPrendeFaEseguito oggi
change_relationsubject, target, deltaModifica una reputazione rispettando le regole sulle relazioni pubblicate dall'host.
give_itemitem, countConsegna qualcosa.
grant_knowledgeloreDice qualcosa al giocatore.
open_shopvendorMette sullo schermo le scorte di un mercante.
pay_coincoinIl giocatore paga.
receive_coincoinIl giocatore viene pagato.
recruit_companioncompanionAggiungi qualcuno al gruppo quando lo consentono le regole di reclutamento pubblicate dall'host.
set_quest_statequest, statePorta 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_combatencounterChiude la conversazione.
take_itemitem, countToglie qualcosa.
travel_todestinationSposta la compagnia.
  • 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_coin o has_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" }
    ]
  }
]
BattutaPrendeTempiGiocata oggi
ask_nameprompt_keyla scena la aspetta
endla scena prosegue
fade_insecondsla scena la aspetta
fade_outsecondsla scena la aspetta
lock_playerla scena prosegue
narrateline_key, secondsla scena la aspetta
play_cuecuela scena prosegue
remove_actoractorla scena prosegue
sayactor, line_keyla scena la aspetta
show_exitla scena prosegue
start_dialoguegraphla scena la aspetta
unlock_playerla scena prosegue
waitsecondsla scena la aspetta
walk_toactor, anchorla scena la aspetta
  • Una scena che toglie i comandi deve restituirli. Una sequenza che finisce senza unlock_player viene 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.json

Il 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.

#SintomoChe cosa dice il validatore
1Il percorso della cartella è sbagliatoWARN: 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.
2L'id non ha i due puntiERROR: add needs an id under your own namespace. frost_blade viene rifiutato; northern_reach:frost_blade viene accettato.
3Il JSON è rottoERROR: 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.
4Il file è nel pacchetto sbagliatoLo 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.
5Manca un campo obbligatorioIl 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=1

Un 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.

FamigliaStatoCartella nel tuo pacchettoComando di resocontoChe cos'è
adaptivePronta all'usocontent/player/adaptivemodding_adaptive_reportProfili che guardano come sta andando una partita e ne suggeriscono un'impostazione diversa.
audioValidato, non viene ancora consumato da nullacontent/assets/audiomodding_audio_reportSuoni 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.
buildingsPronta all'usocontent/world/buildingsmodding_building_reportDefinizioni di edifici e di servizi dell'insediamento: etichetta, colore, ruolo e un interno riusato.
caravansPronta all'usocontent/logistics/caravansmodding_caravan_reportRotte commerciali che una carovana percorre: da dove parte, dove sta andando, che cosa porta, quanto è ben scortata e quanto va veloce.
combat_balancePronta all'usocontent/combat/balancemodding_combat_balance_reportValori di bilanciamento del combattimento, delimitati, che regolano parametri del risolutore già esistenti senza aggiungere regole, operazioni o meccaniche.
dialoguePronta all'usocontent/narrative/dialoguemodding_dialogue_reportConversazioni come record: il grafo, le sue battute e le scelte che ci stanno sopra.
effectsPronta all'usocontent/assets/effectsmodding_effect_reportTempo atmosferico, polvere, scintille e luci, composti a partire dai modelli che l'ospite mette a disposizione.
enemy_archetypesPronta all'usocontent/threat/enemy_archetypesmodding_enemy_archetype_reportTipi di nemico che il livello strategico conosce: grado, quali varianti schierano, dove si accampano, quanto è grande la guarnigione e ogni quanto fanno razzia.
enemy_variantsPronta all'usocontent/combat/enemy_variantsmodding_enemy_variant_reportBlocchi 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.
fontsValidato, non viene ancora consumato da nullacontent/assets/fontsmodding_font_reportCaratteri tipografici che un pacchetto porta, nominati per id: il file, le dimensioni a cui vengono disegnati, e le lingue di cui portano i glifi.
goodsPronta all'usocontent/economy/goodsmodding_goods_reportMerci commerciabili e le loro proprietà economiche.
group_archetypesPronta all'usocontent/strategic/group_archetypesmodding_group_archetype_reportParametri 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.
imagesPronta all'usocontent/assets/imagesmodding_image_reportImmagini che un pacchetto porta, nominate per id: icone, ritratti e fogli di sprite, ciascuna che punta a un file dentro la propria cartella.
input_bindingsPronta all'usocontent/inputmodding_input_reportAzioni proprie di un pacchetto, con il tasto che vorrebbero.
itemsPronta all'usocontent/inventory/itemsmodding_items_reportOggetti d'inventario, armi e armature comprese.
localesPronta all'usocontent/localemodding_locale_reportLe 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.
lorePronta all'usocontent/narrative/loremodding_lore_reportVoci del Codex: luoghi, persone, eventi, usanze e cose su cui un mondo racconta storie.
mapsPronta all'usocontent/world/mapsmodding_map_reportDisposizioni che un pacchetto disegna in Tiled, nominate per id: il file, dove sta nel mondo, e la chiave di lingua con cui è conosciuta.
mercenary_templatesPronta all'usocontent/character/mercenariesmodding_mercenary_reportModelli di mercenari assoldabili: nome, classe, provenienza, salute e morale iniziali, costo d'ingaggio e il giorno in cui compaiono per la prima volta.
mr_linesPronta all'usocontent/medieval_realism/structuredmodding_mr_lines_reportRighe strutturate di realismo medievale, indirizzate per file e id di riga invece che per un campo id nel JSON.
noble_housesPronta all'usocontent/politics/noble_housesmodding_noble_house_reportDati iniziali di un casato nobiliare: il signore, l'erede, quali insediamenti rispondono al casato, e chi conta come rivale o alleato.
npc_definitionsPronta all'usocontent/narrative/npcsmodding_npc_reportDefinizioni di NPC con un nome.
perksPronta all'usocontent/character/perksmodding_perk_reportPrivilegi dichiarativi: inneschi ed effetti, senza nessun gestore scritto in codice.
poisPronta all'usocontent/world/poismodding_poi_reportPunti d'interesse collocati per coordinate sulla mappa del mondo scritta a mano.
presentation_bindingsPronta all'usocontent/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.
progressPronta all'usocontent/player/progress-Record di progressione del giocatore: obiettivi, profili di difficoltà sicuri e profili di partita entro le regole dell'ospite.
quest_metadataPronta all'usocontent/narrative/quest_metadatamodding_quest_metadata_reportRecord di metadati delle missioni, indicizzati per quest_id invece che per id.
quest_plansPronta all'usocontent/narrative/quest_plansmodding_quest_plan_reportPiani 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.
questsControllata, non ancora installatacontent/narrative/quests-Risorse di missione scritte a mano, caricate per percorso invece che interpretate come record.
recipesPronta all'usocontent/economy/recipes-Ricette di artigianato: che cosa si consuma, che cosa ne esce, dove si lavora, quanto costa e quanto è probabile che vada male.
relationshipsPronta all'usocontent/companion/relationships-Modelli di compagni, politiche di rapporto delimitate, condizioni di reclutamento e legami dichiarativi.
scenesPronta all'usocontent/narrative/scenesmodding_scene_reportScene messe in scena: la stanza, chi ci sta dentro e le battute che si svolgono in ordine.
screensPronta all'usocontent/ui/screensmodding_screen_reportDisposizioni di schermata: quali sezioni stiano in quale pannello di una schermata che il gioco ha già, e in che ordine.
settingsPronta all'usocontent/settingsmodding_settings_reportOpzioni che un giocatore può cambiare, dichiarate invece che disegnate.
themesPronta all'usocontent/assets/themesmodding_theme_reportTavolozze dell'interfaccia come gettoni: colori con un nome, dimensioni e spaziature, con le coppie il cui contrasto un giocatore deve poter leggere.
vendor_inventoriesPronta all'usocontent/world/vendor_inventoriesmodding_vendor_inventory_reportTabelle delle scorte dei mercanti.
world_generationPronta all'usocontent/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:

SarebbeDove andrebbeChe cos'è
feature_extensionancora nessuna cartellaUn 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:

RispostaChe cosa fa il salvataggio
preserve_inert_referenceL'id resta, non si risolve in niente, e viene segnalato. Quello che il giocatore aveva ha ancora un nome.
substitute_placeholderRisponde un sostituto stabile posseduto dal motore, così il mondo si carica lo stesso, e l'id originale viene conservato accanto.
drop_optional_presentationIl 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.

CampoNecessarioValori
idtesto, id
rolestringa
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.

CampoNecessarioValori
idtesto, id
origin_settlement_idstringa
destination_settlement_idstringa
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.

CampoNecessarioValori
idtesto, id
filetesto, fixed shape
name_keystringa
world_originelenco 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.

CampoNecessarioValori
idtesto, id
display_namestringa
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.

CampoNecessarioValori
kindqualunque
idtesto, id
streamtesto, id
tablesoggetto
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.

CampoNecessarioValori
idtesto, 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.

CampoNecessarioValori
idtesto, id
archetype_idstringa
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.

CampoNecessarioValori
idtesto, 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.

CampoNecessarioValori
idtesto, id
display_namestringa
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.

CampoNecessarioValori
idtesto, 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.

CampoNecessarioValori
idtesto, id
display_namestringa
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.

CampoNecessarioValori
idtesto, id
skilltesto, fixed shape
name_keystringa
kindroad, junction, lateral, capstone
colintero da 0 a 4
rowintero da 1 a 7
levelintero 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:

CampoNecessarioValori
idtesto, id
kindbond
relationstringa
subjectstringa
targetstringa
initial_regardintero da -100 a 100
policystringa
description_key-stringa
name_key-stringa
note_key-stringa

Un record con kind: companion_template:

CampoNecessarioValori
idtesto, id
kindcompanion_template
unitstringa
recruitstringa
loyaltystringa
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:

CampoNecessarioValori
idtesto, id
kindrecruit_terms
meansstringa
cost-intero da 0 a 1000000
description_key-stringa
name_key-stringa
requires_bond-stringa

Un record con kind: relationship_policy:

CampoNecessarioValori
idtesto, id
kindrelationship_policy
relation_kindselenco di stringhe
boundsoggetto
bandselenco 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.

CampoNecessarioValori
idtesto, id
valuesoggetto

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.

CampoNecessarioValori
idtesto, 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.

CampoNecessarioValori
idtesto, 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.

CampoNecessarioValori
idtesto, id
inputsoggetto
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.

CampoNecessarioValori
idtesto, id
display_namestringa
entrieselenco 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:

CampoNecessarioValori
kinddialogue_graph
idstringa
entrystringa
description_key-testo, fixed shape
name_key-testo, fixed shape
speaker-stringa

Un record con kind: dialogue_node:

CampoNecessarioValori
kinddialogue_node
idstringa
graphqualunque
voiceline
speakerstringa
line_keyqualunque
conditions-qualunque
description_key-qualunque
name_key-qualunque
reveals-qualunque

Un record con kind: dialogue_node:

CampoNecessarioValori
kinddialogue_node
idstringa
graphqualunque
voicenarration
line_keyqualunque
conditions-qualunque
description_key-qualunque
name_key-qualunque
reveals-qualunque

Un record con kind: dialogue_node:

CampoNecessarioValori
kinddialogue_node
idstringa
graphqualunque
voiceend
conditions-qualunque
description_key-qualunque
line_key-qualunque
name_key-qualunque
reveals-qualunque

Un record con kind: dialogue_option:

CampoNecessarioValori
kinddialogue_option
idstringa
nodestringa
label_keytesto, fixed shape
gotostringa
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.

ColonnaNecessarioValori
keytesto, 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 Brina

lore

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.

CampoNecessarioValori
idtesto, id
categoryplace, person, event, custom, thing
title_keystringa
body_keystringa
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.

ColonnaNecessarioValori
line_idtesto, 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_only

progress

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:

CampoNecessarioValori
idtesto, id
kindachievement
name_keystringa
description_keystringa
conditionelenco di oggetti
campaign-stringa
hidden-booleano
icon-banner, blade, coin, crown, hand, road, …

Un record con kind: difficulty_profile:

CampoNecessarioValori
idtesto, id
kinddifficulty_profile
name_keystringa
modifiersoggetto
campaign-stringa
description_key-stringa
permadeath-booleano

Un record con kind: run_profile:

CampoNecessarioValori
idtesto, id
kindrun_profile
name_keystringa
difficultystringa
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.

CampoNecessarioValori
quest_idtesto, 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:

CampoNecessarioValori
kindqualunque
idtesto, id
stageselenco
description_key-testo, fixed shape
name_key-testo, fixed shape

Un record con kind: ending:

CampoNecessarioValori
kindqualunque
idtesto, id
arcstringa
requireselenco
description_key-testo, fixed shape
epilogue_key-testo, fixed shape
name_key-testo, fixed shape

Un record con kind: objective:

CampoNecessarioValori
kindqualunque
idtesto, id
queststringa
goalcollect_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:

CampoNecessarioValori
kindqualunque
idtesto, id
name_keytesto, fixed shape
giverstringa
objectiveselenco
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.

CampoNecessarioValori
idtesto, id
beatselenco 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.

CampoNecessarioValori
idtesto, id
filetesto, fixed shape
codecogg, wav
rolemusic, 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.

CampoNecessarioValori
idtesto, id
templatedust_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.

CampoNecessarioValori
idtesto, id
filetesto, fixed shape
formatttf, otf
sizeselenco di interi da 8 a 96
coverselenco
fallback_fontstringa
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.

CampoNecessarioValori
idtesto, id
filetesto, fixed shape
formatpng, 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.

CampoNecessarioValori
idtesto, id
subjecttesto, id
kindbuilding, faction, interface, item, region, tile, …
slotambience, banner, effect, font, icon, portrait, …
cuetesto, 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.

CampoNecessarioValori
idtesto, id
screencharacter_sheet
panelsoggetto

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.

CampoNecessarioValori
idtesto, id
tokensoggetto
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:

CampoNecessarioValori
kindqualunque
idtesto, id
name_keytesto, fixed shape
policyenemy_composition, event_cadence, hint_frequency, pace_economy, pace_encounters, weather_variety
readselenco
fallback_policyenemy_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:

CampoNecessarioValori
kindqualunque
idtesto, id
profiletesto, id
thresholdselenco 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.

CampoNecessarioValori
action_idtesto, id
label_keystringa
contextexploration, combat, menu, global
suggested_keyboardstringa
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.

CampoNecessarioValori
keytesto, id
typebool, int, float, string, enum
defaultqualunque
scopeinstallation, campaign, presentation
label_keystringa
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.

ComandoLa stessa cosa sulla schermata Mod
modding_open_folderil percorso in cima, e il pulsante accanto
modding_manifest_reportla colonna dello stato, e la riga sotto ciascuna riga
modding_<family>_reporti conteggi sotto ogni pacchetto, e Mostra i dettagli
modding_preflight_reportVerifica compatibilità
modding_roots_report, modding_safety_reportCopia il resoconto
modding_reloadNessun 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 load

modding_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.

ComandoChe cosa ti dice
modding_roots_reportRadici e impronte dei mod di dati
modding_manifest_reportStati dei mod (attivo/non valido/ignorato/in conflitto)
modding_fingerprint_reportImpronte deterministiche dei salvataggi (save_wired=no)
modding_safety_reportPostura di sicurezza (mod di comportamento spenti, file bloccati)
modding_preflight_reportVerdetto VERDE/ROSSO sull'insieme dei mod attivi
modding_packaging_reportRilevamento PCK/ZIP di livello 2 (disattivato per impostazione predefinita)
modding_campaign_reportModding_campaign_report [id] - campagne installate in sola lettura; con un id, ci si passa
modding_condition_reportChe cosa pubblica il mondo per le condizioni dei record
modding_reloadModding_reload [all] - rilegge i pacchetti; all solo se non c'è nessuna partita in corso
modding_binding_reportCollegamenti di presentazione: legati/rifiutati/scavalcati
modding_open_folderCrea (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 items

Scrive 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" --json

La 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-baseline

Questo è 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>" --json

Legge 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-runtime

Il 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.

CodiceChe cosa l'ha causatoChe cosa fare
adaptive_brings_a_modelUn 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_backUn 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_invalidIl 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_budgetUn 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_keyUna 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_stepUna 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_referenceUn 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_referenceUna 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_leakedLo 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_aspectUna 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_budgetLa 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_refusedNon è 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_affordanceUn 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_invalidUn 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_mismatchChi 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_missingIl 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_missingNessun 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_refusedUn 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_usedUn 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_refusedUn 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_overranUn 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_invalidUn 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_alternativeInformazione 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_budgetLa 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_usedUn 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_recordedUn 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_offeredViene 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_unwritableIl 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_rejectedUn 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_offeredSotto 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_offeredIl 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_exceededL'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_degradedUna 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_exceededUn 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_warningOltre 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_profileUn 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_identityUn 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_invalidLa 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_handlerDati 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_invalidIl 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_missingUn 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_unenterableUn 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_propertyUna 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_formulaUn 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_expiredUno 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_invalidIl 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_budgetUn 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_unreachableUna 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_operationUn'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_statusUno 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_referenceUn 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_referenceUn 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_allowedUna 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_unclassifiedUna 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_fileUn 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_familyUna 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_missingUna 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_familyUna 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_familyLa 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_leakUn 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_expressionUn 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_endUna 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_invalidIl 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_nodeUn 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_budgetUn 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_keyUna 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_revealUn 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_stepUn 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_referenceUn 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_mismatchI 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_invalidIl 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_offlineLa 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_reportedQualcuno 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_revokedIl 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_refusedUn 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_invalidIl 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_boundsUn 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_overriddenUn 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_referenceUna 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_sourceUn 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_degradedUn 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_droppedUn 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_refusedUn 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_fieldIl 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_namespaceLo 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_fieldManca 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_incompleteTogliere 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_unboundedUn 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_capabilityL'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_autoloadIl 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_fallbackUn 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_refusedUn 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_refusedUn'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_gridUn 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_mismatchByte 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_usedUn'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_refusedUn'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_cancelledUn'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_mismatchI 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_fieldLa 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_refusedLa 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_fieldA 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_rejectedLa 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_unboundedUn 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_formatIl 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_platformIl 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_conflictIl 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_orphanedUna 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_actionUn 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_fieldLa 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_namespaceL'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_unreachableL'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_fieldA 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_chordUn 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_contextIl 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_invalidIl 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_definitionUn 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_replacedUn 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_referenceUn 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_textTesto 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_dataUn 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_pathUna 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_anchorDue 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_invalidLa 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_mismatchUna 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_missingUn 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_failedLa 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_packageUn 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_budgetUna 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_referenceUn 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_subsetQualcosa 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_surfaceUn 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_collisionUna 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_failedIl 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_vanillaUna 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_requiredL'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_invalidIl 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_lostUn 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_budgetUn 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_outsideUn 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_namespaceUn 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_keyUna 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_stepUna 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_referenceUn 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_capabilityUn 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_inactiveIl 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_capabilityUn 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_kindUn 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_untrustedIl 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_requiredIl 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_appliedUn 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_expressionUn 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_unreachableUn 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_invalidIl 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_appliedUn 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_budgetUn 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_keyUna 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_unfinishableUna 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_stepUn 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_referenceUn 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_gapUn 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_codeUn 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_stateUn 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_invalidIl 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_unreachableUn 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_lostIl 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_collisionUna 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_relationUn 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_referenceUn 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_invalidatedVoci 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_missingNessuno 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_budgetUn 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_refusedUna 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_requiredUn 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_tombstonedUn 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_absentLa 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_matchesNiente 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_absentContenuto 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_carriedStato 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_movedUna 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_originalLa 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_missingLa 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_modeDei 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_preservedUn 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_invalidLa 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_migratedUn 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_missingUn 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_requiredIl 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_withheldUn 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_refusedUn 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_unresolvedUn 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_pathUn 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_invalidUn 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_absentUn 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_budgetPiù 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_keyUn 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_serviceUn 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_referenceUn 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_leakUna 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_pathUn'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_invalidIl 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_definitionUna 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_collisionLa 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_sidedUna 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_referenceUn 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_ignoredIl 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_malformedUno 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_orphanedNessun 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_rejectedIl 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_reservedUn 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_futureStato 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_migratedStato 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_oldStato 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_namespaceChi 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_policyUn 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_invalidIl 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_budgetUn 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_keyUna 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_termUna 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_referenceUn 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_weightlessUn 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_executableUn 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_lowUna 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_refusedUn tema che questa build non registra.Leggi la proprietà che il resoconto nomina e riportala dentro quello che permette.
tombstone_blocks_campaignLa 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_substitutedAl 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_recordedUn 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_recoveredIl 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_referenceQualcosa 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_codeUn 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_categoryUn'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_invalidIl 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_behaviourUn 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_referenceUn 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_missingUn 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_inconsistentUn 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_controlUn 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_randomnessUn 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_invalidIl 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_referenceUn 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 codiceScript, estensioni, eseguibili, file di shell — in qualunque punto del tuo pacchetto.
Niente scene né file di risorsaUn record che ne punta uno viene rifiutato anche se il file non c'è.
Niente oscuramento dei file baseUn mod aggiunge e cambia record; non può sostituire i file del gioco.
Nessun tipo nuovo di cosaUn privilegio nuovo sì, un tipo nuovo di privilegio no.
Niente comandi, autoload o impostazioni di progettoNon raggiungibili per niente.
Niente cancellazioni vere e proprieremove 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:// o user://. 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.
DimensioneUn pacchettoTutti quantiSe lo supera
records20 000120 000reject
decoded_image_bytes256 MB1 GBreject
decoded_audio_bytes128 MB512 MBreject
map_cells4 194 3048 388 608reject
map_objects65 536262 144reject
effect_instances4 09616 384degrade
provider_frame_usec2 0008 000degrade
worker_tasks832reject
queue_depth5122 048degrade
teardown_msec100400warn

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.

RegolaPerché
Non rinominare mai un idOgni salvataggio che lo usava resta a piedi. Aggiungine uno nuovo e lascia stare il vecchio.
Disinstallarti non cancella mai le cose di un giocatoreIl 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.

VerdettoPuò scrivere il tuo salvataggioChe cosa significa
compatibleLa composizione corrisponde a quella sotto cui è stato fatto il salvataggio.
degradedCapito, con del contenuto nominato assente. Si continua a giocare e l'assenza viene segnalata.
incompatibleNo, il file viene lasciato stareLa sessione non può onorare quello che dice il salvataggio. Il file originale viene lasciato stare.
Che cosa differisceVerdettoChe cosa significa
identical_compositioncompatibleStessi pacchetti, stesse versioni, stessa composizione.
mod_addedcompatibleUn pacchetto di cui il salvataggio non ha mai saputo niente. Niente di quello che aveva registrato si è mosso.
mod_missingdegradedUn pacchetto che il salvataggio nominava non è installato. I suoi id sono ancora nel file e ci restano.
mod_upgraded_compatibledegradedUn pacchetto è cambiato restando dentro la compatibilità che dichiara. Segnalato, perché un hash cambiato è una risposta cambiata anche quando è una risposta legittima.
provider_contract_incompatibleincompatibleUna 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_missingincompatibleLa campagna stessa è assente. Ogni id nel file appartiene a un mondo che non è installato.
safe_mode_disableddegradedLa sessione è partita con i pacchetti spenti di proposito. Il salvataggio è leggibile e il suo contenuto modificato è assente per scelta.
orphan_state_preserveddegradedStato 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.

PassoChe cosa
ControlloIl validatore pulito, con --strict, prima di caricare.
ZipLa cartella stessa, così l'archivio contiene my_mod/mod.json.
VersioneAlza version in mod.json a ogni caricamento.
RequisitiElenca 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 portaCampi
Chi èstable_id, version
Da dove vieneauthor, license, source_url, package_hash
Che cosa ne dice un negoziocontent_rating, content_warnings, revocation_status
Come è stato consegnatostore, store_id, subscription_id
StatoSi installaChe cosa significa
noneNon è stato segnalato niente.
reportedQualcuno l'ha segnalato e non è stato deciso niente. Il giocatore viene avvisato e sceglie.
quarantinedNoTrattenuto in attesa di una decisione. Non si installa e quello che è già installato non viene cancellato.
revokedNoRitirato. 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 è:

VerdettoChe cosa significa per te
supportedLa build che hai nominato è questa, o abbastanza vicina. Niente da fare.
older_buildHai costruito contro un gioco più vecchio. Si carica lo stesso, e da quello che si è spostato nel frattempo verrebbe l'eventuale sorpresa.
newer_buildHai 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à.
unreadableLa 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:

ClasseChe cosa significaChe cosa ti deve il gioco
invariatoNiente che un pacchetto possa osservare si è spostato.nessuna
additivoEsiste qualcosa di nuovo e tutto quello che c'era significa ancora quello che significava.un incremento minore
rompenteUn 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.

DomandaRisposta
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

ReleaseDataChe cosa si rompeChe 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 fallitoA che cosa punta
discoveryLeggere che cosa è installato. Un fallimento qui è di solito un pacchetto malformato.
provider_startAvviare quello che la composizione ha selezionato. Un fallimento qui nomina una capacità.
first_sceneLa 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.

SostituisceNon 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 cosaCome
Il manifestotype: 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 budgetQuattro 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 giocoDi 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 è tuoI 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 giocoRiferisciti 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 gratuitiNessuna 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 beneUn 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 permessoUn 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 predefinitaChiunque può tradurre il tuo pacchetto e pubblicare la traduzione, citandoti. Dillo sulla tua pagina se preferisci che te lo chiedano prima.
Il riuso chiede primaCostruire 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.

Revisionato rispetto alla build: 2026-08-16. Ogni etichetta indica uno stato, non una promessa.Leggi le etichette →