24977-Crianza_de_Pokémon_Shiny_en_la_guardería_\[100%]_\[INVESTIGACIÓN_FINALIZADA]_\[RUBY]
#0
Doctor Juanjo 12932
Notifiquese: Que el Grupo POSITRON, en persona de su representante [MENTION=12932]Juanjo[/MENTION] considere que esta investigación sea abierta al público debido a que el grupo POSITRON no se encuentra en su mejor momento ni sus miembros están completamente enfocados en su subforo y al mismo tiempo incitar a la generación de nuevos miembros.



PRESENTA:

¿CÓMO CRIAR POKéMON SHINY EN TERCERA GENERACIÓN?
PSEB System - Positron Shiny Egg Breeding System

INTRODUCCIÓN

Como muchos sabrán en los juegos de segunda generación era genial poder criar pokémon shinys, es decir si lograbas conseguir uno de estos raros especímenes al criar en la guardería obtenías un 1.5% de posibilidad (1/64) de tener un huevo del que nacería un pokémon shiny.



Para tercera generación esto se perdió. Y los pokémon shiny quedaron relegados a un simple azar y no a una mutación genética que me gustaba más.

MISIÓN

Lograr que la guardería de tercera generación logre generar ese 1.5% de probabilidad de generar un huevo shiny si el padre o la madre es shiny.

PROCEDIMIENTO



LOGROS CONSEGUIDOS

ESTUDIAR EL SCRIPT DE LA GUARDERÍA: Al investigarlo he descubierto que el special 0xB5 genera en el y en el los Pokémon de la guardería (Y hace algunas cosas más que no he descubierto).

El special2 LASTRESULT 0xB6 devuelve en la variable LASTRESULT un número que:

0x0 = No tienes Pokes y se presenta.

0x1 = Te va a dar un huevo.

0x2 = Tienes un solo Poke en la guardería y te dice que está bien.

0x3 = Tienes 2 Pokes en la guardería y te dice que están bien.

La parte del script que interesa es:

#org 0x1B22B2
preparemsg 0x81B27A2 '"[player] received the EGG from\nth..."
fanfare 0x16F
waitfanfare
waitmsg
waitkeypress
msgbox 0x81B27CD MSG_KEEPOPEN '"Take good care of it."
special 0xB8
clearflag 0x86
release
end

No se observa ningún giveegg.

LOGRAR QUE EL HUEVO SEA SHINY: Aún así introduciendo la rutina del shinyzer:

#org 0x71234A
checkflag 0x1234
if 0x1 call 0x871243C
preparemsg 0x81B27A2 '"[player] received the EGG from\nth..."
fanfare 0x16F
waitfanfare
waitmsg
waitkeypress
msgbox 0x81B27CD MSG_KEEPOPEN '"Take good care of it."
special 0xB8
clearflag 0x86
clearflag 0x1234
release
end

'---------------
#org 0x71243C
setvar 0x8003 0x1
return

De esta manera genero que el huevo que me entreguen sea Shiny. SOLAMENTE si la flag 1234 está activada.

La ventaja de hacer esto es que da independencia total de si el huevo es shiny o no, y el viejo solamente mirara si la flag externa está activa o no. (A este paso lo llamé la palanca de radioactividad de la guardería

CONTROLAR LA PROBABILIDAD DEL 15%:
A pesar de que realmente sera de 1.5%, se ha investigado para un 15% (es más fácil para probarlo pero el valor al final puede ser corregido perfectamente).
Bueno, no se mucho de como se manejan los eventos aleatorios del juego (Supongo que a muy bajo nivel hacen operaciones con bytes y comparan si el resultado están entre algún rango, o algo por el estilo).

Un 15% significa que de 100 posibilidades, 15 son aciertos. Es decir si una variable aleatoria toma 100 posibles valores, 15 de ellos serán aciertos. Por lo que me fui a la fácil: Generar una variable aleatoria random y evaluar los aciertos. ¡Por supuesto no iba a tomar 100 valores y tomar 15 como aciertos! simplemente 15/100 = 3/20. Una variable que toma 20 posiciones de los cuales 3 son aciertos:

'---------------
#org 0x712393
random 0x14
copyvar 0x50FE LASTRESULT
buffernumber 0x2 0x50FE
compare 0x50FE 0x0
if 0x1 goto 0x8712457
compare 0x50FE 0x1
if 0x1 goto 0x8712457
compare 0x50FE 0x2
if 0x1 goto 0x8712457
msgbox 0x87123EF MSG_FACE '" No hay huevos shiny."
end

'---------------
#org 0x712457
msgbox 0x8170CA7 MSG_FACE '" Hay huevos shiny."
setflag 0x1234
end


'---------
' Strings
'---------
#org 0x7123EF
= No hay huevos shiny.

#org 0x170CA7
= Hay huevos shiny.

De esta manera he logrado una especie de "gatillo" que al activarse genera una probabilidad de un 15% de que el huevo sea Shiny o no.

Aquí pueden ver esto funcionando:

YouTube Video

DETERMINAR SI EL POKéMON ES SHINY:

Gracias al método descrito por Mastermind_X, y planteado por [MENTION=13374]Javi4315♪[/MENTION] lo que define que un Pokémon sea Shiny o no es su personalidad que lo podemos obtener como los 4 primeros bytes de la información de un Pokémon (Para más información pueden ver esta investigación de [MENTION=12314]Gershel[/MENTION].

Esos cuatro bytes definen la personalidad del pokemon. Otro dato importante es la ID de entrenador (Que vemos en la TrainerCard) y la ID de entrenador secreta (Un número también aleatorio que no podemos ver).

La fórmula para saber si pokémon es Shiny es:

Trainer ID ⊕ Secret ID ⊕ P1 ⊕ P2

Donde:

Trainer ID, es la ID del TrainerCard que podemos ver en la dirección 0x02024EAE (2 Bytes).

Secret ID, es la ID secreta del Trainer que podemos ver en la dirección 0x02024EB0 (2 Bytes).

P1, son los 2 primeros bytes de la personalidad del pokémon.

P2, son los 2 últimos bytes de la personalidad del pokémon.

⊕, es el operador XOR.

El resultado de esta operación debe dar un valor en hexadecimal que si es menor a 08, entonces el Pokémon es Shiny.

Investigando un poco (Y jugando con los bytes) He descubierto que al almacenar un pokemón en la guardería podemos conseguir la personalidad del pokémon almacenado directamente (Sin tener que buscar cual pokémon del equipo insertamos):

0x20286D0 -> Primer Pokémon de la Guardería

0x2028720 -> Segundo Pokémon de la Guardería

Con esto para identificar un Pokémon Shiny habría que hacer esta operación. (Se requiere ASM para poder hacer XOR).

Gracias a [MENTION=15014]Cheve_X[/MENTION], tenemos una rutina específicamente diseñada para retornar el resultado de la operación para el primer pokemon de la guardería:

Iniciado por Cheve_X

.text
.align 2
.thumb
.thumb_func
.global lesson1

main:
push {r0-r4, lr}
ldr r4, .PKMN_DATA
ldrh r0, [r4]
ldrh r2, [r4, #0X2]
EOR r0, r2
ldr r4, .PKMN_DATA2
ldrh r3, [r4]
ldr r4, .PKMN_DATA3
ldrh r2, [r4]
EOR r3, r2
EOR r0,r3
ldr r1, .VAR
strh r0, [r1]
pop {r0-r1, pc}


.align 2
.PKMN_DATA:
.word 0x20286D0

.PKMN_DATA2:
.word 0x2024EB0

.PKMN_DATA3:
.word 0x2024EAE

.VAR:
.word 0x0201E8C2 + (0x800D * 2)



Para aquellos con problemas en pasarla a HEX...


1F B5 06 4C 20 88 62 88 50 40 05 4C 23 88 05 4C 22 88 53 40 58 40 04 49 08 80 03 BD D0 86 02 02 B0 4E 02 02 AE 4E 02 02 DC E8 02 02

Deben copiar ese código en un Offset vacío que termine en 0, 4, 8 o C, luego deberan usar un callasm a esa direccion+1

Si por ejemplo lo ponen en 0x700000 un script simple con ésto funcionando sería así:


#include std.rbh
#DYNAMIC 0x800000

#org @Inicio
callasm 0x700001
compare LASTRESULT 0x8
if B_> call @NoShiny
msgbox @sms1 MSG_NORMAL
end


#org @NoShiny
msgbox @sms2 MSG_NORMAL '"o hay un Shiny"
end



#org @sms1
= Hay un Shiny

#org @sms2
= No hay un Shiny


INSERTARLO EN EL SCRIPT DE LA GUARDERÍA

Como la rutina de Cheve solo identifica si un Pokemon es shiny (y no el segundo dos), he creado una segunda rutina (Que es igual pero carga el segundo Pokémon)

88 53 40 58 40 04 49 08 80 03 BD D0 86 02 02 B0 4E 02 02 AE 4E 02 02 DC E8 02 02 FF 1F B5 06 4C 20 88 62 88 50 40 05 4C 23 88 05 4C 22 88 53 40 58 40 04 49 08 80 03 BD 20 87 02 02 B0 4E 02 02 AE 4E 02 02 DC E8 02 02

De esta manera el script sería algo así:

'---------------
#include std.rbh
#dynamic 0x712345

#org @Inicio
callasm 0x700001
compare LASTRESULT 0x8
if B_< call @SiShiny
callasm 0x70000D
compare LASTRESULT 0x8
if B_< call @SiShiny
msgbox @sms2 MSG_NORMAL
end


#org @SiShiny
msgbox @sms1 MSG_NORMAL
goto @Proba
end



#org @sms1
= Hay un Shiny

#org @sms2
= No hay un Shiny

#org @Proba
random 0x14
copyvar 0x50FE LASTRESULT
buffernumber 0x2 0x50FE
compare 0x50FE 0x0
if 0x1 goto 0x8712457
compare 0x50FE 0x1
if 0x1 goto 0x8712457
compare 0x50FE 0x2
if 0x1 goto 0x8712457
msgbox 0x87123EF MSG_FACE '" No hay huevos shiny."
end

'---------------
#org 0x712457
msgbox 0x8170CA7 MSG_FACE '" Hay huevos shiny."
setflag 0x1234
end


'---------
' Strings
'---------
#org 0x7123EF
= No hay huevos shiny.

#org 0x170CA7
= Hay huevos shiny.

Este sería el script insertado en la chica (recuerden que es para probar que funcione).

YouTube Video

He insertado la rutina en 0x700000, recuerden que esta incluye una segunda rutina en 0x70000C.

Les dejo el script completo de la guardería con el 100% de esta investigación y listo para usarse: (Con el 1.5%)



EN RESUMEN

Este sistema hace que si alguno de los padres de un huevos es shiny genere un 1.5% de que el pokémon del huevo nazca Shiny.

Investigación iniciada a los 14 día del primer mes de 2014

Investigación principal finalizada a los 18 días del primer mes de 2014. Queda abierta a extensiones, mejores, adaptaciones [FR] y desarrollos posteriores de elementos descubiertos.

AGRADECIMIENTOS

-A [MENTION=12260]Serg!o[/MENTION], por su apoyo, ayuda y estar siempre dispuesto a resolverme dudas.
-A [MENTION=13374]Javi4315♪[/MENTION], por ayudarme y estar respaldando la investigación.
-A [MENTION=15014]Cheve_X[/MENTION], Por su granito de arena por el que pude completar la investigación.
-A [MENTION=26580]BLAx[/MENTION], por su interés y querer ayudar.
-Al grupo POSITRON.
-A la Comunidad Whack a Hack! en general

Firman:
Juanjo - Grupo POSITRON


Ha nacido el PSEB System - Positron Shiny Egg Breeding System