diff options
author | PikalaxALT <PikalaxALT@users.noreply.github.com> | 2019-10-04 16:33:09 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-04 16:33:09 -0400 |
commit | 712ee66e6154d734ea3960cc14ff1f4c1aaa639e (patch) | |
tree | c1e477bdf115f9191f19eb0cde8d75e1c606ab82 /src | |
parent | 0cf4c9f25c2fe165c53a0c24f93a31a27ea42d6a (diff) | |
parent | 44b5d84a840c2c88972d72432e85b59cdc472565 (diff) |
Merge pull request #109 from PikalaxALT/wild_pokenmon_area
Wild pokemon area
Diffstat (limited to 'src')
-rw-r--r-- | src/pokedex_area_markers.c | 238 | ||||
-rw-r--r-- | src/wild_pokemon_area.c | 308 |
2 files changed, 546 insertions, 0 deletions
diff --git a/src/pokedex_area_markers.c b/src/pokedex_area_markers.c new file mode 100644 index 000000000..d3c36a83e --- /dev/null +++ b/src/pokedex_area_markers.c @@ -0,0 +1,238 @@ +#include "global.h" +#include "malloc.h" +#include "bg.h" +#include "decompress.h" +#include "gpu_regs.h" +#include "palette.h" +#include "task.h" +#include "wild_pokemon_area.h" +#include "pokedex_area_markers.h" + +static const u16 sMarkerPal[] = INCBIN_U16("data/pokedex_area_markers/marker.gbapal"); +static const u32 sMarkerTiles[] = INCBIN_U32("data/pokedex_area_markers/marker.4bpp.lz"); + +static const struct Subsprite sSubsprite0 = { + .size = ST_OAM_SIZE_0, + .shape = ST_OAM_SQUARE, + .priority = 1, + .tileOffset = 0 +}; + +static const struct Subsprite sSubsprite1 = { + .size = ST_OAM_SIZE_0, + .shape = ST_OAM_H_RECTANGLE, + .priority = 1, + .tileOffset = 1 +}; + +static const struct Subsprite sSubsprite2 = { + .size = ST_OAM_SIZE_0, + .shape = ST_OAM_V_RECTANGLE, + .priority = 1, + .tileOffset = 3 +}; + +static const struct Subsprite sSubsprite3 = { + .size = ST_OAM_SIZE_2, + .shape = ST_OAM_H_RECTANGLE, + .priority = 1, + .tileOffset = 5 +}; + +static const struct Subsprite sSubsprite4 = { + .size = ST_OAM_SIZE_2, + .shape = ST_OAM_V_RECTANGLE, + .priority = 1, + .tileOffset = 13 +}; + +static const struct Subsprite sSubsprite5 = { + .size = ST_OAM_SIZE_2, + .shape = ST_OAM_H_RECTANGLE, + .priority = 1, + .tileOffset = 21 +}; + +static const struct Subsprite sSubsprite6 = { + .size = ST_OAM_SIZE_2, + .shape = ST_OAM_V_RECTANGLE, + .priority = 1, + .tileOffset = 29 +}; + + +static const struct Subsprite *const sSubsprites[] = { + &sSubsprite0, + &sSubsprite1, + &sSubsprite2, + &sSubsprite3, + &sSubsprite4, + &sSubsprite5, + &sSubsprite6 +}; + +static const s8 sSubspriteLookupTable[][4] = { + { 0, 0x00, 0x00 }, + { 0, 0x36, 0x2c }, + { 0, 0x36, 0x1c }, + { 0, 0x36, 0x0c }, + { 0, 0x5c, 0x0c }, + { 0, 0x6e, 0x18 }, + { 0, 0x5c, 0x24 }, + { 0, 0x4c, 0x18 }, + { 0, 0x4e, 0x34 }, + { 0, 0x36, 0x3e }, + { 0, 0x2a, 0x02 }, + { 0, 0x5c, 0x18 }, + { 2, 0x36, 0x20 }, + { 2, 0x36, 0x10 }, + { 1, 0x3d, 0x0c }, + { 1, 0x4d, 0x0c }, + { 0, 0x5c, 0x12 }, + { 0, 0x5c, 0x1e }, + { 0, 0x54, 0x18 }, + { 1, 0x62, 0x18 }, + { 1, 0x62, 0x0c }, + { 2, 0x6e, 0x0c }, + { 1, 0x62, 0x24 }, + { 4, 0x6a, 0x19 }, + { 1, 0x64, 0x2e }, + { 2, 0x5e, 0x2d }, + { 1, 0x55, 0x34 }, + { 0, 0x44, 0x18 }, + { 4, 0x3e, 0x1a }, + { 1, 0x40, 0x34 }, + { 0, 0x4e, 0x3c }, + { 3, 0x37, 0x3a }, + { 2, 0x36, 0x32 }, + { 1, 0x28, 0x1c }, + { 4, 0x26, 0x04 }, + { 0, 0x5c, 0x04 }, + { 3, 0x5a, 0xfe }, + { 0, 0x33, 0x14 }, + { 1, 0x3d, 0x12 }, + { 0, 0x48, 0x08 }, + { 0, 0x57, 0x08 }, + { 0, 0x70, 0x0e }, + { 0, 0x71, 0x14 }, + { 0, 0x71, 0x19 }, + { 1, 0x4e, 0x2c }, + { 0, 0x41, 0x3c }, + { 0, 0x34, 0x3e }, + { 0, 0x2d, 0x07 }, + { 0, 0x0a, 0x0a }, + { 0, 0x0c, 0x23 }, + { 0, 0x0e, 0x34 }, + { 0, 0x0c, 0x54 }, + { 0, 0x2d, 0x51 }, + { 0, 0x4c, 0x54 }, + { 0, 0x68, 0x52 }, + { 2, 0x0e, 0x02 }, + { 0, 0x0a, 0x0f }, + { 0, 0x0c, 0x1d }, + { 1, 0x02, 0x34 }, + { 1, 0x0c, 0x38 }, + { 1, 0x2c, 0x4a }, + { 1, 0x24, 0x4e }, + { 2, 0x30, 0x50 }, + { 2, 0x34, 0x56 }, + { 0, 0x48, 0x4a }, + { 1, 0x48, 0x4e }, + { 2, 0x51, 0x50 }, + { 0, 0x4c, 0x5c }, + { 0, 0x68, 0x4b }, + { 0, 0x68, 0x56 }, + { 2, 0x6c, 0x53 }, + { 3, 0x60, 0x5a }, + { 0, 0x0e, 0x01 }, + { 0, 0x05, 0x34 }, + { 0, 0x0d, 0x50 }, + { 0, 0x36, 0x4a }, + { 0, 0x45, 0x49 }, + { 0, 0x4c, 0x4d }, + { 0, 0x49, 0x5f }, + { 3, 0x60, 0x5a } +}; + +static void Task_ShowAreaMarkers(u8 taskId) +{ + struct PAM_TaskData * data = (void *)gTasks[taskId].data; + gSprites[data->spr_id].invisible = FALSE; +} + +u8 sub_8134230(u16 species, u16 tilesTag, u8 palIdx, u8 y) +{ + struct SpriteTemplate spriteTemplate; + struct CompressedSpriteSheet spriteSheet; + u8 taskId; + struct PAM_TaskData * data; + struct Subsprite * subsprites; + + spriteSheet.data = sMarkerTiles; + spriteSheet.size = 0x4A0; + spriteSheet.tag = tilesTag; + LoadCompressedSpriteSheet(&spriteSheet); + LoadPalette(sMarkerPal, 0x100 + 16 * palIdx, 0x20); + taskId = CreateTask(Task_ShowAreaMarkers, 0); + data = (void *)gTasks[taskId].data; + data->unk_0C = 0; + data->tilesTag = tilesTag; + data->unk_10 = 0xFFFF; + subsprites = Alloc(120 * sizeof(struct Subsprite)); + data->buffer = subsprites; + data->subsprites.subsprites = subsprites; + data->subsprites.subspriteCount = BuildPokedexAreaSubspriteBuffer(species, subsprites); + SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJWIN_ON); + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG0 | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_BG2 | BLDCNT_TGT2_BG3 | BLDCNT_TGT2_BD); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(12, 8)); + SetGpuReg(REG_OFFSET_BLDY, 0); + SetGpuReg(REG_OFFSET_WININ, 0x1F1F); + SetGpuReg(REG_OFFSET_WINOUT, 0x2F3D); + spriteTemplate = gDummySpriteTemplate; + spriteTemplate.tileTag = tilesTag; + data->spr_id = CreateSprite(&spriteTemplate, 104, y + 32, 0); + SetSubspriteTables(&gSprites[data->spr_id], &data->subsprites); + gSprites[data->spr_id].oam.objMode = ST_OAM_OBJ_WINDOW; + gSprites[data->spr_id].oam.paletteNum = palIdx; + gSprites[data->spr_id].subspriteTableNum = 0; + gSprites[data->spr_id].invisible = TRUE; + HideBg(1); + SetBgAttribute(1, BG_ATTR_CHARBASEINDEX, 0); + FillBgTilemapBufferRect_Palette0(1, 0x00F, 0, 0, 30, 20); + CopyBgTilemapBufferToVram(1); + ShowBg(1); + return taskId; +} + +void sub_81343F4(u8 taskId) +{ + struct PAM_TaskData * data = (void *)gTasks[taskId].data; + FreeSpriteTilesByTag(data->tilesTag); + DestroySprite(&gSprites[data->spr_id]); + Free(data->buffer); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); + SetGpuReg(REG_OFFSET_WININ, 0x1F1F); + SetGpuReg(REG_OFFSET_WINOUT, 0x1F1F); + ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJWIN_ON); + HideBg(1); + SetBgAttribute(1, BG_ATTR_CHARBASEINDEX, 2); + FillBgTilemapBufferRect_Palette0(1, 0x000, 0, 0, 30, 20); + CopyBgTilemapBufferToVram(1); + ShowBg(1); + DestroyTask(taskId); +} + +void SetAreaSubsprite(s32 i, s32 whichArea, struct Subsprite * subsprites) +{ + subsprites[i] = *sSubsprites[sSubspriteLookupTable[whichArea][0]]; + subsprites[i].x = sSubspriteLookupTable[whichArea][1]; + subsprites[i].y = sSubspriteLookupTable[whichArea][2]; +} + +u8 sub_81344E0(u8 taskId) +{ + struct PAM_TaskData * data = (void *)gTasks[taskId].data; + return data->subsprites.subspriteCount; +} diff --git a/src/wild_pokemon_area.c b/src/wild_pokemon_area.c new file mode 100644 index 000000000..5ea9d1610 --- /dev/null +++ b/src/wild_pokemon_area.c @@ -0,0 +1,308 @@ +#include "global.h" +#include "field_specials.h" +#include "event_data.h" +#include "wild_encounter.h" +#include "roamer.h" +#include "overworld.h" +#include "pokedex_area_markers.h" +#include "constants/vars.h" +#include "constants/region_map.h" +#include "constants/species.h" + +struct SeviiDexArea +{ + const u16 (*lut)[2]; + s32 count; +}; + +struct RoamerPair +{ + u16 roamer; + u16 starter; +}; + +static s32 GetRoamerIndex(u16 species); +static s32 CountRoamerNests(u16 species, struct Subsprite * subsprites); +static bool32 PokemonInAnyEncounterTableInMap(const struct WildPokemonHeader * data, s32 species); +static bool32 PokemonInEncounterTable(const struct WildPokemonInfo * pokemon, s32 species, s32 count); +static u16 GetMapSecIdFromWildMonHeader(const struct WildPokemonHeader * header); +static bool32 TryGetMapSecPokedexAreaEntry(u16 mapSecId, const u16 (*lut)[2], s32 count, s32 * lutIdx_p, u16 * tableIdx_p); + +static const u16 sDexAreas_Kanto[][2] = { + { MAPSEC_PALLET_TOWN, 1 }, + { MAPSEC_VIRIDIAN_CITY, 2 }, + { MAPSEC_PEWTER_CITY, 3 }, + { MAPSEC_CERULEAN_CITY, 4 }, + { MAPSEC_LAVENDER_TOWN, 5 }, + { MAPSEC_VERMILION_CITY, 6 }, + { MAPSEC_CELADON_CITY, 7 }, + { MAPSEC_FUCHSIA_CITY, 8 }, + { MAPSEC_CINNABAR_ISLAND, 9 }, + { MAPSEC_INDIGO_PLATEAU, 10 }, + { MAPSEC_SAFFRON_CITY, 11 }, + { MAPSEC_ROUTE_4_FLYDUP, 15 }, + { MAPSEC_ROUTE_10_FLYDUP, 21 }, + { MAPSEC_ROUTE_1, 12 }, + { MAPSEC_ROUTE_2, 13 }, + { MAPSEC_ROUTE_3, 14 }, + { MAPSEC_ROUTE_4, 15 }, + { MAPSEC_ROUTE_5, 16 }, + { MAPSEC_ROUTE_6, 17 }, + { MAPSEC_ROUTE_7, 18 }, + { MAPSEC_ROUTE_8, 19 }, + { MAPSEC_ROUTE_9, 20 }, + { MAPSEC_ROUTE_10, 21 }, + { MAPSEC_ROUTE_11, 22 }, + { MAPSEC_ROUTE_12, 23 }, + { MAPSEC_ROUTE_13, 24 }, + { MAPSEC_ROUTE_14, 25 }, + { MAPSEC_ROUTE_15, 26 }, + { MAPSEC_ROUTE_16, 27 }, + { MAPSEC_ROUTE_17, 28 }, + { MAPSEC_ROUTE_18, 29 }, + { MAPSEC_ROUTE_19, 30 }, + { MAPSEC_ROUTE_20, 31 }, + { MAPSEC_ROUTE_21, 32 }, + { MAPSEC_ROUTE_22, 33 }, + { MAPSEC_ROUTE_23, 34 }, + { MAPSEC_ROUTE_24, 35 }, + { MAPSEC_ROUTE_25, 36 }, + { MAPSEC_VIRIDIAN_FOREST, 37 }, + { MAPSEC_MT_MOON, 39 }, + { MAPSEC_S_S_ANNE, 6 }, + { MAPSEC_UNDERGROUND_PATH, 11 }, + { MAPSEC_UNDERGROUND_PATH_2, 11 }, + { MAPSEC_DIGLETTS_CAVE, 38 }, + { MAPSEC_KANTO_VICTORY_ROAD, 47 }, + { MAPSEC_ROCKET_HIDEOUT, 7 }, + { MAPSEC_SILPH_CO, 11 }, + { MAPSEC_POKEMON_MANSION, 46 }, + { MAPSEC_KANTO_SAFARI_ZONE, 44 }, + { MAPSEC_POKEMON_LEAGUE, 47 }, + { MAPSEC_ROCK_TUNNEL, 41 }, + { MAPSEC_SEAFOAM_ISLANDS, 45 }, + { MAPSEC_POKEMON_TOWER, 43 }, + { MAPSEC_CERULEAN_CAVE, 40 }, + { MAPSEC_POWER_PLANT, 42 } +}; + +static const u16 sDexAreas_Sevii1[][2] = { + { MAPSEC_KINDLE_ROAD, 55 }, + { MAPSEC_TREASURE_BEACH, 56 }, + { MAPSEC_ONE_ISLAND, 48 }, + { MAPSEC_MT_EMBER, 72 } +}; + +static const u16 sDexAreas_Sevii2[][2] = { + { MAPSEC_CAPE_BRINK, 57 }, + { MAPSEC_TWO_ISLAND, 49 } +}; + +static const u16 sDexAreas_Sevii3[][2] = { + { MAPSEC_BOND_BRIDGE, 58 }, + { MAPSEC_THREE_ISLE_PORT, 59 }, + { MAPSEC_THREE_ISLAND, 50 }, + { MAPSEC_BERRY_FOREST, 73 }, + { MAPSEC_THREE_ISLE_PATH, 59 } +}; + +static const u16 sDexAreas_Sevii4[][2] = { + { MAPSEC_FOUR_ISLAND, 51 }, + { MAPSEC_ICEFALL_CAVE, 74 } +}; + +static const u16 sDexAreas_Sevii5[][2] = { + { MAPSEC_RESORT_GORGEOUS, 60 }, + { MAPSEC_WATER_LABYRINTH, 61 }, + { MAPSEC_FIVE_ISLE_MEADOW, 62 }, + { MAPSEC_MEMORIAL_PILLAR, 63 }, + { MAPSEC_FIVE_ISLAND, 52 }, + { MAPSEC_ROCKET_WAREHOUSE, 62 }, + { MAPSEC_LOST_CAVE, 75 } +}; + +static const u16 sDexAreas_Sevii6[][2] = { + { MAPSEC_OUTCAST_ISLAND, 64 }, + { MAPSEC_GREEN_PATH, 65 }, + { MAPSEC_WATER_PATH, 66 }, + { MAPSEC_RUIN_VALLEY, 67 }, + { MAPSEC_DOTTED_HOLE, 78 }, + { MAPSEC_PATTERN_BUSH, 77 }, + { MAPSEC_ALTERING_CAVE, 76 } +}; + +static const u16 sDexAreas_Sevii7[][2] = { + { MAPSEC_TRAINER_TOWER, 68 }, + { MAPSEC_CANYON_ENTRANCE, 69 }, + { MAPSEC_SEVAULT_CANYON, 70 }, + { MAPSEC_TANOBY_RUINS, 71 }, + { MAPSEC_MONEAN_CHAMBER, 79 }, + { MAPSEC_LIPTOO_CHAMBER, 79 }, + { MAPSEC_WEEPTH_CHAMBER, 79 }, + { MAPSEC_DILFORD_CHAMBER, 79 }, + { MAPSEC_SCUFIB_CHAMBER, 79 }, + { MAPSEC_RIXY_CHAMBER, 79 }, + { MAPSEC_VIAPOIS_CHAMBER, 79 } +}; + +static const struct SeviiDexArea sSeviiDexAreas[] = { + { sDexAreas_Sevii1, 4 }, + { sDexAreas_Sevii2, 2 }, + { sDexAreas_Sevii3, 5 }, + { sDexAreas_Sevii4, 2 }, + { sDexAreas_Sevii5, 7 }, + { sDexAreas_Sevii6, 7 }, + { sDexAreas_Sevii7, 11 } +}; + +static const struct RoamerPair sRoamerPairs[] = { + { SPECIES_ENTEI, SPECIES_BULBASAUR }, + { SPECIES_SUICUNE, SPECIES_CHARMANDER }, + { SPECIES_RAIKOU, SPECIES_SQUIRTLE } +}; + +s32 BuildPokedexAreaSubspriteBuffer(u16 species, struct Subsprite * subsprites) +{ + s32 areaCount; + s32 j; + s32 mapSecId; + u16 dexAreaSubspriteIdx; + s32 dexAreaEntryLUTidx; + s32 seviiAreas; + s32 alteringCaveCount; + s32 alteringCaveNum; + s32 i; + + if (GetRoamerIndex(species) >= SPECIES_NONE) + { + return CountRoamerNests(species, subsprites); + } + + seviiAreas = GetUnlockedSeviiAreas(); + alteringCaveCount = 0; + alteringCaveNum = VarGet(VAR_0x4024); + if (alteringCaveNum > 8) + alteringCaveNum = 0; + for (i = 0, areaCount = 0; gWildMonHeaders[i].mapGroup != 0xFF; i++) + { + mapSecId = GetMapSecIdFromWildMonHeader(&gWildMonHeaders[i]); + if (mapSecId == MAPSEC_ALTERING_CAVE) + { + alteringCaveCount++; + if (alteringCaveNum != alteringCaveCount - 1) + continue; + } + if (PokemonInAnyEncounterTableInMap(&gWildMonHeaders[i], species)) + { + dexAreaEntryLUTidx = 0; + while (TryGetMapSecPokedexAreaEntry(mapSecId, sDexAreas_Kanto, 55, &dexAreaEntryLUTidx, &dexAreaSubspriteIdx)) + { + if (dexAreaSubspriteIdx != 0) + { + SetAreaSubsprite(areaCount++, dexAreaSubspriteIdx, subsprites); + } + } + for (j = 0; j < NELEMS(sSeviiDexAreas); j++) + { + if ((seviiAreas >> j) & 1) + { + dexAreaEntryLUTidx = 0; + while (TryGetMapSecPokedexAreaEntry(mapSecId, sSeviiDexAreas[j].lut, sSeviiDexAreas[j].count, &dexAreaEntryLUTidx, &dexAreaSubspriteIdx)) + { + if (dexAreaSubspriteIdx != 0) + { + SetAreaSubsprite(areaCount++, dexAreaSubspriteIdx, subsprites); + } + } + } + } + } + } + + return areaCount; +} + +static s32 GetRoamerIndex(u16 species) +{ + s32 i; + for (i = 0; i < NELEMS(sRoamerPairs); i++) + { + if (sRoamerPairs[i].roamer == species) + return i; + } + + return -1; +} + +static s32 CountRoamerNests(u16 species, struct Subsprite * subsprites) +{ + u16 roamerLocation; + s32 roamerIdx; + u16 dexAreaSubspriteIdx; + s32 dexAreaEntryLUTidx; + + roamerIdx = GetRoamerIndex(species); + if (roamerIdx < 0) + return 0; + if (sRoamerPairs[roamerIdx].starter != ScrSpecial_GetStarter()) + return 0; + roamerLocation = GetRoamerLocationMapSectionId(); + dexAreaEntryLUTidx = 0; + if (TryGetMapSecPokedexAreaEntry(roamerLocation, sDexAreas_Kanto, 55, &dexAreaEntryLUTidx, &dexAreaSubspriteIdx)) + { + if (dexAreaSubspriteIdx != 0) + { + SetAreaSubsprite(0, dexAreaSubspriteIdx, subsprites); + return 1; + } + } + return 0; +} + +static bool32 PokemonInAnyEncounterTableInMap(const struct WildPokemonHeader * data, s32 species) +{ + if (PokemonInEncounterTable(data->landMonsInfo, species, 12)) + return TRUE; + if (PokemonInEncounterTable(data->waterMonsInfo, species, 5)) + return TRUE; + if (PokemonInEncounterTable(data->fishingMonsInfo, species, 12)) + return TRUE; + if (PokemonInEncounterTable(data->rockSmashMonsInfo, species, 5)) + return TRUE; + + return FALSE; +} + +static bool32 PokemonInEncounterTable(const struct WildPokemonInfo * info, s32 species, s32 count) +{ + s32 i; + if (info != NULL) + { + for (i = 0; i < count; i++) + { + if (info->wildPokemon[i].species == species) + return TRUE; + } + } + return FALSE; +} + +static u16 GetMapSecIdFromWildMonHeader(const struct WildPokemonHeader * header) +{ + return get_mapheader_by_bank_and_number(header->mapGroup, header->mapNum)->regionMapSectionId; +} + +static bool32 TryGetMapSecPokedexAreaEntry(u16 mapSecId, const u16 (*lut)[2], s32 count, s32 * lutIdx_p, u16 * tableIdx_p) +{ + s32 i; + for (i = *lutIdx_p; i < count; i++) + { + if (lut[i][0] == mapSecId) + { + *tableIdx_p = lut[i][1]; + *lutIdx_p = i + 1; + return TRUE; + } + } + return FALSE; +} |