Tutorial Scripting Fallout3
De Videojuegos
Esta es una traducción de una guía en inglés realizada por Cipscis sobre el sistema de scripting en Fallout 3. Podemos disfrutar de este tutorial gracias a Bauhaus, que ha realizado dicha traducción.
Podemos encontrar la guía original aquí:
Contenido |
Cosas a tener en cuenta del tutorial
IMPORTANTE: la palabra Forma (del original Form) es utilizada en el presente tutorial para describir artículos o entradas del editor GECK. Se ha traducido con letra capital para diferenciarlo del uso de la palabra forma como método. Además se ha optado por no traducir Script (literalmente guion o escritura), de uso común en programación.
MÁS IMPORTANTE AUN: al final del tutorial hay un glosario con algunas de las palabras en azul que encontrareis. Muchas de estas entradas son específicas del editor GECK y en algunos casos se ha mantenido entre paréntesis el original o la referencia específica de la que está hablando.
OTRA COSA IMPORTANTE: el autor no comenta nada de los espacios necesarios dentro de un Script. Es necesario saber que los espacios de ANTES de que una linea de código comience deben ser habitualmente, pero dependiendo del caso, de tabulador. Aquí teneis un link que explica esto en ingles, bajo un apartado llamado Spaces and Tabs.
Introducción
Este tutorial está dirigido a aquellos que desean aprender la base de Scripting para Fallout 3, pero carecen de experiencia programando. Si esto suena para ti, entonces espero que encuentres este tutorial beneficioso. Antes de comenzar, hay un par de cosas que deberíamos revisar:
- El lenguaje de Script usado en Fallout 3 no distingue entre mayúsculas y minúsculas. Esto quiere decir que aunque puedes tener perfectamente un buen script sin hacer buen uso de letras capitales, es recomendable intentar estandarizar esto, haciendo tus scripts más fáciles de leer.
- Este tutorial asume que tú eres competente en el uso del GECK, o alguna otra herramienta capaz de crear y editar archivos de datos para Fallout 3. Si este no es el caso entonces te recomiendo que mires alguno de los tutoriales oficiales del GECK para familiarizarte con ello antes de intentar seguir este tutorial.
- Si no comprendes alguna de la terminología usada en este tutorial, puedes revisar el Glosario de Términos del final de esta página.
Ahora, empecemos, ¿De acuerdo? Lo primero que necesitas saber sobre Scripting en Fallout 3 es que todos los Script (excepto los Result Scripts, que explicaré en un tutorial posterior) deben comenzar con ScriptName, que declara el identificador (EditorID) del Script. Por ejemplo:
ScriptName MiPrimerScript
Si miras alguno de los Scripts que existen en Fallout3.esm, probablemente notaras que muchos de ellos usan scn en lugar de ScriptName. Esto es perfectamente correcto, porque scn es un alias de ScriptName. Eso quiere decir que nosotros podemos usar esta declaración de identificador:
scn MiPrimerScript
¡Felicidades, has escrito tu primer Script! Aunque no es particularmente excitante, claro (no hace nada por el momento). ¿Por qué no hacemos algo al respecto? Vamos a editar este Script para que muestre el texto “¡Hola Mundo!” en la pantalla al coger una horquilla.
La función que usaremos para mostrar el mensaje se llama ShowMessage, pero antes de que podamos ponerla necesitamos decirle cuando deseamos que se active, lo cual haremos usando los bloques (Blocktipes) Begin/End (de nuevo, excepto para los Result Script).
Durante todos los fotogramas (medida de tiempo) en el cual un Script se activa, las condiciones de cada bloque Begin/End son revisadas secuencialmente de arriba abajo. Si la condición especificada es cierta, entonces el código contenido dentro del bloque Begin/End se activa. En caso contrario no hará nada este fotograma. Como puedes ver, los bloques son esencialmente condicionantes superiores a cualquier otro. Puesto que deseamos que nuestro código corra siempre que una horquilla es añadida al inventario del jugador, vincularemos el Script a la Forma (Form) Horquilla (EditorID: Lockpick), y usarenos el bloque OnAdd y player como parámetro.
ScriptName MiPrimerScript Begin OnAdd player End
Para poder vincular nuestro Script a la Forma (Form) Horquilla, debemos especificar qué tipo de Script es. Con la excepción de los Result Script, todos los Scripts están divididos en tres tipos:
- Object (objeto)
- Quest (misión/busqueda)
- Effect (efecto)
Puesto que deseamos vincular nuestro Script a la horquilla, la cual es una Forma (Form) de Misc Item, debemos definirlo como Object Script (Script de Objeto).
Como ya he mencionado antes, la función que usaremos en este Script es ShowMessage. En cualquier caso, antes de poder usar esta función necesitamos crear un mensaje que usar como parámetro (Miscellaneous-Message). La Forma (Form) de este mensaje debería tener sin marcar la casilla Message Box, así como “¡Hola Mundo!” escrito en el cuadro Message Box. Escribe en ID “MiMensaje”.
Ahora que hemos preparado el mensaje podemos usar ShowMessage en nuestro Script para poder mostrar el texto:
ScriptName MiPrimerScript Begin OnAdd player ShowMessage MiMensaje End
Ahora, si este Script es vinculado al objeto Horquilla, “Hola Mundo” se mostrará arriba a la izquierda de la pantalla siempre que cualquier horquilla sea añadida al inventario del jugador.
Declarando Condicionantes
Hasta el momento, el código contenido en nuestro Script solo se activará si una horquilla es añadida al inventario del jugador. Esto está bien, pero ¿Y si queremos mostrar un mensaje diferente si fue añadido al inventario de un actor diferente del jugador, y mostrar “¡Hola Mundo!” si se añade a este último? Vamos a llamar a este otro mensaje MiOtroMensaje, y dira “Adios Mundo”.
Naturalmente nosotros podríamos conseguir esto teniendo múltiples bloques OnAdd, pero entonces terminaríamos con códigos duplicados en nuestro Script, lo cual es algo que siempre deberíamos evitar. En lugar de eso, usaremos otra función. GetContainer, para determinar que actor tiene el objeto con el Script en su inventario.
Puesto que llamar a GetContainer no es suficiente, vamos a tener que chequear su valor devuelto y usar eso para determinar que sección de nuestro Script debería correr. Para conseguirlo usaremos una declaración “if”.
La declaración “if” es muy similar a un bloque Begin/End. Comienza con la palabra “if”, seguida por la condición que debería ser chequeada, y finaliza con la palabra “endif”. Las declaraciones “if” son diferentes a los bloques Begin/End en que la condición es completamente definida por ti, en oposición a ser elegida de una lista de condiciones utilizables. Así es como nosotros cambiaremos nuestro Script para que el código dentro del bloque OnAdd se active cuando la horquilla es añadida al inventario de algún actor pero muestre el mensaje solo si ese inventario es el del jugador.
ScriptName MiPrimerScript Begin OnAdd if GetContainer == player ShowMessage MiMensaje endif End
Mucha gente entiende mal como las declaraciones “if” funcionan, por tanto vamos a trabajar eso. Primero, GetContainer es llamado. GetContainer devuelve el RefID de la referencia que tiene el objeto con el Script en su inventario, por tanto una vez es llamado puedes visualizar su valor devuelto como sustitución. Por ejemplo, si el objeto con el Script está en el inventario del jugador entonces GetContainer devolverá la RefID del jugador, por tanto puedes ver la condición como esto:
if player == player
La segunda parte de la condición es un operador. El “==” devuelve 1 si ambos argumentos son iguales y 0 si no lo son. Por eso, debido a que “player” y “player” son iguales, la condición evalúa 1.
If 1
Debido a que la condición devuelve un valor cierto (True), el código contenido dentro del estamento “if” se activará. Si, por el contrario, GetContainer devuelve una RefID diferente del jugador entonces la condición sería evaluada como 0, lo cual es un valor falso, y el código dentro del estamento “if” no se activará.
Ahora, como puedes ver, nuestro Script tiene prácticamente la misma funcionalidad que tenía antes, aunque ligeramente menos eficiente. Lo que vamos a hacer ahora es añadir una sección alternativa de código que solo correrá si el objeto con el Script es añadido a el inventario de una referencia diferente a la del jugador. La forma más obvia de hacer esto sería crear un segundo estamento “if” que chequee una condición diferente:
if GetContainer != player
Como puedes ver esta nueva condición es justo lo opuesto de la condición que nosotros usamos antes. Puesto que el valor devuelto por GetContainer será el mismo en ambas condiciones (player) podemos asegurarnos de que una y solo una de esas condiciones sea evaluada como cierta (True). Esto significa que, en lugar de crear enteramente un nuevo estamento “if”, podemos usar un estamento “else”.
Un estamento “else” solo puede ser usado entre un estamento “if” y su correspondiente “endif”. Y básicamente significa “si todas las anteriores condiciones son falsas”. Actualicemos nuestro Script de nuevo, esta vez para mostrar “MiOtroMensaje” si una horquilla es añadida al inventario de una referencia diferente del jugador.
ScriptName MiPrimerScript Begin OnAdd If GetContainer == player ShowMessage MiMensaje Else ShowMessage MiOtroMensaje Endif End
Ahora cuando the bloque OnAdd corre, la condición “if GetContainer == player” es revisada primero. Si se evalúa como cierto (True), la línea “ShowMessage MiMensaje” se activa y el Script saltará al siguiente estamento “elseif” (la condición “else” será completamente ignorada). En caso contrario, si la primera condición es falsa (False), la segunda condición, “else”, será chequeada. Como ya he mencionado antes, el estamento “else” básicamente significa “si todas las anteriores condiciones son falsas” (si un estamento “else” es chequeado el código que contiene se activará y las siguientes condiciones serán saltadas).
Ahora nuestro Script tiene dos posibles salidas: si una horquilla es añadida al inventario del jugador, “MiMensaje” será mostrado, y si una horquilla es añadida al inventario de un personaje diferente del jugador, “MiOtroMensaje” se mostrará. Esto está bien, pero ¿Qué pasa si queremos tener más posibles salidas asociadas a nuestro Script? Por ejemplo, ¿Mostrar un mensaje diferente si otra horquilla es añadida al inventario de padre del jugador? (Vamos a llamarlo “MiPadreMensaje” y debe decir “¡Hola Papá!”) Quizás la más obvia aproximación a esto sería situar un nuevo estamento “if” dentro del estamento “else:”
ScriptName MiPrimerScript Begin OnAdd If GetContainer == player ShowMessage MiMensaje Else If GetContainer == PadreRef ShowMessage MiPadreMensaje else ShowMessage MiOtroMensaje endif Endif End
Como puedes ver, si una horquilla es añadida al inventario de una referencia (reference) diferente a al del jugador, el Script entonces chequeará si la horquilla ha sido añadida al inventario de la referencia (reference) del padre. Aunque esto funciona perfectamente, el lenguaje de Scripting usado en Fallout3 incluye una elegante herramienta que nos permite utilizar una amplia cantidad de condiciones como esta sin tener que incluir todos nuestro estamentos “if” dentro de otros. Esta herramienta es un estamento “elseif”, y puede ser usado así:
ScriptName MiPrimerScript Begin OnAdd If GetContainer == player ShowMessage MiMensaje Elseif GetContainer == PadreRef ShowMessage MiPadreMensaje else ShowMessage MiOtroMensaje Endif End
Este código funciona exactamente de la misma forma que el anterior, excepto que es mucho más fácil de leer, como puedes ver, y tu solo has de incluir un estamento “endif” porque tú solo has usado un “if”. Recuerda siempre: “elseif” y ”else” no necesitan sus propios estamento “endif”, solo los estamentos “if” los requieren.
Una de la cuestiones generales más comunes que he visto preguntadas sobre el lenguaje de programación usado en Fallout3 es “¿Cuándo podemos usar un switch/case?” Si tú no has hecho programación antes, entonces esto realmente no significa nada para ti. Los estamentos “switch/case” pueden ser usados en ciertas situaciones en lugar de los estamentos “if”. Aunque ellos no permiten ninguna funcionalidad extra, pueden hacer el código mucho más fácil de leer. La respuesta a esta cuestión en no, los estamentos “switch/case” no pueden ser usado en los Scripts de Fallout3, por tanto nos limitaremos a los estamentos “if” y ”elseif”.
Variables
A menudo encontrarás que necesitas alguna forma de almacenar información en un Script. Para este propósito tenemos tres tipos de variables disponibles. Estos tres tipos, incluyendo sus alias, son:
- Int / short / long
- Float
- Ref / reference
Cada uno de estos tipos de referencias puede ser usado para almacenar un específico tipo de valor. Básicamente, las variables “int” almacenan valores íntegros (positivos o negativos), las variables “float” almacenan valores con punto flotante (números con decimales con coma flotante, que también pueden ser positivos o negativos), y las variables “ref” alamcenan identificadores (FormIDs) (aunque son más comúnmente usadas para almacenar RefIDs, es decir el nombre).
Para poder crear una variable para nuestro uso debemos declararla primero. Justo como cuando usamos “ScriptName” para declarar el identificador (EditorID) de nuestro Script, cuando declaremos una variable debemos usar una palabra clave apropiada que determine qué tipo de variable es. Podemos elegir el nombre de nuestra variable, pero dos variables en el mismo Script no pueden tener el mismo nombre, aunque sean de diferentes tipos, y una variable no puede compartir nombre con ningúna Forma (Form) (por ejemplo no podemos darle el nombre “Lockpick” a una variable porque ya es utilizado identificador (EditorID) de la Forma (Form) horquilla). Vamos a declarar una variable, para que podamos almacenar el valor devuelto por GetContainer para usar más tarde:
ScriptName MiScript ref rContainer Begin OnAdd ... End
Como puedes ver la declaración de nuestra nueva variable es localizada en la cima del Script, fuera de nuestro bloque Begin/End. Todas tus declaraciones de variables deben ir situadas aquí, justo como la declaración “ScriptName”. Observa asimismo como he llamado a mi variable: la he precedido con la letra “r” para saber que se trata de una variable de referencia, y la he nombrado acorde a su función, la cual es almacenar el identificador (RefID) del contenedor del objeto con el Script. Como nombrar tus variables y que convenciones usar está completamente a tu discreción, pero es importante que las nombres acordes a su función para que tu guión sea más fácil de seguir. Si tus variables son todas nombradas "Variable1", "Variable2", etc., tu Scrip probablemente será muy difícil de comprender.
Una vez que hemos declarado nuestra variable, automáticamente se le asigna un valor de 0. Para poder cambiar el valor de una variable debemos usar un comando “set”, que consiste en el uso de dos palabras clave: “set” y “to”. Por ejemplo, si deseamos configurar nuestra variable “rContainer” a el valor devuelto por GetContainer, debemos hacer así:
set rContainer to GetContainer
Como puede ver, el comando “set” se inicia con la palabra clave “set”, la cual es seguida por el nombre de la variable, la cual es seguida a su vez por el comando “to”, que es seguida por último por una expresión. El valor de la variable se configurará a el resultado de la expresión.
Funciones de referencia
La primera función que usamos en este tutorial, ShowMessage, es lo que conocemos como una función no-referencial, puesto que no actua sobre una referencia específica. La mayoría de las funciones, de todas formas, son funciones referenciales, y llevan a cabo una acción en una referencia específica. Debido a esto, cuando las llamamos debemos especificar la referencia sobre la que actuará. Hay dos formas de usar una función referencial: con sintaxis de referencia implícita y con sintaxis de referencia explícita.
- Cuando una función de referencia es llamada con sintaxis implícita, debe hacerse sobre una referencia con Script. Debido a esto, las funciones de referencia pueden solos ser llamadas con sintaxis implícita en Scripts de referencias (Reference Script). Las funciones de referencia usan exactamente la misma sintaxis que las funciones no-referenciales, y pueden ser llamadas en objetos de inventario así como en referencias.
- Cuando una función de referencia es llamada con sintaxis explícita, debe hacerse con una referencia específica. Se puede especificar esta referencia de dos formas:
- Usando el EditorRefID. Solo las referencias persistentes pueden ser llamadas de esta forma.
- Usando una variable “ref” local almacenando el identificador de la referencia (RefID).
- Las funciones de referencia llamadas con sintaxis explícita especifican una referencia prefijando el nombre de la función con el identificador de la referencia (EditorRefID) o el nombre de una variable “ref”, y separando esta de la función con un espacio.
Es importante recordar que las funciones no pueden ser usadas directamente para llamar funciones de referencia con sintaxis explícita, ni pueden ser usadas directamente como parámetros en otras funciones. En lugar de esto, el valor devuelto por una función debe ser almacenada en una variable, y esa variable entonces podría ser usada al llamar a la función. Por ejemplo, el siguiente código no funciona:
GetContainer.AddItem Caps001 10
En lugar de esto el valor devuelto de GetContainer debe ser almacenado en una variable “ref” local, y esa variable local debe ser usada para llamar a getContainer.
ref rContainer
set rContainer to GetContainer
rContainer.AddItem Caps001 10
En nuestro Script, nosotros ya hemos llamado a una función de referencia (GetContainer). Y puesto que GetContainer solo funciona realmente en objetos de inventario, debería ser siempre llamado con sintaxis implícita, justo como hemos hecho.
De todas formas ¿Dónde nos hemos quedado? Ah, cierto, justo acabamos de declarar una variable “ref”, llamada rContainer, y la hemos configurado al valor devuelto por GetContainer. Ahora que tenemos el identificador (RefID) (de la referencia que tiene la horquilla con el Script en su inventario) almacenado en una variable podemos usar funciones de referencia sobre ella con sintaxis explícita. Ahora bien, ¿Y si deseamos cambiar nuestro Script para que, si una horquilla es añadida al inventario de una referencia diferente a la del jugador y su padre, 10 chapas sean añadidas al inventario de esa referencia en lugar de mostrar un mensaje? Nosotros podríamos hacer esto utilizando sintaxis explícita para usar AddItem sobre la referencia. Algo como esto:
ScriptName MiPrimerScript ref rContainer Begin OnAdd set rContainer to GetContainer if rContainer == player ShowMessage MiMensaje elseif rContainer == MQDadRef ShowMessage MiPadreMensaje else rContainer.AddItem Caps001 10 endif End
Una cosa más que deberíamos comentar aquí es que cuando comparamos identificadores (RefIDs almacenador en variables “ref” y representados por EditorRefIDs), la función GetIsReference debería ser usada en lugar del operador “==”, por tanto nuestro Script seria esto:
ScriptName MiPrimerScript ref rContainer Begin OnAdd set rContainer to GetContainer if rContainer.GetIsReference player ShowMessage MiMensaje elseif rContainer.GetIsReference MQDadRef ShowMessage MiPadreMensaje else rContainer.AddItem Caps001 10 endif End
Como puedes ver, GetIsReference es llamado por la referencia que tiene su identificador (RefID) almacenado en nuestra variable rContainer, y usa la identificación (RefID) que está siendo comparada como un parámetro. Para esta función, nosotros podemos intercambiar esos identificadores y seguiría funcionando. (ej: “player.GetIsReference rContainer”)
Comentarios
Cuando tus Scripts lleguen a ser más largos y complejos, puede ser difícil seguirlos. Para ayudarte a hacer tus Scripts más fáciles de comprender es importantes anotarlos usando comentarios. Los comentarios son básicamente texto que es parte del código contenido en el Script pero es completamente ignorado (no tiene ningún efecto en como el Script funciona).
Los comentarios en los Script de Fallout3 por el usa del punto y coma (Todo texto después de un “;” es un comentario, y será ignorado. Este tipo de comentario es conocido como Comentario de Linea, puesto que se extiende desde el punto y coma especificado hasta el final de la línea. Muchos otros lenguajes informáticos permiten un tipo de comentario conocido como Comentario de Bloque donde otro carácter específico es usado para marcar el final del comentario. Pero Fallout3 no permite esto.
Un método particularmente útil de usar comentarios es explicar que representa un cierto valor. Por ejemplo la función GetOpenState usa diferentes valores para representar “estados abiertos” de una puerta. Por si mismo no tienen sentido, por tanto es buena idea usar a comentario para explicar el significado de un valor. Por ejemplo:
if GetOpenState == 3 ; Cerrado ... elseif GetOpenState == 4 ; Cerrando ... endif
Como puedes ver, los comentarios aquí ayudan a explicar el verdadero significado de una condición. Si el comentario no existiera cualquiera leyendo el Script necesitaría mirar la documentación de GetOpenState para comprender que significa cada valor. El mismo concepto se aplica a las variables donde diferentes valores significan diferentes estados. Por ello es buena idea usar comentarios cuando declares la variable explicando lo que ese valor representa.
Otra buena forma de usar comentarios es describir la función de un Script. Por ejemplo, si tú tienes un Script que usa algún complicado calculo para situar una referencia enfrente de jugador, entonces sería buena idea explicar esto en un comentario en la cima del código. De esa forma, cualquiera leyendo ese código tendrá que leer ese comentario antes de intentar comprender como funcionan tus cálculos.
Siempre que escribas Scripts, deberías anotar aquello que consideres necesario. Si tu crees que alguna parte de tu Script será beneficiosa con una pequeña explicación, no dudes en añadir un comentario cerca. Incluso si el comentario solo contiene una o dos palabras una pequeña clarificación puede ahorrar un largo camino, y los Scripts que no contienen ningún comentario pueden algunas veces tomar mucho tiempo para ser completamente comprendidos.
Glosario
Alias
Muchas funciones y palabras clave tienen “alias”. Existen nombres alternativos que pueden ser usados en lugar del nombre principal de la función. Por ejemplo, la función StopCombatAlarmOnActor tiene un alias (scaonactor). Esto significa que las siguientes dos líneas de código son idénticas:
StopCombatAlarmOnActor
scaonactor
Blocktipe (Bloque)
Hay un limitado número de condiciones que pueden ser usados por los bloques Begin/End, como OnAdd y OnDeath. Cada una de esas condiciones es un bloque. Diferentes tipos de Script tienen diferentes bloques disponibles para ellos, por tanto es de ayuda dividir los bloques en categorías:
• Efecto
o ScriptEffectFinish
o ScriptEffectStart
o ScriptEffectUpdate
• Específicos de Referencia
o OnActivate
o OnActorEquip
o OnActorUnequip
o OnAdd
o OnCombatEnd
o OnDeath
o OnDestructionStageChange
o OnDrop
o OnEquip
o OnHit
o OnHitWith
o OnLoad
o OnMagicEffectHit
o OnMurder
o OnPackageChange
o OnPackageDone
o OnPackageStart
o OnRelease
o OnSell
o OnStartCombat
o OnTrigger
o OnTriggerEnter
o OnTriggerLeave
o OnUnequip
o SayToDone
• General
o GameMode
o MenuMode
Como puedes ver la gran mayoría de bloques son específicos de referencias. Muchos de ellos pueden solo ser usados en ciertos tipos de formas (Form). Por ejemplo, OnDeath solo puede ser usado en actores (PersonajesNoJugadores y criaturas), y OnAdd solo en formas (Forms) utilizables como las armas.
EditorID
Todas las formas (Forms) no referenciales, así como ciertas referencias, tienen EditorIDs. Son básicamente alias para sus FormIIDs, y son usados en Scripts para referirse a formas u objetos específicos.
EditorRefID
El EditorID de una referencia.
Effect Script (Script de Efecto)
Los Effect Scripts pueden ser ligados a las formas (Form) de Base Effect, las cuales pueden ser usadas para efectos de objeto, efectos de actor y formas (forms) de ingestible. Los Effects Scripts son Scripts de referencia, aunque también se activan en el objetivo del efecto al contrario que los objetos con Script, los cuales serían el efecto en si misno. Debido a esto, las variables declaradas en Effect Scripts no pueden ser accedidas remotamente. Los Effect Script están limitados a tres bloque utilizables:
• ScriptEffectStart
• ScriptEffectUpdate
• ScriptEffectFinish
False (Falso)
Cero
Form (Forma)
Casi todos los objetos almacenados en un archivo de datos es un tipo de forma (Form). Hay muchos tipos diferentes de formas, y cada uno de ellos almacena información acerca de un tipo diferente de objeto. Por ejemplo, las formas de Scripts almacenan información acerca de secuencias de comandos (Scripts), mientras que las formas de armas almacenar información acerca de las armas. Diferentes formas pueden ser identificadas por su único EditorID y FormID.
FormID
Un número hexadecimal de seis dígitos que especifica una forma (Form). Los dos primeros dígitos de un FormID corresponden con la posición del archivo de datos tal cual se origina en tu orden de carga. Esto permite hasta 255 archivos de datos para ser cargados simultáneamente, incluyendo Fallout3.esm. El prefijo "ff" está reservado para las formas que se almacenan en el archivo de guardado (“partida salvada”)(la mayoría de ellas serán referencias).
Function (Función)
Aparte de la manipulación de variables, todo en programación es hecho por funciones. Ciertas funciones se pueden utilizar para determinar la información acerca de una forma específica o el estado actual del juego, y otras pueden ser utilizadas para realizar acciones (que afectan a formas específicas o el estado del juego de alguna manera). Funciones que actúan sobre referencias específicas se conocen como funciones de referencia, mientras que las funciones que no actúan sobre formas específicas se conocen como funciones no-referenciales.
Objects Scripts (Scripts de Objetos)
Los Script de Objetos se pueden ligar a formas (Forms) que pueden tener referencias, tales como actores, equipamiento, o armas. Son Scripts de referencia, y puede usar de bloques de especificación de referencia. Los Script de Objetos se ejecutan todos los fotogramas en el que el objeto con el Script (o su contenedor, en el caso de objetos en un inventario) sea cargado.
Operator (Operador)
Los operadores se utilizan para manipular los valores, y se dividen en tres categorías:
Operadores aritméticos
+ Suma
- Resta
* Multiplicación
/ División
% Modulo
Operadores lógicos
&& Y
|| O
Los operadores de comparación devolverán 1 si evalúan como verdadero, y 0 si evalúan como falso. Por ejemplo, "3 <5" obtendrá 1 porque la declaración "3 es menor que 5" es cierta, mientras que "3 == 5" volverá 0 porque la declaración "3 es igual a 5" es falso. Estos operadores no pueden devolver ningun valor distinto de 1 y 0.
Al igual que los operadores de comparación, los operadores lógicos también devolverán 1 si evalúan como verdadero, y 0 si evalúan como falso. Aquí hay una tabla que muestran los posibles resultados de los operadores lógicos:
A B A&&B A||B falso falso falso falso falso cierto falso cierto cierto falso falso cierto cierto cierto cierto cierto
Aunque los operadores lógicos NOT y XOR no están disponibles, puedes aún alcanzar la misma salida usando “A == 0” en lugar de “NOT A” y "( A||B )-(A&&B)" en lugar de "A XOR B".
Recuerda que cuando uses expresiones complicadas es de ayuda utilizar paréntesis para que tú o cualquiera que lea el código pueda observar en qué orden son evaluados los operadores.
Parameter (Parámetro)
Muchas funciones, especialmente aquellas que llevan a cabo acciones en lugar de conseguir información, requieren más datos para funcionar correctamente. Esta información es pasada a las funciones a través de parámetros, los cuales están separados del nombre de la función por un espacio, y/o una coma opcional. Por ejemplo, las siguientes dos líneas son equivalentes:
player.AddItem Caps001 10
player.AddItem,Caps001,10
Algunas funciones tienen parámetros opcionales, los cuales pueden ser omitidos de la function llamada. Si no están incluidos en la función entonces usarán un valor por defecto. Por ejemplo, las siguientes dos líneas son equivalentes:
player.AddItem Caps001 10 0
player.AddItem Caps001 10
Player (Jugador)
Varias formas tienen una dura codificación en el juego. La mayoría de ellas no es necesario nombrarlas, pero una muy importante y útil es la referencia "player". Básicamente, el hecho de que esta referencia sea así significa que siempre podrás usar la referencia del jugador con la palabra clave "player", que es el EditorRefID del jugador, sin importar si los archivos de datos son o no cargados.
Quest Script
Los Quest Scripts pueden ser ligados a las formas (Form) de quests y son Scripts no-referenciales. No pueden usar bloques que requieran especificar referancias.Los Quest Scripts tienen la habilidad única de tener un tiempo de retraso (Delay Time) que define cuan a menudo el Script será ejecutado. Esto es definido en el menú de la quest en cuestión y puede ser cambiado con un Script utilizando la función SetQuestDelay. Para que un Script de Quest se ejecute cada fotograma, el tiempo de retraso debería ser configurado a un valor muy bajo como 0.001.
Referencia
Una referencia es un tipo especial de forma (Form). Las referancias son las formas que puedes ver o con las que interactuar en el mundo del juego, y básicamente actúan como señaladores o marcadores de las formas. Como tales, contienen dos conjuntos de información:
- La información específica de la referencia.
- Información sobre el objeto base (la forma en la que la referencia se basa)
Reference Script (Script de referencia)
Los Scripts ligados a Formas que pueden tener referencias son llamados Scripts de Referencia. Cada referencia a una de esas formas activará su propia instancia de ese Script.
RefID
El FormID de una referencia.
True (Cierto)
Valor diferente de cero.
Variable
Una variable es cualquier cosa que permite almacenar información en un Script para su uso posterior. Hay tres tipos de variables disponibles en la programación de Fallout 3, cada una almacenando un diferente tipo de información:
-int / short / long
Almacena un número íntegro. Tiene un rango de -2,147,483,648 a 2,147,483,647.
-float
Almacena un número con punto flotante (con una coma decimal). Tiene un rango que incluye -3.402823x1038 a -1.175494x10-38, 0 y 1.175494x10-38 a 3.402823x1038.
-ref / reference
Almacena una FormID. Usualmente usado para guardar una RefID, por eso se llama ref/reference.