Registrarse

[Scripting] Scripts Basados en el Reloj DNS

Gold

Porrero a tiempo parcial
Miembro insignia
Pues mientras hacía los scripts del GS Chronicles, me topé con la necesidad de hacer el script del Lapras de la Cueva Unión, el cual es un Pokémon especial que solo aparece los Viernes en la tercera planta de la cueva, el resto de días es inaccesible.

El punto es que mientras lo hacía, me percaté que tutorilaes que expliquen como hacer uso del sistema día y noche para scripting es casi nulo. Lo único que hay es este tutorial de Javi4315, el cual aparte de solo darte información sobre scripts basados en la hora (de manera poco optimizada), tiene un título que para cualquiera que lo lea se le haga dificil saber que es sobre el uso de día y hora. Así que haré un tutorial más extenso acerca del uso de los scripts basados en día y noche.

Nota: Por lo obvio que es el título, para el uso de lo que detallaré a continuación es necesario tener instalado el sistema Day, Night and Seasons de Primedialga. Puedes buscar el el foro como aplicarlo o puedes uando la herramienta para aplicar el sistema.
  • Entender la estructura del sistema DNS.
    Este es el primer paso para entender lo que viene. Debemos entender la estructura de datos que la herramienta usa. Para ello basta con abrir la herramienta DNS, y tal y como indica la misma, la información sobre el reloj interno se almacena en la memoria RAM en la dirección 0x0300553C. Quedando de manera mejor explicada así:
    Código:
    0x0300553C: Año actual (2 bytes, little endian)
    0x0300553E: byte no especificado, mas debe tener un uso, no he visto bien
    0x0300553F: Mes actual (1 byte, empezando en 00 para Enero y terminando en 0C para Diciembre)
    0x03005540: Día actual (1 byte, empezando en 00 para 1 y terminando en 1F para 31)
    0x03005541: Día de la semana actual (1 byte, empezando en 00 para Domingo y terminando en 06 para Sábado)
    0x03005542: Hora actual (1 byte, empezando en 00 para las 00:00 o medianoche, y terminando en 17 para las 23:00 u 11PM)
    0x03005543: Minuto actual (1 byte, empezando en 00 para 00 minutos y terminando en 3B para 59 minutos)
    0x03005544: Segundo actual (1 byte, con la misma estructura que los minutos, obviamente esta cambia cada segundo)
    Con al información anterior ya tenemos idea de los datos guardados en la RAM para el reloj, ahora toca ir al siguiente paso, que es entender un comando de scripting muy útil para hacer los scripts basados en el reloj:
  • El comando copybyte.
    Este sencillo comando nos hará un gran favor para comprobar de manera muy eficaz los datos del día de la semana. Lo que hace este comando es simplemente copiar el byte almacenado en una dirección de la RAM hacia otra dirección de la RAM, sobreescribiendo así cualquier dato anterior en dicha dirección.la estructura es la siguiente:
    Código:
    copybyte 0x(dirección destino) 0x(Dirección donde se extraerá el byte)
    Te preguntarás ¿Porqué el comando copybyte? Pues la respuesta es que como vimos antes, los datos del reloj están en cierta direcciónd e la RAM, podemos así copiar los datos hacia la dirección de la RAM de las variables temporales, en este caso nos valdremos de la dirección donde se guarda la variable 0x800D, mejor conocida como LASTRESULT.

    Con lo anterior ya tenemos idea de que hacer, ahora viene lo bueno. Hacer un evento basado en el reloj.

1. Script basado en el estado del día.

Esto es lo que el tuto de Javi que puse arriba explica, mas yo lo explicaré de una manera más eficiente. Verán, el tuto de Javi está orientado para que ciertos scripts sucedan a ciertas horas del día. No es malo, pero si solo queremos un script que se ejecute de noche, será innecesariamente largo. Ahora explico la manera más eficiente de hacerlo.

Cuando insertas el sistema RTC, la herramienta te pide una dirección de la RAM libre para poner ahí el "statusbyte" del RTC, por defecto la herramienta escribe en 0x0203C000. El statusbyte se refiere a el estado del día actual. La estructura es la siguiente:

Código:
Statusbytes 01, 02 y 03: Marcan que es día
Statusbytes 04, 05 y 00: Marcan que es de noche
Entonces con la información anterior ya puedo hacer mi script que sucederá solo de día. El ejemplo es el siguiente:

Código:
#dynamic 0xC00000

'---------------
#org @start
copybyte 0x203C000 0x3005541 //Copia el byte donde se almacena el statusbyte a la dirección donde está LASTRESULT.
compare LASTRESULT 0x1 //comprueba que el statusbyte sea 0x01 (Equivale de 04:00 a 06:00 horas) 
if 0x1 goto @dia //Si es un statusbyte de día, entonces saltará al siguiente script
compare LASTRESULT 0x2 //comprueba que el statusbyte sea 0x02 (Equivale de 06:00 a 17:00 horas) 
if 0x1 goto @dia //Si es un statusbyte de día, entonces saltará al siguiente script
compare LASTRESULT 0x3 //comprueba que el statusbyte sea 0x03 (Equivale de 17:00 a 19:00 horas) 
if 0x1 goto @dia //Si es un statusbyte de día, entonces saltará al siguiente script
msgbox   [MENTION=37022]esno[/MENTION]che MSG_NORMAL //a partir de aquí se ejecutan los comandos en caso sea de noche, puedes poner lo que sea. Para este ejemplo puse un msgbox
end

#org @dia
msgbox @esdia MSG_NORMAL //aquí empiezan a ejecutarse los scripts en caso sea de día
giveitem 0x1 0x1 MSG_OBTAIN
end

#org @esdia
= Que bien que es de día\nToma este objeto, chaval!

#org   [MENTION=37022]esno[/MENTION]che
= ¿No has visto la hora, chaval?\ndeberías estar en tu cama.
Y de esta manera que el script muy simplificado para que se ejecute solo si es de día, para hacer lo contrario basta con modificar los compare para que comprueben los statusbyte de noche. O simplemente usar la misma plantilla,pero modificando lo que pase en el día/noche.

2. Script basado en el día de la semana.

Bueno, este es parecido al enterior, peor aquí lo haré un pelín más complejo. Lo que voy a hacer es replicar el evento de Lapras de Pokémon Oro/Plata/Cristal. En dichas versiones cada Viernes aparece un Lapras en la Cueva Unión, con el cual puedes luchar y atrapar. Cada Viernes aparece un nuevo Lapras, mas solo aparece uno cada Viernes.

Lo que haré aqui es tirar de un script de nivel tipo 01 o 03 para que elscript sea quien aparezca o desaparezca a Lapras en el mapa al entrar al mapa. Me valdré de dos flags para ello, la primera es la que controla la visibilidad de Lapras, la segunda es la que determina si hemos batallado con Lapras. En el script de Lapras simplemente pongo un wildbattle para el encuentro. Al finalizar el mismo se pondrán dos setflags que son las anteriores mencionas (En el ejemplo de abajo, 0x9C3 es la de visibilidad de Lapras, 0x9C4 si ya peleamos con Lapras, recuerden, estas flags no son válidas por defecto en FR. Yo las uso porque ya he expandido el número de flags disponibles)

Código:
//---------------
#Dynamic 0xC00000
#org @start
copybyte 0x20370D0 0x3005541 //copia el byte de la dirección B en la dirección A (Nuestro caso la dirección de la RAM de LASTRESULT (0x800D)
compare LASTRESULT 0x5 //compara con LASTRESULT si el día es Viernes (0x5)
if 0x1 goto @viernes //Si es viernes, salta al siguiente script
setflag 0x9C3 //Si no es Viernes, seguirá activando la flag indicada
compare LASTRESULT 0x5 //Compara de nuevo si no es Viernes
if 0x5 call @fixflag //Si el día es cualquiera que no sea Viernes, llama el siguiente script (Esta es para hacer que puedas volver a pelear con otro Lapras el próximo Viernes)
end //(Al acabar la llamada, el script acaba)

//---------------
#org @viernes
checkflag 0x9C4 //Comprueba si ya peleamos hoy con Lapras
if 0x1 goto @nothing //Si ya peleamos, salta al siguiente script, que no hará nada más
clearflag 0x9C3 //Reestablece la flag indicada, para así poder hacer aparacer a Lapras
end

//---------------
#org @nothing
end //Cualquier script que salte hacia aquí no hará nada y acabará

#org @fixflag
clearflag 0x9C4 //reestablece la flag indicada, para que cuando sea Viernes, podamos volver a luchar con Lapras
return //Como el script fue llamado, es obligatorio que regrese al script que lo llamó
El script de arriba quizás no sea la mejor manera de replicar dicho evento, pero es la manera más sencilla que encontré para solucionar dicho problema.

3. Script basado en una hora específica del día

Puedes usar este mismo tuto de Javi4315 para este proceso

4. Script basado en una estación del año

De nuevo, Javi ya hizo un tuto que cubre exactamente esto

Y es todo. Hay más aplicaciones para el sistema, como por ejemplo poder hacer un script el día del cumpleaños del jugador o uno durante cierto día del año. pero es lo que encontré que puede ser usado más frecuentemente. Y recuerden, este tuto vale para cualquier rombase que sea compatible con el sistema DNS.
 

BLAx501!

A veces comento en temas :3
Miembro de honor
Usuario de Platino
Respuesta: GBA | Scripts Basados en el Reloj DNS

Buen tutorial @Dr.Seuss, siempre es genial contar con herramientas para hacer el mundo de los proyectos que se desarrollan más vivo e interactivo.

Cada vez se irá dejando más de lado el ROM Hacking tradicional en pos de las potentes decompilaciones, pero nunca está de más tener este tipo de información a mano para los que aún siguen desarrollando sus proyectos "a la antigua" por la dificultad de portear el trabajo realizado a las nuevas plataformas.
 

IIWolfgangII

Usuario de oro
Respuesta: GBA | Scripts Basados en el Reloj DNS

Hola Dr. por alguna Razón en mi Rom, teniendo instalado ya el DNS y el RTC el "1. Script basado en el estado del día." Nunca Ejecuta.. y copie uno exactamente como el que escribiste y otro echo por mi, y aun nada. Solo se Ejecuta la Parte de "msgbox @esnoche" Dándome a entender que siendo la hora que sea, todo lo anterior es Ignorado!!
 

Bugrhak

A long time ago I used to call myself "Subzero".
Respuesta: GBA | Scripts Basados en el Reloj DNS

Hola Dr. por alguna Razón en mi Rom, teniendo instalado ya el DNS y el RTC el "1. Script basado en el estado del día." Nunca Ejecuta.. y copie uno exactamente como el que escribiste y otro echo por mi, y aun nada. Solo se Ejecuta la Parte de "msgbox @esnoche" Dándome a entender que siendo la hora que sea, todo lo anterior es Ignorado!!
Debería de ejecutarse correctamente, vamos, que he mirado muy por arriba el script y no le veo fallos.
¿Con que herramienta has instalado el sistema DNS? ¿Con la herramienta de PrimeDialga?
 

IIWolfgangII

Usuario de oro
Perdon por la Tardanza de la Respuesta!! De echo estoy usando una Rom Base que se encuentra en Whack de "Leon y UltimaSoul" instale el Dns con uno de los Ips.. aunque debo decir una cosa, este Script no me funciona pero cuando hice que un Npc me diga el Horario lo decia en tiempo real, osea que funciona el RTC. De echo estoy tratando de ver por que no me funciona este script.. o tal vez sea otra cosa ya vere xD
Y si, Fue con el Prime Dialga!
 

IIWolfgangII

Usuario de oro
Paso a dejarles el Codigo, como yo lo puse en un Script de Nivel.

#dynamic 0x800000

#org @inicio
copybyte 0x20370D0 0x3005542
compare LASTRESULT 0x5
if 0x2 goto @Dia
compare LASTRESULT 0x16
if 0x3 goto @Dia
goto @noche
end

#org @Dia
setflag 0x22D
setflag 0x22F
setflag 0x23E
setflag 0x242
setflag 0x24C
hidesprite 0x1
hidesprite 0x2
hidesprite 0x3
hidesprite 0x4
hidesprite 0x5
end

#org @noche
clearflag 0x22D
clearflag 0x22F
clearflag 0x23E
clearflag 0x242
clearflag 0x24C
showsprite 0x1
showsprite 0x2
showsprite 0x3
showsprite 0x4
showsprite 0x5
end
 

Bugrhak

A long time ago I used to call myself "Subzero".
Paso a dejarles el Codigo, como yo lo puse en un Script de Nivel.

#dynamic 0x800000

#org @inicio
copybyte 0x20370D0 0x3005542
compare LASTRESULT 0x5
if 0x2 goto @Dia
compare LASTRESULT 0x16
if 0x3 goto @Dia
goto @noche
end

#org @Dia
setflag 0x22D
setflag 0x22F
setflag 0x23E
setflag 0x242
setflag 0x24C
hidesprite 0x1
hidesprite 0x2
hidesprite 0x3
hidesprite 0x4
hidesprite 0x5
end

#org @noche
clearflag 0x22D
clearflag 0x22F
clearflag 0x23E
clearflag 0x242
clearflag 0x24C
showsprite 0x1
showsprite 0x2
showsprite 0x3
showsprite 0x4
showsprite 0x5
end
Le voy a hacer una pequeña pero necesaria corrección a tu script:

el "goto @noche" que pones antes del "end" en el script principal no es necesario. En vez de ese "goto" puedes poner directamente lo que iría a partir del puntero "@noche".
De esa manera te evitas gastar un par de bytes (los del comando "goto" mas el puntero al subscript).
Te dejo el script ya corregido:

Código:
#dynamic 0x800000

#org @inicio
copybyte 0x20370D0 0x3005542
compare LASTRESULT 0x5
if 0x2 goto @Dia
compare LASTRESULT 0x16
if 0x3 goto @Dia
clearflag 0x22D  //noche
clearflag 0x22F
clearflag 0x23E
clearflag 0x242
clearflag 0x24C
showsprite 0x1
showsprite 0x2
showsprite 0x3
showsprite 0x4
showsprite 0x5
end

#org @Dia
setflag 0x22D
setflag 0x22F
setflag 0x23E
setflag 0x242
setflag 0x24C
hidesprite 0x1
hidesprite 0x2
hidesprite 0x3
hidesprite 0x4
hidesprite 0x5
end
 
Arriba