#include "global.h" #include "event_data.h" #include "fieldmap.h" #include "field_effect.h" #include "field_player_avatar.h" #include "metatile_behavior.h" #include "overworld.h" #include "pokemon_menu.h" #include "rom6.h" #include "script.h" #include "secret_base.h" #include "sound.h" #include "constants/field_effects.h" #include "constants/metatile_behaviors.h" #include "constants/songs.h" extern u8 DoSecretBaseCaveFieldEffectScript[]; extern u8 DoSecretBaseTreeFieldEffectScript[]; extern u8 DoSecretBaseShrubFieldEffectScript[]; const u8 gSpriteImage_83D198C[] = INCBIN_U8("graphics/unknown_sprites/83D259C/0.4bpp"); const u8 gSpriteImage_83D1A0C[] = INCBIN_U8("graphics/unknown_sprites/83D259C/1.4bpp"); const u8 gSpriteImage_83D1A8C[] = INCBIN_U8("graphics/unknown_sprites/83D259C/2.4bpp"); const u8 gSpriteImage_83D1B0C[] = INCBIN_U8("graphics/unknown_sprites/83D259C/3.4bpp"); const u8 gSpriteImage_83D1B8C[] = INCBIN_U8("graphics/unknown_sprites/83D259C/4.4bpp"); const u8 gUnusedEmptySpace_83D1C0C[32] = {0}; const u16 gFieldEffectObjectPalette7[] = INCBIN_U16("graphics/field_effect_objects/palettes/07.gbapal"); const u8 gSpriteImage_83D1C4C[] = INCBIN_U8("graphics/unknown_sprites/83D25EC/0.4bpp"); const u8 gSpriteImage_83D1CCC[] = INCBIN_U8("graphics/unknown_sprites/83D25EC/1.4bpp"); const u8 gSpriteImage_83D1D4C[] = INCBIN_U8("graphics/unknown_sprites/83D25EC/2.4bpp"); const u8 gSpriteImage_83D1DCC[] = INCBIN_U8("graphics/unknown_sprites/83D25EC/3.4bpp"); const u8 gSpriteImage_83D1E4C[] = INCBIN_U8("graphics/unknown_sprites/83D25EC/4.4bpp"); const u8 gSpriteImage_83D1ECC[] = INCBIN_U8("graphics/unknown_sprites/83D25C4/0.4bpp"); const u8 gSpriteImage_83D1F4C[] = INCBIN_U8("graphics/unknown_sprites/83D25C4/1.4bpp"); const u8 gSpriteImage_83D1FCC[] = INCBIN_U8("graphics/unknown_sprites/83D25C4/2.4bpp"); const u8 gSpriteImage_83D204C[] = INCBIN_U8("graphics/unknown_sprites/83D25C4/3.4bpp"); const u8 gSpriteImage_83D20CC[] = INCBIN_U8("graphics/unknown_sprites/83D25C4/4.4bpp"); const u8 gSpriteImage_83D214C[] = INCBIN_U8("graphics/unknown_sprites/83D25C4/5.4bpp"); // unused const u16 gFieldEffectObjectPalette8[] = INCBIN_U16("graphics/field_effect_objects/palettes/08.gbapal"); const u8 gSpriteImage_83D21EC[] = INCBIN_U8("graphics/unknown_sprites/83D2688/0.4bpp"); const u8 gSpriteImage_83D22EC[] = INCBIN_U8("graphics/unknown_sprites/83D2688/1.4bpp"); const u8 gSpriteImage_83D23EC[] = INCBIN_U8("graphics/unknown_sprites/83D2688/2.4bpp"); const struct OamData gOamData_83D24EC = { .y = 0, .affineMode = 0, .objMode = 0, .mosaic = 0, .bpp = 0, .shape = 0, .x = 0, .matrixNum = 0, .size = 1, .tileNum = 0, .priority = 2, .paletteNum = 0, .affineParam = 0, }; const union AnimCmd gSpriteAnim_83D24F4[] = { ANIMCMD_FRAME(0, 8), ANIMCMD_FRAME(1, 8), ANIMCMD_FRAME(2, 8), ANIMCMD_FRAME(3, 8), ANIMCMD_FRAME(4, 8), ANIMCMD_END, }; const union AnimCmd gSpriteAnim_83D250C[] = { ANIMCMD_FRAME(0, 8), ANIMCMD_FRAME(1, 8), ANIMCMD_FRAME(2, 8), ANIMCMD_FRAME(3, 8), ANIMCMD_FRAME(4, 8), ANIMCMD_END, }; const union AnimCmd gSpriteAnim_83D2524[] = { ANIMCMD_FRAME(4, 8), ANIMCMD_FRAME(3, 8), ANIMCMD_FRAME(2, 8), ANIMCMD_FRAME(1, 8), ANIMCMD_FRAME(0, 8), ANIMCMD_END, }; const union AnimCmd gSpriteAnim_83D253C[] = { ANIMCMD_FRAME(0, 8, .hFlip = TRUE), ANIMCMD_FRAME(1, 8, .hFlip = TRUE), ANIMCMD_FRAME(2, 8, .hFlip = TRUE), ANIMCMD_FRAME(3, 8, .hFlip = TRUE), ANIMCMD_FRAME(4, 8, .hFlip = TRUE), ANIMCMD_END, }; const union AnimCmd gSpriteAnim_83D2554[] = { ANIMCMD_FRAME(4, 8, .hFlip = TRUE), ANIMCMD_FRAME(3, 8, .hFlip = TRUE), ANIMCMD_FRAME(2, 8, .hFlip = TRUE), ANIMCMD_FRAME(1, 8, .hFlip = TRUE), ANIMCMD_FRAME(0, 8, .hFlip = TRUE), ANIMCMD_END, }; const union AnimCmd gSpriteAnim_83D256C[] = { ANIMCMD_FRAME(0, 8), ANIMCMD_FRAME(1, 8), ANIMCMD_FRAME(2, 8), ANIMCMD_FRAME(3, 8), ANIMCMD_FRAME(4, 8), ANIMCMD_END, }; const union AnimCmd *const gSpriteAnimTable_83D2584[] = { gSpriteAnim_83D24F4, }; const union AnimCmd *const gSpriteAnimTable_83D2588[] = { gSpriteAnim_83D250C, gSpriteAnim_83D2524, gSpriteAnim_83D253C, gSpriteAnim_83D2554, }; const union AnimCmd *const gSpriteAnimTable_83D2598[] = { gSpriteAnim_83D256C, }; const struct SpriteFrameImage gSpriteImageTable_83D259C[] = { {gSpriteImage_83D198C, 0x80}, {gSpriteImage_83D1A0C, 0x80}, {gSpriteImage_83D1A8C, 0x80}, {gSpriteImage_83D1B0C, 0x80}, {gSpriteImage_83D1B8C, 0x80}, }; const struct SpriteFrameImage gSpriteImageTable_83D25C4[] = { {gSpriteImage_83D1ECC, 0x80}, {gSpriteImage_83D1F4C, 0x80}, {gSpriteImage_83D1FCC, 0x80}, {gSpriteImage_83D204C, 0x80}, {gSpriteImage_83D20CC, 0x80}, }; const struct SpriteFrameImage gSpriteImageTable_83D25EC[] = { {gSpriteImage_83D1C4C, 0x80}, {gSpriteImage_83D1CCC, 0x80}, {gSpriteImage_83D1D4C, 0x80}, {gSpriteImage_83D1DCC, 0x80}, {gSpriteImage_83D1E4C, 0x80}, }; static void CaveEntranceSpriteCallback1(struct Sprite *); static const struct SpriteTemplate sSpriteTemplate_CaveEntrance = { .tileTag = 0xFFFF, .paletteTag = 4099, .oam = &gOamData_83D24EC, .anims = gSpriteAnimTable_83D2584, .images = gSpriteImageTable_83D259C, .affineAnims = gDummySpriteAffineAnimTable, .callback = CaveEntranceSpriteCallback1, }; static void TreeEntranceSpriteCallback1(struct Sprite *); const struct SpriteTemplate sSpriteTemplate_TreeEntrance = { .tileTag = 0xFFFF, .paletteTag = 4104, .oam = &gOamData_83D24EC, .anims = gSpriteAnimTable_83D2588, .images = gSpriteImageTable_83D25C4, .affineAnims = gDummySpriteAffineAnimTable, .callback = TreeEntranceSpriteCallback1, }; static void ShrubEntranceSpriteCallback1(struct Sprite *); const struct SpriteTemplate sSpriteTemplate_ShrubEntrance = { .tileTag = 0xFFFF, .paletteTag = 4104, .oam = &gOamData_83D24EC, .anims = gSpriteAnimTable_83D2598, .images = gSpriteImageTable_83D25EC, .affineAnims = gDummySpriteAffineAnimTable, .callback = ShrubEntranceSpriteCallback1, }; const struct SpritePalette gFieldEffectObjectPaletteInfo7 = {gFieldEffectObjectPalette7, 0x1003}; const struct SpritePalette gFieldEffectObjectPaletteInfo8 = {gFieldEffectObjectPalette8, 0x1008}; static void FieldCallback_SecretBaseCave(void); static void StartSecretBaseCaveFieldEffect(void); static void CaveEntranceSpriteCallback2(struct Sprite *); static void CaveEntranceSpriteCallbackEnd(struct Sprite *); static void FieldCallback_SecretBaseTree(void); static void StartSecretBaseTreeFieldEffect(void); static void TreeEntranceSpriteCallback2(struct Sprite *); static void TreeEntranceSpriteCallbackEnd(struct Sprite *); static void FieldCallback_SecretBaseShrub(void); static void StartSecretBaseShrubFieldEffect(void); static void ShrubEntranceSpriteCallback2(struct Sprite *sprite); static void ShrubEntranceSpriteCallbackEnd(struct Sprite *sprite); static void SetCurrentSecretBase(void) { SetCurrentSecretBaseFromPosition(&gPlayerFacingPosition, gMapHeader.events); SetCurrentSecretBaseVar(); } static void AdjustSecretPowerSpritePixelOffsets(void) { switch (gFieldEffectArguments[1]) { case DIR_SOUTH: gFieldEffectArguments[5] = 8; gFieldEffectArguments[6] = 40; break; case DIR_NORTH: gFieldEffectArguments[5] = 8; gFieldEffectArguments[6] = 8; break; case DIR_WEST: gFieldEffectArguments[5] = -8; gFieldEffectArguments[6] = 24; break; case DIR_EAST: gFieldEffectArguments[5] = 24; gFieldEffectArguments[6] = 24; break; } } #if DEBUG void Debug_SetUpFieldMove_SecretPower(void) { u8 metatile; CheckPlayerHasSecretBase(); if (gSpecialVar_Result == 1 || GetPlayerFacingDirection() != DIR_NORTH) { ScriptContext2_Disable(); return; } GetXYCoordsOneStepInFrontOfPlayer(&gPlayerFacingPosition.x, &gPlayerFacingPosition.y); metatile = MapGridGetMetatileBehaviorAt(gPlayerFacingPosition.x, gPlayerFacingPosition.y); if (MetatileBehavior_IsSecretBaseCave(metatile) == TRUE) { SetCurrentSecretBase(); gLastFieldPokeMenuOpened = 0; FieldCallback_SecretBaseCave(); } else if (MetatileBehavior_IsSecretBaseTree(metatile) == TRUE) { SetCurrentSecretBase(); gLastFieldPokeMenuOpened = 0; FieldCallback_SecretBaseTree(); } else if (MetatileBehavior_IsSecretBaseShrub(metatile) == TRUE) { SetCurrentSecretBase(); gLastFieldPokeMenuOpened = 0; FieldCallback_SecretBaseShrub(); } else { ScriptContext2_Disable(); } } #endif bool8 SetUpFieldMove_SecretPower(void) { u8 behavior; CheckPlayerHasSecretBase(); if (gSpecialVar_Result == 1 || GetPlayerFacingDirection() != DIR_NORTH) return FALSE; GetXYCoordsOneStepInFrontOfPlayer(&gPlayerFacingPosition.x, &gPlayerFacingPosition.y); behavior = MapGridGetMetatileBehaviorAt(gPlayerFacingPosition.x, gPlayerFacingPosition.y); if (MetatileBehavior_IsSecretBaseCave(behavior) == TRUE) { SetCurrentSecretBase(); gFieldCallback = FieldCallback_PrepareFadeInFromMenu; gPostMenuFieldCallback = FieldCallback_SecretBaseCave; return TRUE; } if (MetatileBehavior_IsSecretBaseTree(behavior) == TRUE) { SetCurrentSecretBase(); gFieldCallback = FieldCallback_PrepareFadeInFromMenu; gPostMenuFieldCallback = FieldCallback_SecretBaseTree; return TRUE; } if (MetatileBehavior_IsSecretBaseShrub(behavior) == TRUE) { SetCurrentSecretBase(); gFieldCallback = FieldCallback_PrepareFadeInFromMenu; gPostMenuFieldCallback = FieldCallback_SecretBaseShrub; return TRUE; } return FALSE; } static void FieldCallback_SecretBaseCave(void) { gFieldEffectArguments[0] = gLastFieldPokeMenuOpened; ScriptContext1_SetupScript(DoSecretBaseCaveFieldEffectScript); } bool8 FldEff_UseSecretPowerCave(void) { u8 taskId = oei_task_add(); gTasks[taskId].data[8] = (uintptr_t)StartSecretBaseCaveFieldEffect >> 16; gTasks[taskId].data[9] = (uintptr_t)StartSecretBaseCaveFieldEffect; return FALSE; } static void StartSecretBaseCaveFieldEffect(void) { FieldEffectActiveListRemove(FLDEFF_USE_SECRET_POWER_CAVE); FieldEffectStart(FLDEFF_SECRET_POWER_CAVE); } bool8 FldEff_SecretPowerCave(void) { AdjustSecretPowerSpritePixelOffsets(); CreateSprite( &sSpriteTemplate_CaveEntrance, gSprites[gPlayerAvatar.spriteId].oam.x + gFieldEffectArguments[5], gSprites[gPlayerAvatar.spriteId].oam.y + gFieldEffectArguments[6], 148); return FALSE; } static void CaveEntranceSpriteCallback1(struct Sprite *sprite) { PlaySE(SE_M_ROCK_THROW); sprite->data[0] = 0; sprite->callback = CaveEntranceSpriteCallback2; } static void CaveEntranceSpriteCallback2(struct Sprite *sprite) { if (sprite->data[0] < 40) { sprite->data[0]++; if (sprite->data[0] == 20) SetOpenedSecretBaseMetatile(); } else { sprite->data[0] = 0; sprite->callback = CaveEntranceSpriteCallbackEnd; } } static void CaveEntranceSpriteCallbackEnd(struct Sprite *sprite) { FieldEffectStop(sprite, FLDEFF_SECRET_POWER_CAVE); EnableBothScriptContexts(); } static void FieldCallback_SecretBaseTree(void) { gFieldEffectArguments[0] = gLastFieldPokeMenuOpened; ScriptContext1_SetupScript(DoSecretBaseTreeFieldEffectScript); } bool8 FldEff_UseSecretPowerTree(void) { u8 taskId = oei_task_add(); gTasks[taskId].data[8] = (uintptr_t)StartSecretBaseTreeFieldEffect >> 16; gTasks[taskId].data[9] = (uintptr_t)StartSecretBaseTreeFieldEffect; return FALSE; } static void StartSecretBaseTreeFieldEffect(void) { FieldEffectActiveListRemove(FLDEFF_USE_SECRET_POWER_TREE); FieldEffectStart(FLDEFF_SECRET_POWER_TREE); } bool8 FldEff_SecretPowerTree(void) { s16 behavior = MapGridGetMetatileBehaviorAt(gPlayerFacingPosition.x, gPlayerFacingPosition.y) & 0xFFF; if (behavior == MB_SECRET_BASE_SPOT_TREE_1) gFieldEffectArguments[7] = 0; if (behavior == MB_SECRET_BASE_SPOT_TREE_2) gFieldEffectArguments[7] = 2; AdjustSecretPowerSpritePixelOffsets(); CreateSprite( &sSpriteTemplate_TreeEntrance, gSprites[gPlayerAvatar.spriteId].oam.x + gFieldEffectArguments[5], gSprites[gPlayerAvatar.spriteId].oam.y + gFieldEffectArguments[6], 148); if (gFieldEffectArguments[7] == 1 || gFieldEffectArguments[7] == 3) SetOpenedSecretBaseMetatile(); return FALSE; } static void TreeEntranceSpriteCallback1(struct Sprite *sprite) { PlaySE(SE_M_SCRATCH); sprite->animNum = gFieldEffectArguments[7]; sprite->data[0] = 0; sprite->callback = TreeEntranceSpriteCallback2; } static void TreeEntranceSpriteCallback2(struct Sprite *sprite) { sprite->data[0]++; if (sprite->data[0] >= 40) { if (gFieldEffectArguments[7] == 0 || gFieldEffectArguments[7] == 2) SetOpenedSecretBaseMetatile(); sprite->data[0] = 0; sprite->callback = TreeEntranceSpriteCallbackEnd; } } static void TreeEntranceSpriteCallbackEnd(struct Sprite *sprite) { FieldEffectStop(sprite, FLDEFF_SECRET_POWER_TREE); EnableBothScriptContexts(); } static void FieldCallback_SecretBaseShrub(void) { gFieldEffectArguments[0] = gLastFieldPokeMenuOpened; ScriptContext1_SetupScript(DoSecretBaseShrubFieldEffectScript); } bool8 FldEff_UseSecretPowerShrub(void) { u8 taskId = oei_task_add(); gTasks[taskId].data[8] = (uintptr_t)StartSecretBaseShrubFieldEffect >> 16; gTasks[taskId].data[9] = (uintptr_t)StartSecretBaseShrubFieldEffect; return FALSE; } static void StartSecretBaseShrubFieldEffect(void) { FieldEffectActiveListRemove(FLDEFF_USE_SECRET_POWER_SHRUB); FieldEffectStart(FLDEFF_SECRET_POWER_SHRUB); } bool8 FldEff_SecretPowerShrub(void) { AdjustSecretPowerSpritePixelOffsets(); CreateSprite( &sSpriteTemplate_ShrubEntrance, gSprites[gPlayerAvatar.spriteId].oam.x + gFieldEffectArguments[5], gSprites[gPlayerAvatar.spriteId].oam.y + gFieldEffectArguments[6], 148); return FALSE; } static void ShrubEntranceSpriteCallback1(struct Sprite *sprite) { PlaySE(SE_M_POISON_POWDER); sprite->data[0] = 0; sprite->callback = ShrubEntranceSpriteCallback2; } static void ShrubEntranceSpriteCallback2(struct Sprite *sprite) { if (sprite->data[0] < 40) { sprite->data[0]++; if (sprite->data[0] == 20) SetOpenedSecretBaseMetatile(); } else { sprite->data[0] = 0; sprite->callback = ShrubEntranceSpriteCallbackEnd; } } static void ShrubEntranceSpriteCallbackEnd(struct Sprite *sprite) { FieldEffectStop(sprite, FLDEFF_SECRET_POWER_SHRUB); EnableBothScriptContexts(); }