Documentación de WeiDU

Westley Weimer
weimer@cs.berkeley.edu




Índice
1 Sobre WeiDU

La página principal de WeiDU es: http://www.cs.berkeley.edu/~weimer/bgate/. Te recomiendo encarecidamente que descargues la última versión.

WeiDU está diseñado para hacer más fácil la escritura y distribución de modificaciones de los juegos del Infinity Engine. Puede cargar y modificar los recursos del Infinity Engine de acuerdo a las ordenes que introduzcas. WeiDU es ideal para empaquetar modificaciones que incluyan diálogo o que deban ser compatibles con otras modificaciones.

Seré honesto: Al principio, WeiDU es más difícil de usar que algunas de sus alternaticas. Sin embargo, la mayoría de los usuarios dicen que: 1) Las alternativas son insuficientes porque carecen de la capacidad que sólo WeiDU ofrece, y 2) WeiDU te engancha y mejora con el tiempo.

Eres bienvenido/a a usar estas utilidades para crear y distribuír tus propios módulos del Infinity Engine. Esta utilidad está bajo la GNU General Public License , pero puedes distribuir una copia binaria sin modificar de WeiDU.EXE (sin el código fuente) con tu módulo si lo deseas.

Decidí crear mis propias utilidades de DLG y TLK del Infinity Engine porque no pude conseguir que el TeamBG DLG Editor y el Mass Converter trabajaran correctamente. No analizaban las cadenas gramaticalmente o mutilaban los textos o fallaban aleatoriamente... estaba completamente mal. Además eran todos GUIs (Grafic User Interface). Como un creyente de Unix estaba enamorado de las utilidades de líneas de comando y como un estudiante de investigación PL, me encanta hacer pequeños lenguajes y compiladores. WeiDU fue originalmente una familia de pequeños programas con nombres poco imaginativos como DC, DD y TP. El término ``WeiDU'', más atractivo (el cual rima con ``IDU'', Eye-Dee-You) fué acuñado por Jason Compton y Ghreyfain, autores notables de módulos de Baldur's Gate II.

2 ¡No tengas miedo!

Paso a paso, una guía para principiantes de WeiDU:
  1. No temas. Muchos como tu son niños en la era GUI. Pero los programas que trabajan con líneas de comando pueden ser tus amigos, y al final te darás cuenta de que trabajan más rápido y, si, son más fáciles de usar.

  2. La mejor forma de aprender como escribir código en formato D de WeiDU es Leyendo código escrito en formato D de WeiDU. Comienza decompilando los DLGs existentes en el juego que entiendas y léelos completamente. Compara como aparecen en WeiDU con como aparecen en otras herramientas de edición del BG2, herramientas con las cuales te sientes más a gusto, como el Near Infinity o el Infinity Explorer.

  3. La mejor manera de escribir código en formato D de WeiDU es leer código escrito en formato D de WeiDU, Parte 2. Un creciente número de paquetes de adiciones al BG2 están siendo creadas usando WeiDU. Hay una lista disponible en http://www.cs.berkeley.edu/~weimer/bgate/weidumods.html. Estos pueden ayudarte a entender los rasgos avanzados de WeiDU, como el anexo de diálogo, scripts y la edición de los 2DA, y la introducción de objetos/conjuros/criaturas trabajando en el escenario del ``mundo real''. Intenta descargar algunos para entender COMO trabajan.

  4. Echa un vistazo a algunos de los ejemplos de este documento. Hay un tutorial de WeiDU muy bueno (escrito por Japheth) disponible en http://dragon-forge.fwstudios.net/tutorial-weidu.htm. Si te estás sintiendo abrumado, empieza con ese, que también cubre la instalación. Ghreyfain también tiene un tutorial de ``Cómo crear un NPC con WeiDU'' en http://forums.db-forge.com/forgottenwars/index.php?board=13;action=display;threadid=678

  5. Finalmente, hay un foro de discusión de WeiDU en http://forums.fwstudios.net/index.php?act=SF&f=50.
3 D y DLG: Conceptos básicos

Esta sección es una introdicción suave a como están estructurados los archivos DLG del Infinity Engine. Primero, vamos a usar WeiDU para crear SCSARLES.D y echar un vistazo al diálogo de Sir Sarles.

Puedes instalar WeiDU.exe en cualquier parte de tu sistema. Sin embargo, te recomiendo que lo coloques en el directorio de instalación de tu Baldur's Gate 2. Aún así, WeiDU usará el Registro de Windows para intentar localizar los archivos del BG2.

Para lograr el efecto descrito, abre una ventana DOS y colócate en tu directorio del BG2. Luego solo escribe el texto en rojo en la linea de comandos del DOS.

C:\Archivos de Programa\Black Isle\BGII - SoA\> weidu SCSARLES.DLG


Esto creará un archivo de texto llamado SCSARLES.D en el directorio actual. Ábrelo con el NotePad o el Microsoft Word o algo de eso. Solo es un archivo de texto que describe el diálogo del juego.

Se verá algo así como:
// creator  : c:\bgate\weidu\weidu.asm.exe
// argument : SCSARLES.DLG
// game     : C:\Program Files\Black Isle\BGII - SoA
// source   : C:\Program Files\Black Isle\BGII - SoA\data\Dialog.bif
// dialog   : C:\Program Files\Black Isle\BGII - SoA\\t{DIALOG.}\ttref{TLK}
// dialogF  : (none)

BEGIN ~SCSARLES~

IF ~NumTimesTalkedTo(0)~ THEN BEGIN 0 // from:
  SAY #28655 /* ~¿Quién es? ¿Se puede saber por qué me has interrumpido mientras
    meditaba? A mi musa creativa hay que despertarla dulcemente y tu
    estruendo no es nada apropiado.~ [SARLES02] */
  IF ~~ THEN REPLY #28656 /* ~Perdón. Te dejaré con tus
    pensamientos.~ */ GOTO 1
  IF ~~ THEN REPLY #28657 /* ~Lo siento, pero he venido en busca de tu
    talento para un encargo artístico.~ */
      DO ~SetGlobal("TalkedToSarles","GLOBAL",1)~ GOTO 2
END

IF ~~ THEN BEGIN 1 // from: 0.0
  SAY #28661 /* ~Entonces olvidaré incluso que alguna vez estuviste aquí. Lo cierto es que es 
    increíblemente fácil de hacer.~ */
  IF ~~ THEN DO ~SetNumTimesTalkedTo(0)~ EXIT
END
Los diálogos en los juegos del Infinity Engine se comportan como máquinas de estado finito. Si no estás familiarizado con el concepto de máquinas de estado finito, mira http://whatis.techtarget.com/definition/0,,sid9_gci213052,00.html or http://www.c3.lanl.gov/mega-math/workbk/machine/mabkgd.html. Cada bloque de la forma:
  IF ~Condición inicial~ THEN BEGIN situación1 
    SAY ~Algo~
    IF ~Condición de respuesta~ THEN REPLY ~Texto de respuesta~ GOTO situación2
  END
representa una situación (más detalles abajo). Cuando el jugador comienza una conversación con un NPC, el engine del juego explora a través de todas las situaciones en el archivo DLG de ese personaje en un orden especial de carga (WEIGHT) y toma la única que tiene una "Condición Inicial" no-vacía y verdadera. Si ninguna situación tiene una "Condición Inicial" no-vacía y verdadera, entonces consigues que aparezca el mensaje ``Bob - No tiene nada para decirte.''. No te preocupes por el de carga por ahora.

El interlocutor (en este caso, Sir Sarles) entonces dirá cualquier cosa que aparezca luego de SAY. Las líneas REPLY representan las respuestas que el personaje del jugador puede regresar. Si la "Condición de Respuesta" es verdadera, al jugador le es concedida la opción de decir el "Texto de Respuesta" y moverse a otra situación en el diálogo (donde Sarles probablemente dirá algo más).

Recuerda: SAY es para lo que dicen los NPCs, REPLY es para lo que los jugadores responden. Si lo piensas bien, notarás que todos los diálogos en los juegos del Infinity Engine están estructurados de esta manera.

Las condiciones tienen la misma sintaxis que se usa en los scripts BCS en el Infinity Engine. Necesitarás aprender scripting del Infinity Engine dentro de poco. Las cadenas (de caracteres o strings en los lenguajes de programación) son definidas entre tildes o "" (a tu elección, pero WeiDU esa el tilde por defecto). Después de SAY o REPLY o JOURNAL puedes dar dos cadenas en lugar de una. La primera es usada con el DIALOG.TLK, la segunda es usada con el DIALOGF.TLK (para las lenguas extranjeras, cuando el personaje principal es femenino). Si no das dos cadenas, la única que diste se usa para ambos.

También puedes usar simples números precedidos con un signo de número (como #1234) para especificar una referencia dentro del directorio del DIALOG.TLK. Esto es útil cuando estás modificando diálogos existentes (digamos, el Espíritu del Destino en ToB). Entonces si un usuario extranjero instala tu diálogo, mantendrá todas las versiones extranjeras de las cadenas que no cambiaste o añadiste. Normalmente los números de referencia de las cadenas son puestos a la derecha después de la palabra clave SAY y la frase es puesta luego en comentarios. La línea de comando --text hace que el texto sea emitido junto con su número de referencia en comentarios.

También puedes indicar que un archivo de sonido (WAV/WAVC) debe ser asociado con la cadena dada, este incluye un nombre de recurso de no más de 8 letras, en [corchetes] luego de la frase, como en:
  SAY ~Hola~ [HELLO]
Los comentarios son al estilo de C/C++: desde // hasta el fin de la línea es un comentario, como lo es /* todo entre estos signos (barra y estrella) */. Los comentarios son ignorados por WeiDU. Son para tu beneficio. Ejemplo::
  SAY ~Hola~ [HELLO]   // esto es un comentario... ¡y aquí termina!
  IF /* Esto también es un comentario */ ~~ THEN EXIT
Las respuestas también pueden contener acciones (usando la palabra clave DO), la cual se comporta igual que las acciones de los scripts BCS del Infinity Engine. También pueden agregar entradas al diario, terminar el diálogo o transferirlo a otro hablante.

Ejemplos:
  IF ~~ THEN BEGIN 2 // from: 0.1
La línea marca el comienzo de la situación 2 en el diálogo. El comentario te dice que puede ser alcanzado en la primera transicion de la respuesta de la situación 0.
  IF ~~ THEN REPLY ~Perdón. Te dejaré con tus pensamientos
~ // #28656 
      GOTO 1
Este REPLY siempre puede ser elegido e involucra el texto hablado "Perdón...". Ese texto es la cadena con el número de referencia 28656. Si el jugador elige esa respuesta, se translada a la situación 1.

Finalmente, una transición también puede tomar esta forma:
  COPY_TRANS filename label
N. del T: Filename: Nombre del Archivo. Label: Etiqueta

Durante el proceso, COPY_TRANS será reemplazado por todas las transiciones de la situación "label" del archivo "filename". Las copias ocupan un puesto antes de todas las otras acciones D.

4 Formato de diálogo D

El formato de archivo D es una manera de describir los diálogos del Infinity Engine y los diálogos de sus modulos en un formato portable y sencillo de comprender. Soporta traducciones a idiomas extranjeros y te permite escribir extensiones a los diálogos ya existentes del juego sin forzarte e escribir de vuelta la parte que no se modificará. Esto te permitirá escribir módulos que trabajen con otros módulos escritos por otras personas.

El formato de archivoD es presentado aquí en un extenso libre contexto con notaciones gramáticales . Si no estás familiarizado con los CFGs, echa un vistazo a http://www.wikipedia.com/wiki/Context-free_grammar, http://cs.wpi.edu/~kal/PLT/PLT2.1.2.html o http://www.cs.rochester.edu/users/faculty/nelson/courses/csc_173/grammars/cfg.html. Sin embargo, no necesitas realmente comprender un CFG como es debido.

Para tener una idea real de como funcionan, usa WeiDU para crear JAHEIRA.D para ti y míralo en el editor de texto. También puedes explorar los directorios examples y test que vienen con WeiDU.

Todas las palabras clave de sintaxis son dadas en COURIER MAYÚSCULA. Todas las otras palabras clave son complementarias. Notas:
Archivo D   Un archivo D es un archivo de texto que contiene un número de Acciones D. Los Archivos D le dicen a WeiDU como crear y modificar los archivos DLG del Infinity Engine.
Es Acción D lista Un archivo D es una lista de acciones D. Generalmente la primera y única es BEGIN, la cual define el contenido de un nuevo diálogo. Otras acciones D pueden ser usados para modificar diálogos existentes.
 
Acción D   Una acción D le dice a WeiDU como crear o modificar archivos DLG del Infinity Engine.
Es BEGIN Nombre del Archivo [ nonPausing ] situación lista BEGIN le dice a WeiDU que tu estás creando un nuevo archivo DLG. Cualquier archivo DLG con el mismo nombre será sobreescrito. El nuevo archivo DLG contiene exactamente las situaciones en la lista. Si fijas nonPausing en un entero distinto a cero, el juego no ``parará el tiempo'' mientras las conversaciones toman lugar. Por defecto, el tiempo se detiene durante las conversaciones.
o APPEND Nombre del Archivo situación lista END Esto le dice a WeiDU que coloque las situaciones dadas al final de un archivo filename.DLG ya existente.
o CHAIN [ IF [ WEIGHT #weight ] stateTriggerString THEN ] entryFilename entryLabel chainText lista chainEpilogue Esto indica a WeiDU como hacer una larga conversación en la cual el personaje del jugador puede no decir nada. Esto es útil cuando quieres que los NPCs hablen entre ellos por largo tiempo. CHAIN y sus amigos, INTERJECT y INTERJECT_COPY_TRANS pueden ser extremadamente eficientes cuando estás escribiendo conversasiones no triviales. Mira los ejemplos para hacerte la idea. CHAIN solo adjuntará a los diálogos existentes. No puedes usar CHAIN para crear un nuevo DLG.
o INTERJECT entryFilename entryLabel globalVariable chainText lista exitFilename exitLabel Se comporta como CHAIN excepto que el chainText es guardado adicionalmente por el predicado transicion Global("globalVariable","GLOBAL",0) y acompañado por la acción SetGlobal("globalVariable","GLOBAL",1). Si tomas globalVariable para ser único, esto se asegurará de que chainText es visto sólo una vez por juego. Esto es útil para hacer interjecciones.
o INTERJECT_COPY_TRANS entryFilename entryLabel globalVariable chainText lista Esto se comporta justo como INTERJECT excepto que el exitFilename y el exitLabel no estás presentes. En lugar de eso, En lugar de eso, cuando quiera que el diálogo desapareciera del chainText lo seguiría una copia de las transiciones que estaban en la situación con stateLabel originalmente. Esto es conveniente para hacer interjecciones rápidas para NPCs que no cambien el flujo verdadero de la conversación. Mira la transicion COPY_TRANS para más información acerca de esta idea.
o EXTEND_TOP archivo stateLabel lista [ #positionNumber ] transicion lista END Esto instruye a WeiDU a añadir todas las transiciones en lista hasta la cima de la lista de transicion para las situaciones especificadas en archivo.DLG (el cual debe YA existir).
Si es dada una positionNumber, WeiDU intertará las transiciones justo entre las trassiciones ya existentes #positionNumber y #positionNumber+1 en las situaciones para el archivo dado. La primer transicion lleva el número 1.
o EXTEND_BOTTOM archivo stateNumber lista [ #positionNumber ] transicion lista END Se comporta como EXTEND_TOP pero agrega las transiciones al final de la lista.
o ADD_STATE_TRIGGER archivo stateNumber stateTriggerString [ stateNumber lista ] Esto instruye a WeiDu para añadir la stateTriggerString a todas las situaciones con los stateNumbers dados en el archivo archivo.DLG (el cual debe YA existir). Esto es conveniente para añadir condiciones extra a las situaciones de un diálogo ya existente.
o ADD_TRANS_TRIGGER archivo stateNumber transTriggerString [ stateNumber lista ] Esto instruye a WeiDU para añadir la transTriggerString a todas las transiciones en todas las situaciones con los stateNumbers dados en el archivo archivo.DLG (el cual debe YA existir). Esto en muy usado en conjuncion con EXTEND_BOTTOM para hacer una nueva bifurcación en una situacion existente. Usa ADD_TRANS_TRIGGER para añadir la negación de algun predicado de todas las transiciones existentes, luego usa EXTEND_BOTTOM para añadir una transicion con ese predicado para esa situacion.
o REPLACE archivo situación lista END Esto instruye a WeiDU para cargar archivo.DLG y remplazar algunas de sus situaciones con la nuevas descirptas en la lista de la situación. Todas las situaciones deben tener stateLabels numéricos (por ejemplo, "5" o "67"). Una nueva situación con la etiqueta X reemplazará a la vieja situación de número X.
o SET_WEIGHT archivo stateLabel #stateWeight Esto instruye a WeiDU para cambiar destructivamente el WEIGHT de la situación dada en archivo.DLG (el cual YA debe existir). Esto puede ser usado sólo para reparar o controlar los diálogos existentes. Nunca uses SET_WEIGHT si puedes evitarlo.
o REPLACE_SAY archivo stateLabel sayString Esto instruye a WeiDU para cambiar destructivamente el sayString de la situación dada en archivo.DLG (el cual DEBE existir). Esto debe ser usado solamente para reparar o controlar los diálogos existentes. Nunca uses REPLACE_SAY si puedes evitarlo.
o REPLACE_STATE_TRIGGER archivo stateNumber stateTriggerString [ stateNumber lista ] Esto instruye a WeiDU para colocar destructivamente las stateTriggerString de todas las situaciones con los stateNumbers dados en el archivo archivo.DLG (El cual debe YA existir). Esto debe ser usado con cuidado.
o REPLACE_TRIGGER_TEXT archivo oldText newText Esto instruye a WeiDU para reemplazar todas las ocurrencias de oldText (texto viejo) (el cual puede ser un regexp) en los stateTriggerStrings y los transTriggerStrings de archivo.DLG (El cual DEBE existir). Esto debe ser usado solamente para reparar o controlar los diálogos existentes. Nunca lo uses si puedes evitarlo.
o REPLACE_ACTION_TEXT archivo oldText newText Esto instruye a WeiDU para reemplazar destructivamente todas las ocurrencias de oldText (texto viejo) (el cual puede ser un regexp) en las stateActionStrings de archivo.DLG (el cual DEBE existir). Esto puede ser usado solamente para reparar o controlar los diálogos existentes. Nunca uses esto si puedes evitarlo.
 
chainEpilogue   Determina donde el diálogo debe llegar a su fin en CHAIN.
Es END archivo stateNumber Transfiere la situación dada in el archivo de diálogo dado.
o EXTERN archivo stateNumber Transfiere la situación dada in el archivo de diálogo dado.
o COPY_TRANS archivo stateNumber Al final del texto de CHAIN, copia todas las transiciones de la situación dada en el archivo dado. Esto es útil para las interjecciones (ver INTERJECT).
o EXIT Al final del texto CHAIN, para finalizar el diálogo.
 
situación   En los juegos del Engine Infinity, esta es la unidad fundamental de diálogo.
Es IF [ WEIGHT #weightNumber ] stateTriggerString THEN BEGIN stateLabel SAY sayText [ = SayText ... ] transicion lista END Cuando comienzas a hablar con una criatira que usa un archivo DLG, el Engine Infinity busca a través de todas las situaciones en ese archivo en orden de WEIGHT creciente y selecciona y selecciona la primera que encuentra de la cual el stateTriggerString es verdadero y no-vacío. La criatura dirá entonces todo lo del sayText asociado. Finalmente, las transiciones son evaluadas en orden de abajo hacia arriba (i.e., reversa). Si una transicion es encontrada con untransTriggerString que es evaluada como Verdadera y no replyText, esatransicion es ejecutada de inmediato. De otra manera, todas las transiciones son presentadas como opciones para el personaje del jugador.
Si una stateLabel es un entero, este es llamado un stateNumber. Todas las situaciones en los archivos DLG que vienen con el juego original usan stateNumbers. Solo los archivos D usan cadenas de caracteres simbólicas para las stateLabels.
Si se incluye más de un pedazo de sayText, esto es llamado Multisay.
o APPENDI archivo situación lista END Esto se comporta justo como el APPEND de la Acción D pero es considerado unasituación. Evita su uso.
o CHAIN2 entryFilename entryLabel chain2Text lista exitFilename exitLabel Esto se comporta como el CHAIN de una Acción D pero es considerado una situación. En fin, chain2Text es ligeramente distinto de chainText. Evita esta construcción.
 
transición   Las transiciones determinan como fluye el diálogo desde una situación a otra.
Es IF transTriggerString THEN transFeature lista transNext Si la transTriggerString es evaluado como Verdadero o está vacío, esta transición es fiable. Si no contiene replyText dentro de su lista de transFeature, es tomado inmediatamente. De otra manera, el replyText es presentado como una opción para el usuario. Si la transición es tomada, ninguna acción en la lista de transFeature es ejecutada y el diálogo fluye desde el punto indicado por el transNext. Las transiciones son evaluadas en "orden inverso". Así, la última respuesta para una situación es chequeada primero. Si su transTriggerString es avaluada como Verdadero y no tiene texto REPLY, esa transición es tomada inmediatamente. Mira SAREV25A, la situación 1 por un ejemplo de una situación con toda clase de transiciones.
o COPY_TRANS archivo stateLabel Esto instruye a WeiDU para copiar todas las transiciones de la situación con la stateLabel dada en archivo.DLG. Esta copia tiene lugar antes de todas las otras Acciones D.
Por ejemplo, esta es una lista de transición válida:
IF ~Before()~ THEN GOTO mi_situación
COPY_TRANS PLAYER1 33
IF ~After()~ THEN EXTERN SOLA 55
 
transFeature   Estos son rasgos o acciones asociadas con la toma de una transición.
Es REPLY replyText Si esta transición es tomada, el PJ dice el replyText.
o DO stateActionString Si esta transición es tomada, la stateActionString es ejecutada.
o JOURNAL texto Si esta transición es tomada, el texto es añadido al diario del PJ.
o SOLVED_JOURNAL texto Si esta transición es tomada, el texto es añadido a la sección ``Gestas cumplidas'' del diario del PJ.
o UNSOLVED_JOURNAL texto Si esta transición es tomada, el texto es añadido a la sección ''Gestas'' del diario del PJ.
o FLAGS entero Esto te permite fijar los rasgos asociados con la transición directa usando el formato binario de los archivos DLG. ¡No uses esto!
 
transNext   Esto determina a donde fluye el diálogo luego de que una transición ha sido tomada.
Es GOTO stateLabel El diálogo continúa en la situación con la etiqueta stateLabel en el mismo archivo DLG de la situación actual.
o EXTERN archivo stateLabel El diálogo continúa en la situación con la etiqueta stateLabel en el archivo archivo.DLG.
o EXIT La conversación termina.
 
chainText   Esto es una rápida taquigrafía para enlazar muchos pequeños pedazos de diálogo cuando el PJ no está diciendo nada.
Es [ IF transTriggerString THEN ] sayText = sayText ...  
seguido por Si el transTriggerString es Verdadero o si no está presente, cada sayText es dicho en orden por el hablante actual. [ == fileName [ IF transTriggerString THEN ] sayText = sayText ... ] El == (son dos signos de igual (=) consecutivos) marca el comienzo de un nuevo hablador (indicado por fileName). Si el transTriggerString es verdadero o no está presente, este nuevo hablador dice todo lo de su sayText en orden.
 
texto   Esto representa las cadenas (de carácteres) que son mostradas a el jugador, y no las cadenas que el juego usa internamente para los predicados y las acciones.
Es cadena [ [WAVEFILE] ] La cadena dada es usada para ambos: jugadores femeninos y masculinos. El [WAVEFILE] opcional es el sonido asociado.
o cadena [ [WAVEFILE] ] cadena [ [WAVEFILE] ] La primer cadena y archivo de sonido son usados si el PJ es masculino, la segunda cadena y archivo de sonido son usados si el PJ es femenino. Esto es útil principalmente para las versiones internacionales (no hablantes de inglés) de los juegos del Engine Infinity.
o #entero La cadena con el número de referencia #entero del DIALOG.TLK debe ser usada de forma inalterada.
o @entero La última definición de la cadena de traducción @entero, dada en algún archivo TRA debe ser usado.

5 Opciones de las líneas de comando

WeiDU es una utilidad de líneas de comando. Los GUIs están disponibles, pero este documento solo describe la evocación de líneas de comando. Usa el DOS Shell ("command" o "cmd") para correr WeiDU. Tu controlas su comportemiento escribiendo argumentos para él a través de las líneas de comando.

Tu invocas WeiDU tipeando WeiDU mientras estás situado en su directorio, y luego cualquier número de opciones y archivos, como los descriptos abajo.
   
Tipos de Archivos de Entrada:  
ARCHIVO.D Compila el ARCHIVO en un DLG.
ARCHIVO.DLG Descompila el ARCHIVO en un D.
ARCHIVO.TLK Usa ARCHIVO como el archivo de entrada principal TLK para todas las operaciones.
ARCHIVO.TP o ARCHIVO.TP2 Lee el ARCHIVO y pregunta al usuario si instalar, reinstalar o desinstalar sus Componentes TP2s.
ARCHIVO.TRA Usa ARCHIVO como una fuente de cadenas de traducción cuando procesa los archivos D.
ARCHIVO.ITM o ARCHIVO.EFF o ARCHIVO.SPL Enlista todos los efectos en el ARCHIVO.
 
Opciones de Entrada Generales:  
--game X Fija el directorio principal del juego en X. WeiDU busca por el CHITIN.KEY y el DIALOG.TLK en el directorio principal del juego. Cuando sea iniciado, WeiDU buscará en el directorio actual y usará el Registro de Windows para encontrar tu juego. Si esto falla, necesitarás usar WeiDU usando el interruptor --game para definir el directorio del BG2. WeiDU también buscará por el BG1, IWD y PST.
--nogame No cargar ninguno de los archivos del juego por defecto
--search X Busca en X por los archivos entrados (acumulativo)
--tlkin X Usar X como DIALOG.TLK
--ftlkin X Usar X como DIALOGF.TLK
--tlkmerge X Anexa las cadenas de X en el DIALOG.TLK cargado.
--autotp Usar DIALOG[F].TLK, leer todos los archivos TP2 y hacer una anotación.
--yes Contestar todas las preguntas de los TP2 con 'Yes'
--uninstall Contestar todas las preguntas de los TP2 con 'Uninstall'
 
Opciones de Salida Generales:
--out X Dirige todos los archivos de salida al directorio X
--backup X Hacer backup de los archivos del directorio X antes de sobreescribirlos
--tlkout X Emite X como nuevo DIALOG.TLK. Debes especificar esta opción para las nuevas cadenas en tus archivos D o TP2 o TRA para mostrar en el juego.
--ftlkout X Emite X como nuevo DIALOGF.TLK
 
Opciones D:
--transin X Usar el archivo TRA de traducción X (acumulativo)
--testtrans Chequea todos los archivos de traducción TRA especificados
--noheader No emite los comentarios de encabezado D
--nofrom No emite los comentarios D del tipo // from:
--nocom No emitir NINGUNO de los comentarios D
--text Emitir cadenas de texto con referencias en los comentarios
--dout X Nombrar un archivo D de salida para emitir (acumulativo)
--traify X Convertir el archivo D o TP2 llamado X para usar TRAs. Usa --dout para especificar el nombre para el recientemente creado archivoTRA.
--traify# X Usar con --traify. Comienza el archivo TRA desde la cadena de traducción @X en vez de @0.
--transref Emitir los números de referencia de las cadenas en los archivos TRA.
--trans Emitir los archivos D y TRA acoplados cuando se descompila un DLG.
 
Opciones de Cadenas TLK:
--traify-tlk Emitir un archivo TRA para el archivo TLK especificado (ver --textout --min --strfind)
--make-tlk X Hacer un archivo TLK para el archivo TRA X (acumulativo, ver --tlkout)
--string X Mostrar la referencia de cadena #X (acumulativo)
--strfind X Mostrar las cadenas que contengan X (acumulativo, regexp permitido)
--strapp X Adicionar la cadena X a el DIALOG.TLK (acumulativo)
 
Opciones BIFF:
--textout X Colocar el texto de salida en el archivo X
--textapp X Adicionar el texto de salida al final del archivo X
--list-biffs Enumerar todos los archivos BIFF en el CHITIN.KEY.
--list-files Enumerar todos los recursos en el CHITIN.KEY.
--biff X Enumerar los contenidos del archivo BIFF X (acumulativo)
--biff-type X Examinar todos los recursos BIFF con la extensión X ... (acumulativo)
--biff-str X ... y enlistar aquellos que contengan X (acumulativo, regexp permitido)
--biff-name X Asumir que los objetos matizados tienen un nombre de strref en el offset X
--biff-get X Extraer el recurso X de los BIFF del juego (acumulativo, regexp permitido)
 
Opciones ARE/ITM/SPL/EFF:
--automate X Automáticamente crea un archivo TP2 para los recursos en el directorio X
--automate-min X Sólo automate las cadenas de referencia sobre X
--list-eff X Enlista los efectos en el recurso X
 
Opciones de Comparación:
--cmp-from X Emite los WRITE_BYTEs para convertir este archivo ...
--cmp-to X ... es este otro.
--dcmp-from X Emite los REPLACEs para convertir este archivo DLG ...
--dcmp-to X ... en este otro.
--tcmp-from X Comparar este archivo TRA (o directorio de archivos TRA files)...
--tcmp-to X ... con este otro (o este directorio).
--tlkcmp-from X Emitir los STRING_SETs para convertir este archivo TLK ...
--tlkcmp-to X ... en este otro.
 
Opciones de datos:
--log X Apuntar las salidas y detalles en X
--autolog Apuntar las salidas y detalles en WSETUP.DEBUG
 
Opciones de Ayuda:
-help Muestra una concisa lista de opciones
--help Muestra una concisa lista de opciones

6 Usos de Ejemplo:
7 Tutoriales de WeiDU

Esta sección incluye tutoriales de partes específicas de WeiDU. Muchos de ellos fueron aportados por usuarios como tu.

7.1 Multi-SAY
Este turorial fue amablemente aportado por Jason Compton.

Aunque una simple línea SAY puede ser de cualquier tamaño, por asuntos de estilo (particularmente en BG2) esta es considerada una buena forma de separar las lineas muy largas en pedazos más pequeños.

Fácilmente uno puede crear una serie de simples bolques de SAY, usando GOTO para el próximo, pero si no hay condiciones especiales siendo chequeadas o acciones siendo tomadas, puedes enlazar muy fácilmente bastantes líneas a la vez.

Digamos que tienes un NPC de escenario eneñando una lección acerca del Proyecto de ley de los Derechos de la Constitución de USA.
BEGIN TEACHER

IF ~NumTimesTalkedTo(0)~ THEN BEGIN constitution_1
  SAY ~On September 25, 1789, the First Congress of the United States
    therefore proposed to the state legislatures 12 amendments to the
    Constitution that met arguments most frequently advanced against it. The
    first two proposed amendments, which concerned the number of constituents
    for each Representative and the compensation of Congressmen, were not
    ratified. Articles 3 to 12, however, ratified by three- fourths of the
    state legislatures, constitute the first 10 amendments of the
    Constitution, known as the Bill of Rights.~
  IF ~~ THEN EXIT
END 
Este es un bloque de diálogo perfectamente válido, pero es extremadamente largo, y probablemente se salga de la ventana de diálogo de los jugadores con baja resolución.

En vez de dividir cada sentencia en una nueva situaión explícita, podemos usar el Multi-SAY y ahorrarnos mucho tecleo. El Multi-SAY es llamado con el signo = (igual), el cual le dice a WeiDU que "el hablante actual debe decir otra línea aquí."

Así es como se vería esa situación D con Multi-SAY:
IF ~NumTimesTalkedTo(0)~ THEN BEGIN constitution_1
  SAY ~On September 25, 1789, the First Congress of the United States
  therefore proposed to the state legislatures 12 amendments to the
  Constitution that met arguments most frequently advanced against it.~
      =
  ~The first two proposed amendments, which concerned the number of
  constituents for each Representative and the compensation of Congressmen,
  were not ratified.~
      =
  ~Articles 3 to 12, however, ratified by three-fourths of the state
  legislatures, constitute the first 10 amendments of the Constitution,
  known as the Bill of Rights.~
  IF ~~ THEN EXIT
END
Esto creará tres situaciones de diálogo, separados por una simple transición de "Continuar".

Y así es como actúa el Multi-SAY en resumidas cuentas. Note que (siempre con WeiDU) los ENTERs y los espacios en blanco antes y después de el signo = son totalmente opcionales, y son usados aquí sólo por ilustración.
SAY ~Uno~ = ~Dos~ = ~Tres~ 
es perfectamente válido también.

Puedes usar Multi-SAY dentro de casi cualquier situación, y puedes usarlo en una Acción D APPEND. Esto es válido:
APPEND J#KLSYJ
  IF ~~ THEN BEGIN Renal1_1
    SAY ~De acuerdo, . Puedo aceptar eso... tienes razón, hay
    asuntos mayores a considerar.~ 
      = 
    ~Pero espero que entiendas por qué dije algo, porque sería
    molesto tener a alguien tan cerca mío, en un rol como ese.~
    IF ~~ THEN EXIT
  END                            // Fin de la situación Renal1_1
END                             // Fin de APPEND J#KLSYJ
Sin embargo, no puedes usar Multi-SAY dentro de REPLACE, porque la naturaleza de REPLACE es cambiar (o reemplazar) una situacióntate simple, mientras que la naturaleza del Multi-SAY is crear múltiples situaciones.

7.2 CHAIN
Este tutorial fue amablemente aportado por Jason Compton.

CHAIN es una extensión del concepto de Multi-SAY, solo que con mútiples participantes. Si tienes dos NPCs hablando de acá para allá por un perídodo de tiempo prolongado, y no necesitas hacer ningún chequeo de condiciones especiales o acciones para que ellos hablen, puede resultar muy tedioso hacer un bloque separado IF/THEN/BEGIN/SAY para cada línea.

Imagina una conversación como esta: Si quieres añadir este pequeño banter a tu juego, podrías hacerlo con 11 bloques APPEND, uno por cada línea, o ahorrar un poco de tiempo duplicando las líneas seguidas de Kelsey e Imoen con Multisay dentro de sus APPENDs, entonces solo necesitarías 9. En realidad, podrías quitar con 2 bloques de APPEND (recuerda que las situaciones no tienen por qué ser escritas en el orden en que son dichas, así que puedes mecionar todas las líneas de Kelsey primero y luego todas las de Immy tan largas como las etiquetas enlacen la conversación correctamente), un con 5 declaraciones de situación y uno con 4. Pero hay una manera aún mejor, y esa es usar CHAIN. Trabaja muy parecido al Multi-SAY. Tu esas = para indicar que el interlocutor actual debe hablar de nuevo, y == (dos signos de igual consecutivos) para indicar que un nuevo interlocutor debe tomar la palabra.

Note como en WeiDU 82, CHAIN ahora puede definir disparadores de situaciones, ejecutar acciones DO, y terminar con un EXIT o COPY_TRANS. Esto significa que para los banters más simples entre NPC/NPC, donde el PJ no tiene oportunidad de hablar, no nececitas usar nada más.

Observa y comprende como este diálogo trabaja usando un CHAIN.
CHAIN
  IF ~Global("KelseyImoenPizza","LOCALS",0)
      InParty("Imoen2")
      See("Imoen2")
      !StateCheck("Imoen2",STATE_SLEEPING)~ THEN BJKLSY pizzachain
  ~Imoen, ¿Qué te gusta en tu pizza?~
DO ~SetGlobal("KelseyImoenPizza","LOCALS",1)~
  == IMOEN2J
  ~Oregano.~
  =
  ~Oh, y quizás con un poco de albahaca mezclada.~
  == BJKLSY
  ~Bueno, si, ¿pero algo más?~
  == IMOEN2J
  ~La salsa es buena.~
  == BJKLSY
  ~(risas) No estás siendo muy útil, Imoen.~
  == IMOEN2J
  ~Mendrugo. Me gusta el mendrugo en mi pizza. Mendrugo cocido es mejor.~
  == BJKLSY
  ~¿Quieres que te haga esa pizza o no?~
  =
  ~Fue TU idea.~
  == IMOEN2J
  ~No puedo decidir. No importa, sólo tengo yogurt.~
  == BJKLSY
  ~(suspiro)~
EXIT 
Note como trabaja este diálogo.

Usamos la declaración CHAIN para definir el gatillo de la situación (las condiciones de comienzo que deben ser verdaderas) y asignarlas a BJKLSY.DLG. La etiqueta "pizzachain" es más que nada para tener una referencia interna. Kelsey dice la primera línea, luego usamos == IMOEN2J para permitirle responder, "Oregano." Luego, podemos usar el = simple para indicar que el interlocutor actual (Imoen) tiene dos líneas consecutivas.

Luego es el turno de hablar de Kelsey, entonces usamos == BJKLSY para decirle a WeiDU que cambien a el otro interlocutor (el cual es Kelsey, desde que le especificamos BJKLSY. Su banter viaja de acá para allá por un rato, y luego cuando es el turno de las líneas de Kelsey, luego de ¿Quieres que te haga esa pizza o no? y Fue TU idea., separamos con un = simple para indicar que el interlocutor actual (Kelsey) tiene dos líneas consecutivas.

Luego del final de Kelsey, el suspiro exasperado, usamos el comando EXIT para terminar el CHAIN, y salir del diálogo.

Y eso es todo lo que necesitas saber para usar CHAIN. Te ahorra tremendas cantidades de tiempo que perderías usando bloques de APPEND individuales o aún bloques de Multi-SAY, para cada NPC.

CHAIN avanzado:

Puedes incluir acciones DO y condiciones dentro del chainText (texto de chain), como en:
CHAIN
  IF ~Global("KelseyImoenPizza","LOCALS",0)
      InParty("Imoen2")
      See("Imoen2")
      !StateCheck("Imoen2",STATE_SLEEPING)~ THEN BJKLSY pizzachain
  ~Imoen, ¿Qué te gusta en tu pizza?~
DO ~SetGlobal("KelseyImoenPizza","LOCALS",1)~
  == IMOEN2J
    ~Oregano.~
    =
    ~Oh, y tal vez con un poco de albahaca mezclada.~

  == BJKLSY
    ~Bueno, si, ¿pero algo más?~

  == IMOEN2J
    ~La salsa es buena.~

    == BJKLSY   IF ~PartyHasItem("pepperoni")~ THEN
      ~Mir, TENEMOS peperoni. ¿Por qué no usar sólo esto? Lo comeré de cualquier modo.
      Si a ti no te gusta, tengo yogurt en su lugar.~

    == IMOEN2J  IF ~!PartyHasItem("pepperoni")~ THEN
      ~Mendrugo. Me gusta el mendrugo en mi pizza. Mendrugo cocido es mejor.~
    == BJKLSY IF ~!PartyHasItem("pepperoni")~ THEN
      ~¿Quieres que te haga esa pizza o no?~
      =
      ~Fue TU idea.~

    == IMOEN2J  IF ~!PartyHasItem("pepperoni")~ THEN
      ~No puedo decidir. No importa, sólo tengo yogurt.~
    == BJKLSY IF ~!PartyHasItem("pepperoni")~ THEN
      ~(suspiro)~
EXIT
En este caso, el diálogo cambia si el grupo tiene el objetor "peperonni". Si es así, Kelsey dice el TENEMOS peperoni, luego (suspiro) y luego el diálogo finaliza. Si no, el diálogo trabaja como antes. Las líneas del chainText con IFs en ellas sólo están comproband si sus condiciones son verdaderas.

7.3 COPY_TRANS

Este tutorial fue amablemente aportado por Jason Compton.

Hay algunos diálogos con ramificaciones complejas en el Engine Infinity que tu, como creador de mods, debes querer agregar. Considera el Baldur's Gate 2 y el diálogo de "La llegada al Infierno". Hay un breve diálogo interno en el que el protagonista acepta que en realidad él/ella está ahora en el Infierno, y entonces todos los compañeros hechos por Bioware tienen oportunidad de hablar. (PLAYER1.DLG situación 25. Ayudará al resto de la explicación su tu usas WeiDU para descompilar PLAYER1.DLG en PLAYER1.D, y/o abrir PLAYER1.DLG en el Near Infinity y mirar la situación 25.)

Luego de que la voz interna del PJ dice Dudas de que estén contentos con su actual situación, cuando tú ni siquiera sabes por qué estás aquí, todos los NPCs de Bioware tienen la oportunidad de hablar. Si estás crando un nuevo NPC y esperas que esté completo, rebosante de la calidad de Bioware, debes querer permitirle a tu personaje hablar aquí igualmente. Para eso, un simple EXTEND_BOTTOM hará el trabajo.

Aquí hay un ejemplo de como Weimer hizo esto con Solaufein:
EXTEND_BOTTOM PLAYER1 25
  IF ~IsValidForPartyDialogue("Sola")
      Global("SolaWelcomeHell","GLOBAL",0)~ THEN
    DO ~SetGlobal("SolaWelcomeHell","GLOBAL",1)~ EXTERN SOLA inHell1
END
Esto coloca una nueva transición al final de PLAYER1 25 que dice al juego que se bifurque a la observación de Soulafein acerca de tu ingreso en el Infierno, si él está presente (IsValid) y si no hemos visto su comentario antes (el chequeo por SolaWelcomeHell=0, luego fijándose a 1. Esto asegura que este curso pueda suceder sólo una vez, lo cual es importante por una razón que explicaré más tarde.) SOLA inHell1, el cual definiremos más tarde, contiene el comentario de Solaufein.

Una vez que Solaufein hace su comentario, sería muy juicioso que permitamos a los otros NPCs de Bioware tener la palabra igualmente, como Bioware proyectó y como los jugadores experimentados de afuera esperan. Podrías simplemente usar el PLAYER1.D descompilado y copiar y pegar la lista de transición. Pero hay algunas buenas razones para no hacer eso. En un grado trivial, eso es un gran derroche de espacio en tu archivo D.

La razón más importante es esta: Si otro mod de NPC viene y deja su propio EXTEND_BOTTOM, no tendrías manera de saber esto. Colocando el paquete de Bioware en la lista de transición, darías por hecho que solo tu mod de NPC tiene su diálogo. El resto serían silenciosos. Entonces si tu fueras el creador de Solaufein, y Solaufein fuera instalado luego de Kelsey y Tashia en un juego, Keslsey y Tashia serían salteados, porque tu solo copiaste la lista de traducción de Bioware. Eso es una gran responsabilidad.

Por eso es que existe COPY_TRANS. COPY_TRANS atrae la lista de trnsición entera de una situación específica y hace la lista de transición para tu nueva situación.

Para ilustrar, mira SOLA inHell1 :
APPEND SOLA
  IF ~~ THEN BEGIN inHell1
    SAY @2 = @3         // usar las cadenas @2 y @3 del archivo de traducción
    COPY_TRANS PLAYER1 25
  END
END 
En vez de copiar y pegar esa gigantesca lista de transiciones IF "" THEN EXTERN del PLAYER1.D, permitimos a WeiDU hacerlo por nosotros. COPY_TRANS PLAYER1 25 dice a WeiDu que agare la lista actual de transiciones de PLAYER1 situación 25, y la usa con la lista de transición de SOLA inHell1. Esto asegura que Solaufein dejará expandir la actividad correctamente a Imoen, Aerie, Minsc, y el resto de la pandilla, Así como también agarra las transiciones que pueden haver sido añadidas por otros NPCs como Kelsey, Valen o Tashia.

COPY_TRANS puede formar toda tu nueva lista de transicion de las situaciones, o sólo una parte de ellas. Esto sería válido, por ejemplo:
IF ~~ THEN BEGIN commentary
  SAY ~Hey, I think I might like to run the transition list from TOLGER
    75... or I might want to do something else, if I'm in chapter six!~
  COPY_TRANS TOLGER 75
  IF ~Global("Chapter","GLOBAL",6)~ THEN GOTO chapter6commentary
END
Esto haría a la transición GOTO commentary2 aparecer al fondo de la memoria de transición (debajo de la lista copiada para TOLGER 75). Recuerda que los gatillos de transición se leen de abajo hacia arriba, asi que esta sería la primera transición evaluada. Si quieres que sea evaluada luego de la lista de transiciones en el COPY_TRANS, colócalo arriba. Nótese, sin embargo, que Bioware usualmente estructura sus listas de transición de modo que el gatillo más alto siempre será verdadero (en realidad, a veces es "True()") asi que es algo improbable que tu nunca quieras colocar un nuevo gatillo de transición encima del COPY_TRANS.

Ahora, esa explicación de por que el chequeo de la variable SolaWelcomeHell es importante: si un usuario instala el mismo mod más de una vez, y éste usa COPY_TRANS, la lista otra vez incluirá nuestro nueva gatillo:
IF ~IsValidForPartyDialogue("Sola")
      Global("SolaWelcomeHell","GLOBAL",0)~ THEN
    DO ~SetGlobal("SolaWelcomeHell","GLOBAL",1)~ EXTERN SOLA inHell1
Si no había memoria siendo fijada para asegurarse de que la transición puede correr sólo una vez, el usuario conseguiría meterse en un círculo. Esto puede y ha pasado ya con algunos mods. El resultado final sería Solaufein o Kelsey o cualquiera que ofrece constantemente su comentario, una y otra vez.

Nota importante: El compilador D de WeiDU ejecuta COPY_TRANS antes que otras acciones que puedes usar para afectar una lista de transiciones dentro del mismo archivo D (como EXTEND_TOP y EXTEND_BOTTOM). Eso es una ventaja.

7.4 INTERJECT
Este tutorial fue amablemente aportado por Jason Compton.

Interjecciones , los pequeños comentarios que hacen los miembros del grupo, una gran manera para darle gusto a un nuevo NPC o una nueva misión que hayas creado. Esto muestra que lo personajes están prestando atención a su mundo de juego, y que tienen una opinión acerca de lo que sucede a su alrededor.

A través de las interjecciones, un NPC puede aconsejar un curso de acción, quejarse acerca de una desición, forzar tu mano... cosas entretenidas.

La forma tradicional para hacer una interjección es encontrar una situación de un diálogo donde otro NPC podría comentar, y usar EXTEND_BOTTOM y APPEND en conunción.

Aquí hay une ejemplo:
EXTEND_BOTTOM SAHPR4 7
     IF ~IsValidForPartyDialog("J#Kelsey")~ THEN EXTERN J#KLSYJ KelseySAHPR4
END

APPEND J#KLSYJ
  IF ~~ THEN BEGIN KelseySAHPR4
    SAY ~Urk. ¿Quién fue el afortunado donador?~
    IF ~~ THEN EXTERN SAHPR2 10
  END
END
Esto funciona, pero es también más trabajo del que se necesita hacer desde la introducción de INTERJECT. (Dicho sea de paso, para los "historiadores" de WeiDU, hay dos motivos principales por los cuales las funciones avanzadas has sido añadidas a WeiDU desde las primeras versiones de Solaufein y el comando CHAIN original: Weimer los necesitaba para sus propios objetivos en la creación de mods, o un proyecto, usualmente Kelsey, lo necesitaba. INTERJECT aconteción cuando Westley finalmente decidió que Solaufein y Valen debían comentar acerca de las gestas. Por otro lado, COPY_TRANS y INTERJECT_COPY_TRANS fueron idea mia.)

INTERJECT simplifica este proceso considerablemente. Para correr un INTERJECT, necesitas saber la situación original (la línea luego de la cual quieres una o más interjecciones de los NPCs), y la situación de destino (donde quieres que el diálogo vaya luego de la interjección.) Generalmente, pero no necesariamente, la situación de destino sería dondequiera que el diálogo originalmente planeara dirigirse, pero si el NPC cambia la conversación en una nueva dirección, esa puede cambiar. Mostraremos los casos más simples para ilustrar.

INTERJECT es una forma especializada de CHAIN. Entonces si estás familiarizado con CHAIN, esto te resultará familiar también.

Considera las driadas en el calabozo de Irenicus. Tal vez Minsc debería decir algo también. IDRYAD1.DLG situación 1 ofrece una buena oportunidad.
IF ~~ THEN BEGIN 1 // from:
  SAY #11080 /* ~Estamos en sus manos.~ */
  IF ~~ THEN EXTERN ~IDRYAD2~ 1
END
Minsc está indignado. Aquí es cuando el puede expresarlo. La idea es que queremos agregar el comentario de Minsc, pero el diálogo deve continuar justo como lo haría si Minsc no hubiera comentado nada.
INTERJECT IDRYAD1 1 MinscDryad
  == MINSCJ IF ~IsValidForPartyDialog("Minsc")~ THEN 
    ~¡Bubú está indignado de que ese mago extraño posea a estas adorables damas!
    ¿Pueden Minsc y Bubú ayudarlas, bellas señoritas?~
END IDRYAD2 1
Aquí está lo que sucede.

Llamar a INTERJECT requiere tres argumentos: el nombre del diálogo y la situación dode vamos a interrumpir, mas un nombre único de variable global. Esta variable será fijada de 0 a 1 luego del INTERJECT, para asegurarse de que esto sólo puede pasar una vez. (Esto es importante en caso de que los jugadores accidentalmente instalen tu mod dos veces, podría crear un problema en círvulos similar al descripto en el tutorial de COPY_TRANS.)

Entonces, INTERJECT IDRYAD1 1 MinscDryad dice a WeiDU "Mete este diálogo luego de la situación 1 de IDRYAD1. Este diálogo se ejecutará si MinscDryad es 0. Luego de ejecutarse, fijaremos MinscDryad a 1."

Luego necesitamos definir quien está hablando. == (que son dos signos de igual consecutivos) es una notación al estilo CHAIN para un nuevo interlocutor, y MINSCJ es el diálogo correcto para usar para el comentario de Minsc "joined-party". Si Minsc está en el grupo y disponible para el diálogo, dirá su línea. Luego de eso, nos transicionamos a la situación 1 de IDRYAD2 (END IDRYAD2 1), lo cual es a donde el diálogo estaba destinado en primer lugar. Podemos hacer esto más complicado y permitir a la driada responder su interrupción antes de proseguir.
INTERJECT IDRYAD1 1 MinscDryad
  == MINSCJ     IF ~IsValidForPartyDialog("Minsc")~ THEN 
    ~¡Bubú está indignado de que ese mago extraño posea a estas adorables damas!
    ¿Pueden Minsc y Bubú ayudarlas, bellas señoritas?~
  == IDRYAD1    IF ~IsValidForPartyDialog("Minsc")~ THEN 
    ~Mortal grande, estamos teniendo una escena dramática. Por favor
    no interrumpas.~
END IDRYAD2 1
Nótese que repetimos el chequeo
IF ~IsValidForPartyDialog("Minsc")~ THEN
en IDRYAD1. Esto es para asegurarse de que ella solo dice esa línea si Minsc está allí, y por añadidura hace este pequeño comentario. Así ahora, Minsc interrumpe, la driada #1 lo regaña, y luego proseguimos con la línea de la segunda driada.

Un consejo: Aunque no es necesario coger una situación que tenga solo una trancisión a otra situación, a menos que estés deseoso de experimentar (o estés intentando intencionalmente quitar las opciones del jugador para la ecuación, haciendo que el NPC diga algo que fuerze a la acción inmediata, por ejemplo), no uses INTERJECT dentro de una situación en la cual haya opciones para el jugador (REPLYs).

7.5 INTERJECT_COPY_TRANS
Este tutorial fue amablemente aportado por Jason Compton.

INTERJECT es bueno para crear interjecciones en donde no existe ya ninguna. Sin embargo, muchas de las oportunidades realmente buenas para las interjecciones en los diálogos del juego ya tienen interjecciones en ellos. Si usas el INTERJECT estándar, las chances son que pases por arriba de ellas.

Considera TOLGER.DLG situación 75. Luego de que Tolgerias dice Éste es un asunto muy delicado, y no puedo contarle todo a cualquier curioso. Necesito que te comprometas a aceptar la tarea. cuatro NPCs (Edwin, Jaheira, Yoshimo, Korgan) dirán lo que ellos piensan de esa distribución corrupta. Lo que es más, Bioware estructuró las transiciones del diálogo para que los cuatro puedan introducir su comentario, si están todos en el grupo.

Sin embargo, usando un INTERJECT estándar para una nueva línea de un NPS se saltearía esos cuatro comentarios, lo cual es más bien desconsiderado. INTERJECT_COPY_TRANS funciona parecido al INTERJECT normal, pero en vez de definir una situación, una transición y luego END, WeiDU usará COPY_TRANS con la lista de transición para la situación en la cual estás usando INTERJECT.

Esto no es tan confuso como suena. Mira como el nuevo NPC hipotético Aqualung responde a los términos de Tolgerias:
INTERJECT_COPY_TRANS TOLGER 75 AquaTolger
  == AQUALUNJ   IF ~IsValidForPartyDialogue("Aqualung")~ THEN 
    ~Hey, ¡Esa es una oferta realmente miserable! ¿A donde fueron esas pequeñas chicas?
    Podría estar sentado en un banco en el parque, ¡no necesito esta molestia! De todos
    modos, ¿Quién eres tu?~
  == TOLGER     IF ~IsValidForPartyDialogue("Aqualung")~ THEN 
    ~No eres más que un viejo cabrón, lo que ves soy solo yo. Ahora ¿Alguien más
    tiene un agudo comentario que le gustaría hacer?~
END
Entonces, si Aqualung está cerca, él oirá el comentario, dirá lo suyo y luego Tolgerias le responderá. Luego de eso, el juego buscará la presencia de Edwin, Jaheira, Yoshimo y Korgan y tendermos sus respuestas a Tolgerias igualmente.

Sugerencia: INTERJECT_COPY_TRANS es bueno para usar aún cuando no hay otras interjecciones en la situación, ejemplo, si hay solo un sumple IF "" THEN GOTO bla. Esto es, tan largo como planees proceder con el destino orignial. Te ahorra el problema de tener que buscar y poner el destino.

7.6 WEIGHTs de las situaciones

stateTriggerStrings, las condiciones que determinan que situación debe ser usada para el comienzo de un diálogo, pueden tener WEIGHTs. Estos WEIGHTs son usados por el Engine Infinity para elegir cuál situación elegir si múltiples gatillos de situación son evaluados como "verdaderos". [ En realidad, los WEIGHTs son solamente los desbalances dentro de la tabla de los gatillos de la situación en el archivo DLG, pero este detalle no es importante a menos que estés escribiendo tu propia herramienta. ] WEIGHTs solo tienen sentido para los stateTriggerStrings que no están vacíos.

Si múltiples stateTriggerStrings son evaluados como verdaderos, el Engine Infinity escogerá la situación con el WEIGHT más bajo. Usualmente el weighting (carga) sigue el orden de la declaración de la situación en el archivo D. Es decir, la primera situación mencionada tiene la carga más liviana (P.Ej, será escogido el primero en caso de un empate) y la última situación mencionada tiene la mayor carga (P.Ej, será escogido a lo último en caso de un empate). Sin embargo, puedes incluir una directiva WEIGHT explícita para cambiar las cosas, por ejemplo, considera este archivo D:
BEGIN foozle
  IF ~True()~ THEN BEGIN a SAY ~Jason~ END
  IF ~True()~ THEN BEGIN b SAY ~yada~ END
  IF ~True()~ THEN BEGIN c SAY ~Compton~ END
  IF ~True()~ THEN BEGIN d SAY ~kelsey~ END
Si tu hablas con foozle, este dirá siempre Jason. Sin embargo, puedes alterar esplícitamente las cargas de manera que la tercer situación es escogida primero, como en:
BEGIN foozle
  IF WEIGHT #10 ~True()~ THEN BEGIN a SAY ~Jason~ END
  IF            ~True()~ THEN BEGIN b SAY ~yada~ END
  IF WEIGHT #2  ~True()~ THEN BEGIN c SAY ~Compton~ END
  IF            ~True()~ THEN BEGIN d SAY ~kelsey~ END
Con este archivo D, foozle dirá siempre Compton. Todas las situaciones con directivas WEIGHT vienen antes que todas las situaciones sin ellas. Las situaciones sin directivas WEIGHT son clasificadas en orden de aparición. Asi que el orden de las situaciones para foozle.DLG es c-a-b-d. Si, esto es complicado.

Consejo Muy Recomendado: No use las directivas WEIGHT en sus archivos D hechos a mano. Solo use el orden implícito.

Las directivas WEIGHT fueron introducidas para facilitar el manejo de los archivos DLG creados por Bioware (P.Ej., BJAHEIR.DLG) que incluyen cargas engañosas. Solo a las situaciones con gatillos no-vacíos le son dadas cargas implícitas. Si creas un archivo D desde un DLG que presenta cargas complicadas, WeiDU emitirá comentarios como este:
IF WEIGHT #8 /* Triggers after states #: 11 12 24 25 26 36 58 even though
                they appear after this state */
  ~True()~ THEN BEGIN 10 // from:
    SAY #52190 /* ~Please do not interrupt our thoughts. We must prepare
      carefully if we are to see a weakness in the illithid web. ~ */
    IF ~~ THEN EXIT
END
para recordarte que el orden no es lo que tu piensas o lo que parece ser.

A todos los gatillos de las situaciones en los archivos DLG le son dadas cargas contando desde 0 hasta el número máximo de gatillos de situación en el archivo DLG. Puedes usar cualquier número que quieras (aún uno negativo): WeiDU simplemente lo clasificará. ADD_STATE_TRIGGER no cambia la carga asociada con ese gatillo. APPEND puede ser usado para dar una carga no-trivial a una situación, como en:
APPEND BJAHEIR
  IF WEIGHT #-999 ~MyCondition()~ THEN BEGIN mystate SAY ~My Stuff~ END 
END
Dado que BJAHEIR tiene implícitos WEIGHTs en el rango de #0 a aproximadamente #50, esto causa que mystate (con un valor de -999) tenga prioridad sobre todas las situaciones que ya existen en BJAHEIR. Sin tal acción drástica, las situaciones APPENDed (anexadas) tendrán que usar el orden implícito, y tendrán de esa manera la prioridad más baja (porque aparecen al final del archivo). Multisay y CHAIN también anexan situaciones, pero como ellos anexan situaciones con stateTriggerStrings vacíos, los WEIGHTs no son relevantes.

Considera el siguiente ejemplo:
BEGIN foozle
  IF WEIGHT #10 ~True()~ THEN BEGIN a SAY ~Jason~ END
  IF            ~~ THEN BEGIN b SAY ~yada~ END
  IF WEIGHT #2  ~True()~ THEN BEGIN c SAY ~Compton~ END
  IF            ~True()~ THEN BEGIN d SAY ~kelsey~ END
  ADD_STATE_TRIGGER foozle 1 /* state b */ ~MyCondition()~
El diálogo foozle resulante aún tendrá el orden de carga c-a-b-d.

Aquí hay otro ejemplo:
BEGIN foozle
  IF            ~True()~ THEN BEGIN a SAY ~Jason~ END
  IF            ~~ THEN BEGIN b SAY ~yada~ END
  IF            ~True()~ THEN BEGIN c SAY ~Compton~ END
  IF            ~True()~ THEN BEGIN d SAY ~kelsey~ END
  ADD_STATE_TRIGGER foozle 1 /* state b */ ~MyCondition()~
El diálogo foozle resultante tendrá el orden a-b-c-d esperado.

Sin embargo, considera este nocivo ejemplo:
  //////
  // foozle.DLG contents, assume it has already been created and is 
  // sitting on your hard drive somewhere
  // IF            ~True()~ THEN BEGIN a SAY ~Jason~ END
  // IF            ~~ THEN BEGIN b SAY ~yada~ END
  // IF            ~True()~ THEN BEGIN c SAY ~Compton~ END
  // IF            ~True()~ THEN BEGIN d SAY ~kelsey~ END
  //////

  // new D file
  ADD_STATE_TRIGGER foozle 1 /* state b */ ~MyCondition()~
Esto actualizará foozle y el oden resultante será a-c-d-b (porque cuando foozle.DLG fue cargado por el disco, a a c y d le fueron dadas cargas, pero a b no (porque tenía un gatillo vacío)). De ese modo, debes evitar usar ADD_STATE_TRIGGER en situaciones con gatillos vacíos a menos que sepas lo que estás haciendo.

7.7 Archivos de traducción TRA

Si estás escribiendo un mod y te gustaría hacerlo más fácil para traducir a otro idioma, puedes usar los "archivos de traducción" (así el BGII mismo usa el DIALOG.TLK) para separar la estructura y el contenido de tu diálogo. Un archivo de traducción basicamente enlista las cadenas de textos en orden. Por ejemplo,

C:\Program Files\Black Isle\BGII - SoA\> WeiDU --trans SCSARLES.DLG


Esto crea scsarles.D y scsarles.tra. scsarles.D ahora contiene:
IF ~NumTimesTalkedTo(0)~ THEN BEGIN 0 // from:
  SAY @1 /* ~¿Quién es? ¿Se puede saber por qué me has interrumpido mientras meditaba?
    A mi musa creativa hay que despertarla dulcemente
    y tu estruendo no es nada apropiado.~ [SARLES02] #28655 */
  IF ~~ THEN REPLY @2 
    /* ~Perdón. Te dejaré con tus pensamientos.~ #28656 */ GOTO 1
  IF ~~ THEN REPLY @3 /* ~Lo siento, pero he venido en busca de tu talento para un encargo artístico.~ #28657 */ 
    DO ~SetGlobal("TalkedToSarles","GLOBAL",1)~ GOTO 2
END 
Nótese que todas las cadenas han sido reemplazadas por un @número y los textos han sido puestos en comentarios.

El archivo de traducción scsarles.tra contiene todas esas cadenas:
// SCSARLES translation file
@1   = ~¿Quién es? ¿Se puede saber por qué me has interrumpido mientras meditaba? 
A mi musa creativa hay que despertarla dulcemente 
y tu estruendo no es nada apropiado.~ [SARLES02]
@2   = ~Perdón. Te dejaré con tus pensamientos.~
@3   = ~Lo siento, pero he venido en busca de tu talento para un encargo artístico.~ 
Luego puedes pedir a alguien que hable en otra lengua que escriba un nuevo archivo de traducción traduciendo todas las líneas en scs