Registrarse

[pokeemerald] Añadiendo puertas de 16x16px

Jaizu

Decomp user
Bienvenidos a otro maravilloso tutorial del tito Jaizu para decomp.

Esta vez os enseñaré a añadir puertas de 16x16px sin perder las que ya contiene la ROM, es decir, un nuevo tipo de puertas.

La magia de las puertas está en src/field_door.c
Lo primero que hay que hacer es crear nuestras puertas pequeñas.
Buscamos:
Código:
static const struct DoorAnimFrame sDoorCloseAnimFrames[] =
{
    {4, 0x200},
    {4, 0x100},
    {4, 0},
    {4, -1},
    {0, 0},
};
Y debajo añadimos:
Código:
static const struct DoorAnimFrame sSmallDoorOpenAnimFrames[] =
{
    {4, -1},
    {4, 0},
    {4, 0x80},
    {4, 0x100},
    {0, 0},
};
static const struct DoorAnimFrame sSmallDoorCloseAnimFrames[] =
{
    {4, 0x100},
    {4, 0x80},
    {4, 0},
    {4, -1},
    {0, 0},
};
Y ahora lo único que tenemos que es hacer es que las funciones por defecto comprueben el tamaño de las nuevas puertas y ya, sencillo.
Iremos a la función CopyDoorTilesToVram y cambiaremos el else por un else if y añadiremos un else con nuestra puerta.
Esta es algo liosa porque hay que tener el cuenta el tamaño que tiene puerta en bloques y restarle esa cantidad a la VRAM para que cargue nuestra puerta correctamente. Así que esta función os la voy a dejar hecha, debería quedar tal que así:
Código:
static void CopyDoorTilesToVram(const struct DoorGraphics *gfx, const struct DoorAnimFrame *frame)
{
    if (gfx->size == 2)
        CpuFastSet(gfx->tiles + frame->offset, (void *)(VRAM + 0x7E00), 0x80);
    else if (gfx->size == 1)
        CpuFastSet(gfx->tiles + frame->offset, (void *)(VRAM + 0x7F00), 0x40);
    else
        CpuFastSet(gfx->tiles + frame->offset, (void *)(VRAM + 0x7F80), 0x20);
}
Ahora en la función DrawCurrentDoorAnimFrame, más de lo mismo. Lo único que hacemos es cambiar el else por un else if que comprueba el tamaño de la puerta y luego un else con nuestra puerta. Quedaría tal que así:
Código:
static void DrawCurrentDoorAnimFrame(const struct DoorGraphics *gfx, u32 x, u32 y, const u8 *pal)
{
    u16 arr[24];
    
    if (gfx->size == 2)
    {
        door_build_blockdef(&arr[8], 0x3F0, pal);
        DrawDoorMetatileAt(x, y - 1, &arr[8]);
        door_build_blockdef(&arr[8], 0x3F4, pal + 4);
        DrawDoorMetatileAt(x, y, &arr[8]);
        door_build_blockdef(&arr[8], 0x3F8, pal);
        DrawDoorMetatileAt(x + 1, y - 1, &arr[8]);
        door_build_blockdef(&arr[8], 0x3FC, pal + 4);
        DrawDoorMetatileAt(x + 1, y, &arr[8]);
    }
    else if (gfx->size == 1)
    {
        door_build_blockdef(&arr[0], 0x3F8, pal);
        DrawDoorMetatileAt(x, y - 1, &arr[0]);
        door_build_blockdef(&arr[0], 0x3FC, pal + 4);
        DrawDoorMetatileAt(x, y, &arr[0]);
    }
    else
    {
        door_build_blockdef(&arr[0], 0x3FC, pal);
        DrawDoorMetatileAt(x, y, &arr[0]);
    }
}
También lo mismo para la función DrawClosedDoorTiles, que por cierto, los nombres de las funciones explican muy bien qué hacen cada una.
Esa quedaría tal que así:
Código:
static void DrawClosedDoorTiles(const struct DoorGraphics *gfx, u32 x, u32 y)
{
    CurrentMapDrawMetatileAt(x, y);
    if (gfx->size >= 1)
    {
        CurrentMapDrawMetatileAt(x, y - 1);
    }
    if (gfx->size == 2)
    {
        CurrentMapDrawMetatileAt(x + 1, y - 1);
        CurrentMapDrawMetatileAt(x + 1, y);
    }
}
Lo mismo para DrawOpenedDoor....
Código:
static void DrawOpenedDoor(const struct DoorGraphics *gfx, u32 x, u32 y)
{
    gfx = GetDoorGraphics(gfx, MapGridGetMetatileIdAt(x, y));
    if (gfx != NULL) {
    if (gfx->size >= 1) 
        DrawDoor(gfx, GetLastDoorFrame(sDoorOpenAnimFrames, sDoorOpenAnimFrames), x, y);
    else
        DrawDoor(gfx, GetLastDoorFrame(sSmallDoorOpenAnimFrames, sSmallDoorOpenAnimFrames), x, y);
    }
}
Y para las dos siguientes, StartDoorOpenAnimation y StartDoorCloseAnimation más de lo mismo:
Código:
static s8 StartDoorOpenAnimation(const struct DoorGraphics *gfx, u32 x, u32 y)
{
    gfx = GetDoorGraphics(gfx, MapGridGetMetatileIdAt(x, y));
    if (gfx == NULL)
    {
        return -1;
    }
    else
    {
        if (gfx->size == 2)
            return StartDoorAnimationTask(gfx, sBigDoorOpenAnimFrames, x, y);
        else if (gfx->size == 1)
            return StartDoorAnimationTask(gfx, sDoorOpenAnimFrames, x, y);
        else 
            return StartDoorAnimationTask(gfx, sSmallDoorOpenAnimFrames, x, y);
    }
}

static s8 StartDoorCloseAnimation(const struct DoorGraphics *gfx, u32 x, u32 y)
{
    gfx = GetDoorGraphics(gfx, MapGridGetMetatileIdAt(x, y));
    if (gfx == NULL)
        return -1;
    else if (gfx->size >= 1) 
        return StartDoorAnimationTask(gfx, sDoorCloseAnimFrames, x, y);
    else
        return StartDoorAnimationTask(gfx, sSmallDoorCloseAnimFrames, x, y);
}
Ahora lo único que nos queda es decirle qué puertas será de 16x16px.
En mi caso tocaré la del Profesor Birch.
Dentro de
Código:
static const struct DoorGraphics sDoorAnimGraphicsTable[] =
Busco mi puerta y le cambio el tamaño 1 por el tamaño 0, y me queda tal que así:
Código:
    {METATILE_Petalburg_Door_BirchsLab,                     DOOR_SOUND_NORMAL,  0, sDoorAnimTiles_BirchsLab, sDoorAnimPalettes_BirchsLab},
Cada puerta tiene una paleta del tileset asignada a cada bloque de su puerta.
Como nuestras nuevas puertas tienen la mitad de bloques que las standar, debemos buscar esa parte y eliminar las paletas del bloque no existente.
En mi caso esto:
Código:
static const u8 sDoorAnimPalettes_BirchsLab[] = {8, 8, 8, 8, 8, 8, 8, 8};
Quedaría como esto:
Código:
static const u8 sDoorAnimPalettes_BirchsLab[] = {8, 8, 8, 8};
Finalmente solo nos quedaría editar el gráfico de la puerta para que sea la mitad de alto que el anterior. Este no es un tutorial de edición de imágenes así que os dejo esa parte para vosotros, yo me gozaré mi super puerta de 16x16px, que sin cambiarle el gráfico ha quedado cuestionable cuanto menos...
 
Arriba