diff options
Diffstat (limited to 'engine/wildmons.asm')
-rwxr-xr-x | engine/wildmons.asm | 1057 |
1 files changed, 1057 insertions, 0 deletions
diff --git a/engine/wildmons.asm b/engine/wildmons.asm new file mode 100755 index 000000000..6f39e19dc --- /dev/null +++ b/engine/wildmons.asm @@ -0,0 +1,1057 @@ +LoadWildMonData: ; 29ff8 + call _GrassWildmonLookup + jr c, .copy + ld hl, wd25a + xor a + ld [hli], a + ld [hli], a + ld [hl], a + jr .done_copy +.copy + inc hl + inc hl + ld de, wd25a + ld bc, $3 + call CopyBytes +.done_copy + call _WaterWildmonLookup + ld a, $0 + jr nc, .no_copy + inc hl + inc hl + ld a, [hl] +.no_copy + ld [wd25d], a + ret + +Function2a01f: ; 2a01f + hlcoord 0, 0 + ld bc, SCREEN_WIDTH * SCREEN_HEIGHT + xor a + call ByteFill + ld a, e + and a + jr nz, .kanto + decoord 0, 0 + ld hl, JohtoGrassWildMons + call Function2a052 + ld hl, JohtoWaterWildMons + call Function2a06e + call Function2a0b7 + call Function2a0cf + ret + +.kanto + decoord 0, 0 + ld hl, KantoGrassWildMons + call Function2a052 + ld hl, KantoWaterWildMons + jp Function2a06e +; 2a052 + +Function2a052: ; 2a052 +.loop + ld a, [hl] + cp $ff + ret z + push hl + ld a, [hli] + ld b, a + ld a, [hli] + ld c, a +rept 3 + inc hl +endr + ld a, $15 + call Function2a088 + jr nc, .next + ld [de], a + inc de + +.next + pop hl + ld bc, $2f + add hl, bc + jr .loop +; 2a06e + +Function2a06e: ; 2a06e +.loop + ld a, [hl] + cp $ff + ret z + push hl + ld a, [hli] + ld b, a + ld a, [hli] + ld c, a + inc hl + ld a, $3 + call Function2a088 + jr nc, .next + ld [de], a + inc de + +.next + pop hl + ld bc, 9 + add hl, bc + jr .loop +; 2a088 + +Function2a088: ; 2a088 + inc hl +.loop + push af + ld a, [wd265] + cp [hl] + jr z, .found +rept 2 + inc hl +endr + pop af + dec a + jr nz, .loop + and a + ret + +.found + pop af + jp Function2a09c +; 2a09c + +Function2a09c: ; 2a09c + push de + call GetWorldMapLocation + ld c, a + hlcoord 0, 0 + ld de, SCREEN_WIDTH * SCREEN_HEIGHT +.loop + ld a, [hli] + cp c + jr z, .found + dec de + ld a, e + or d + jr nz, .loop + ld a, c + pop de + scf + ret + +.found + pop de + and a + ret +; 2a0b7 + +Function2a0b7: ; 2a0b7 + ld a, [wRoamMon1Species] + ld b, a + ld a, [wd265] + cp b + ret nz + ld a, [wRoamMon1MapGroup] + ld b, a + ld a, [wRoamMon1MapNumber] + ld c, a + call Function2a09c + ret nc + ld [de], a + inc de + ret +; 2a0cf + +Function2a0cf: ; 2a0cf + ld a, [wRoamMon2Species] + ld b, a + ld a, [wd265] + cp b + ret nz + ld a, [wRoamMon2MapGroup] + ld b, a + ld a, [wRoamMon2MapNumber] + ld c, a + call Function2a09c + ret nc + ld [de], a + inc de + ret +; 2a0e7 + +TryWildEncounter:: ; 2a0e7 +; Try to trigger a wild encounter. + call .EncounterRate + jr nc, .no_battle + call ChooseWildEncounter + jr nz, .no_battle + call CheckRepelEffect + jr nc, .no_battle + xor a + ret + +.no_battle + xor a ; BATTLETYPE_NORMAL + ld [TempWildMonSpecies], a + ld [BattleType], a + ld a, 1 + and a + ret +; 2a103 + +.EncounterRate: ; 2a103 + call GetMapEncounterRate + call ApplyMusicEffectOnEncounterRate + call ApplyCleanseTagEffectOnEncounterRate + call Random + cp b + ret +; 2a111 + +GetMapEncounterRate: ; 2a111 + ld hl, wd25a + call CheckOnWater + ld a, 3 + jr z, .ok + ld a, [TimeOfDay] +.ok + ld c, a + ld b, 0 + add hl, bc + ld b, [hl] + ret +; 2a124 + +ApplyMusicEffectOnEncounterRate:: ; 2a124 +; Pokemon March and Ruins of Alph signal double encounter rate. +; Pokemon Lullaby halves encounter rate. + ld a, [wMapMusic] + cp MUSIC_POKEMON_MARCH + jr z, .double + cp MUSIC_RUINS_OF_ALPH_RADIO + jr z, .double + cp MUSIC_POKEMON_LULLABY + ret nz + srl b + ret + +.double + sla b + ret +; 2a138 + +ApplyCleanseTagEffectOnEncounterRate:: ; 2a138 +; Cleanse Tag halves encounter rate. + ld hl, PartyMon1Item + ld de, PARTYMON_STRUCT_LENGTH + ld a, [PartyCount] + ld c, a +.loop + ld a, [hl] + cp CLEANSE_TAG + jr z, .cleansetag + add hl, de + dec c + jr nz, .loop + ret + +.cleansetag + srl b + ret +; 2a14f + +ChooseWildEncounter: ; 2a14f + call LoadWildMonDataPointer + jp nc, .nowildbattle + call CheckEncounterRoamMon + jp c, .startwildbattle + +rept 3 + inc hl +endr + call CheckOnWater + ld de, .WaterMonTable + jr z, .watermon +rept 2 + inc hl +endr + ld a, [TimeOfDay] + ld bc, $e + call AddNTimes + ld de, .GrassMonTable + +.watermon +; hl contains the pointer to the wild mon data, let's save that to the stack + push hl +.randomloop + call Random + cp 100 + jr nc, .randomloop + inc a ; 1 <= a <= 100 + ld b, a + ld h, d + ld l, e +; This next loop chooses which mon to load up. +.prob_bracket_loop + ld a, [hli] + cp b + jr nc, .got_it + inc hl + jr .prob_bracket_loop + +.got_it + ld c, [hl] + ld b, 0 + pop hl + add hl, bc ; this selects our mon + ld a, [hli] + ld b, a +; If the Pokemon is encountered by surfing, we need to give the levels some variety. + call CheckOnWater + jr nz, .ok +; Check if we buff the wild mon, and by how much. + call Random + cp 35 percent + jr c, .ok + inc b + cp 65 percent + jr c, .ok + inc b + cp 85 percent + jr c, .ok + inc b + cp 95 percent + jr c, .ok + inc b +; Store the level +.ok + ld a, b + ld [CurPartyLevel], a + ld b, [hl] + ; ld a, b + call ValidateTempWildMonSpecies + jr c, .nowildbattle + + ld a, b ; This is in the wrong place. + cp UNOWN + jr nz, .done + + ld a, [UnlockedUnowns] + and a + jr z, .nowildbattle + +.done + jr .loadwildmon + +.nowildbattle + ld a, 1 + and a + ret + +.loadwildmon + ld a, b + ld [TempWildMonSpecies], a + +.startwildbattle + xor a + ret +; 2a1cb + +.GrassMonTable: ; 2a1cb + db 30, $0 ; 30% chance + db 60, $2 ; 30% chance + db 80, $4 ; 20% chance + db 90, $6 ; 10% chance + db 95, $8 ; 5% chance + db 99, $a ; 4% chance + db 100, $c ; 1% chance +; 2a1d9 + +.WaterMonTable: ; 2a1d9 + db 60, $0 ; 60% chance + db 90, $2 ; 30% chance + db 100, $4 ; 10% chance +; 2a1df + +CheckRepelEffect:: ; 2a1df +; If there is no active Repel, there's no need to be here. + ld a, [wRepelEffect] + and a + jr z, .encounter +; Get the first Pokemon in your party that isn't fainted. + ld hl, PartyMon1HP + ld bc, PARTYMON_STRUCT_LENGTH - 1 +.loop + ld a, [hli] + or [hl] + jr nz, .ok + add hl, bc + jr .loop + +.ok +; to PartyMonLevel +rept 4 + dec hl +endr + + ld a, [CurPartyLevel] + cp [hl] + jr nc, .encounter + and a + ret + +.encounter + scf + ret +; 2a200 + +LoadWildMonDataPointer: ; 2a200 + call CheckOnWater + jr z, _WaterWildmonLookup + +_GrassWildmonLookup: ; 2a205 + ld hl, SwarmGrassWildMons + ld bc, GRASS_WILDDATA_LENGTH + call _SwarmWildmonCheck + ret c + ld hl, JohtoGrassWildMons + ld de, KantoGrassWildMons + call _JohtoWildmonCheck + ld bc, GRASS_WILDDATA_LENGTH + jr _NormalWildmonOK + +_WaterWildmonLookup: ; 2a21d + ld hl, SwarmWaterWildMons + ld bc, WATER_WILDDATA_LENGTH + call _SwarmWildmonCheck + ret c + ld hl, JohtoWaterWildMons + ld de, KantoWaterWildMons + call _JohtoWildmonCheck + ld bc, WATER_WILDDATA_LENGTH + jr _NormalWildmonOK + +_JohtoWildmonCheck + call IsInJohto + and a + ret z + ld h, d + ld l, e + ret + +_SwarmWildmonCheck + call CopyCurrMapDE + push hl + ld hl, SwarmFlags + bit 2, [hl] + pop hl + jr z, .CheckYanma + ld a, [wdfcc] + cp d + jr nz, .CheckYanma + ld a, [wdfcd] + cp e + jr nz, .CheckYanma + call LookUpWildmonsForMapDE + jr nc, _NoSwarmWildmon + scf + ret + +.CheckYanma + push hl + ld hl, SwarmFlags + bit 3, [hl] + pop hl + jr z, _NoSwarmWildmon + ld a, [wdc5a] + cp d + jr nz, _NoSwarmWildmon + ld a, [wdc5b] + cp e + jr nz, _NoSwarmWildmon + call LookUpWildmonsForMapDE + jr nc, _NoSwarmWildmon + scf + ret + +_NoSwarmWildmon + and a + ret + +_NormalWildmonOK + call CopyCurrMapDE + jr LookUpWildmonsForMapDE +; 2a27f + +CopyCurrMapDE: ; 2a27f + ld a, [MapGroup] + ld d, a + ld a, [MapNumber] + ld e, a + ret +; 2a288 + +LookUpWildmonsForMapDE: ; 2a288 + push hl + ld a, [hl] + inc a + jr z, .nope + ld a, d + cp [hl] + jr nz, .next + inc hl + ld a, e + cp [hl] + jr z, .yup + +.next + pop hl + add hl, bc + jr LookUpWildmonsForMapDE + +.nope + pop hl + and a + ret + +.yup + pop hl + scf + ret +; 2a2a0 + + +InitRoamMons: ; 2a2a0 +; initialize wRoamMon structs + +; species + ld a, RAIKOU + ld [wRoamMon1Species], a + ld a, ENTEI + ld [wRoamMon2Species], a +; ld a, SUICUNE +; ld [wRoamMon3Species], a + +; level + ld a, 40 + ld [wRoamMon1Level], a + ld [wRoamMon2Level], a +; ld [wRoamMon3Level], a + +; raikou starting map + ld a, GROUP_ROUTE_42 + ld [wRoamMon1MapGroup], a + ld a, MAP_ROUTE_42 + ld [wRoamMon1MapNumber], a + +; entei starting map + ld a, GROUP_ROUTE_37 + ld [wRoamMon2MapGroup], a + ld a, MAP_ROUTE_37 + ld [wRoamMon2MapNumber], a + +; suicune starting map +; ld a, GROUP_ROUTE_38 +; ld [wRoamMon3MapGroup], a +; ld a, MAP_ROUTE_38 +; ld [wRoamMon3MapNumber], a + +; hp + xor a ; generate new stats + ld [wRoamMon1HP], a + ld [wRoamMon2HP], a +; ld [wRoamMon3HP], a + + ret +; 2a2ce + + +CheckEncounterRoamMon: ; 2a2ce + push hl +; Don't trigger an encounter if we're on water. + call CheckOnWater + jr z, .DontEncounterRoamMon +; Load the current map group and number to de + call CopyCurrMapDE +; Randomly select a beast. + call Random + cp 100 ; 25/64 chance + jr nc, .DontEncounterRoamMon + and %00000011 ; Of that, a 3/4 chance. Running total: 75/256, or around 29.3%. + jr z, .DontEncounterRoamMon + dec a ; 1/3 chance that it's Entei, 1/3 chance that it's Raikou +; Compare its current location with yours + ld hl, wRoamMon1MapGroup + ld c, a + ld b, 0 + ld a, 7 ; length of the RoamMon struct + call AddNTimes + ld a, d + cp [hl] + jr nz, .DontEncounterRoamMon + inc hl + ld a, e + cp [hl] + jr nz, .DontEncounterRoamMon +; We've decided to take on a beast, so stage its information for battle. +rept 3 + dec hl +endr + ld a, [hli] + ld [TempWildMonSpecies], a + ld a, [hl] + ld [CurPartyLevel], a + ld a, BATTLETYPE_ROAMING + ld [BattleType], a + + pop hl + scf + ret + +.DontEncounterRoamMon + pop hl + and a + ret +; 2a30d + + +UpdateRoamMons: ; 2a30d + ld a, [wRoamMon1MapGroup] + cp GROUP_N_A + jr z, .SkipRaikou + ld b, a + ld a, [wRoamMon1MapNumber] + ld c, a + call .Update + ld a, b + ld [wRoamMon1MapGroup], a + ld a, c + ld [wRoamMon1MapNumber], a + +.SkipRaikou + ld a, [wRoamMon2MapGroup] + cp GROUP_N_A + jr z, .SkipEntei + ld b, a + ld a, [wRoamMon2MapNumber] + ld c, a + call .Update + ld a, b + ld [wRoamMon2MapGroup], a + ld a, c + ld [wRoamMon2MapNumber], a + +.SkipEntei + ld a, [wRoamMon3MapGroup] + cp GROUP_N_A + jr z, .SkipSuicune + ld b, a + ld a, [wRoamMon3MapNumber] + ld c, a + call .Update + ld a, b + ld [wRoamMon3MapGroup], a + ld a, c + ld [wRoamMon3MapNumber], a + +.SkipSuicune + jp _BackUpMapIndices +; 2a355 + + +.Update: ; 2a355 + ld hl, RoamMaps +.loop +; Are we at the end of the table? + ld a, [hl] + cp -1 + ret z +; Is this the correct entry? + ld a, b + cp [hl] + jr nz, .next + inc hl + ld a, c + cp [hl] + jr z, .yes +; We don't have the correct entry yet, so let's continue. A 0 terminates each entry. +.next + ld a, [hli] + and a + jr nz, .next + jr .loop + +; We have the correct entry now, so let's choose a random map from it. +.yes + inc hl + ld d, h + ld e, l +.update_loop + ld h, d + ld l, e +; Choose which map to warp to. + call Random + and $1f ; 1/8n chance it moves to a completely random map, where n is the number of roaming connections from the current map. + jr z, JumpRoamMon + and 3 + cp [hl] + jr nc, .update_loop ; invalid index, try again + inc hl + ld c, a + ld b, $0 +rept 2 + add hl, bc +endr + ld a, [wdfe7] + cp [hl] + jr nz, .done + inc hl + ld a, [wdfe6] + cp [hl] + jr z, .update_loop + dec hl + +.done + ld a, [hli] + ld b, a + ld c, [hl] + ret + +JumpRoamMons: ; 2a394 + ld a, [wRoamMon1MapGroup] + cp GROUP_N_A + jr z, .SkipRaikou + call JumpRoamMon + ld a, b + ld [wRoamMon1MapGroup], a + ld a, c + ld [wRoamMon1MapNumber], a +.SkipRaikou + + ld a, [wRoamMon2MapGroup] + cp GROUP_N_A + jr z, .SkipEntei + call JumpRoamMon + ld a, b + ld [wRoamMon2MapGroup], a + ld a, c + ld [wRoamMon2MapNumber], a +.SkipEntei + + ld a, [wRoamMon3MapGroup] + cp GROUP_N_A + jr z, .SkipSuicune + call JumpRoamMon + ld a, b + ld [wRoamMon3MapGroup], a + ld a, c + ld [wRoamMon3MapNumber], a +.SkipSuicune + + jp _BackUpMapIndices + +JumpRoamMon: ; 2a3cd +.loop + ld hl, RoamMaps +.innerloop1 ; This loop is completely unnecessary. + call Random ; Choose a random number + and $f ; Take the lower nybble only. This gives a number between 0 and 15. + cp $10 ; If the number is greater than or equal to 16, loop back and try again. + jr nc, .innerloop1 ; I'm sure you can guess why this check is bogus. + inc a + ld b, a +.innerloop2 ; Loop to get hl to the address of the chosen roam map. + dec b + jr z, .ok +.innerloop3 ; Loop to skip the current roam map, which is terminated by a 0. + ld a, [hli] + and a + jr nz, .innerloop3 + jr .innerloop2 +; Check to see if the selected map is the one the player is currently in. If so, try again. +.ok + ld a, [MapGroup] + cp [hl] + jr nz, .done + inc hl + ld a, [MapNumber] + cp [hl] + jr z, .loop + dec hl +; Return the map group and number in bc. +.done + ld a, [hli] + ld b, a + ld c, [hl] + ret +; 2a3f6 + +_BackUpMapIndices: ; 2a3f6 + ld a, [wdfe4] + ld [wdfe6], a + ld a, [wdfe5] + ld [wdfe7], a + ld a, [MapNumber] + ld [wdfe4], a + ld a, [MapGroup] + ld [wdfe5], a + ret +; 2a40f + +RoamMaps: ; 2a40f +; Maps that roaming monsters can be on, +; and possible maps they can jump to. +; Notably missing are Route 40 and +; Route 41, which are water routes. + roam_map ROUTE_29, 2, ROUTE_30, ROUTE_46 + roam_map ROUTE_30, 2, ROUTE_29, ROUTE_31 + roam_map ROUTE_31, 3, ROUTE_30, ROUTE_32, ROUTE_36 + roam_map ROUTE_32, 3, ROUTE_36, ROUTE_31, ROUTE_33 + roam_map ROUTE_33, 2, ROUTE_32, ROUTE_34 + roam_map ROUTE_34, 2, ROUTE_33, ROUTE_35 + roam_map ROUTE_35, 2, ROUTE_34, ROUTE_36 + roam_map ROUTE_36, 4, ROUTE_35, ROUTE_31, ROUTE_32, ROUTE_37 + roam_map ROUTE_37, 3, ROUTE_36, ROUTE_38, ROUTE_42 + roam_map ROUTE_38, 3, ROUTE_37, ROUTE_39, ROUTE_42 + roam_map ROUTE_39, 1, ROUTE_38 + roam_map ROUTE_42, 4, ROUTE_43, ROUTE_44, ROUTE_37, ROUTE_38 + roam_map ROUTE_43, 2, ROUTE_42, ROUTE_44 + roam_map ROUTE_44, 3, ROUTE_42, ROUTE_43, ROUTE_45 + roam_map ROUTE_45, 2, ROUTE_44, ROUTE_46 + roam_map ROUTE_46, 2, ROUTE_45, ROUTE_29 + db -1 +; 2a4a0 + +ValidateTempWildMonSpecies: ; 2a4a0 +; Due to a development oversight, this function is called with the wild Pokemon's level, not its species, in a. + and a + jr z, .nowildmon ; = 0 + cp NUM_POKEMON + 1 ; 252 + jr nc, .nowildmon ; >= 252 + and a ; 1 <= Species <= 251 + ret + +.nowildmon + scf + ret +; 2a4ab + +RandomPhoneRareWildMon: ; 2a4ab +; Related to the phone? + callba GetCallerLocation + ld d, b + ld e, c + ld hl, JohtoGrassWildMons + ld bc, GRASS_WILDDATA_LENGTH + call LookUpWildmonsForMapDE + jr c, .GetGrassmon + ld hl, KantoGrassWildMons + call LookUpWildmonsForMapDE + jr nc, .done + +.GetGrassmon + push hl + ld bc, 5 + 4 * 2 ; Location of the level of the 5th wild Pokemon in that map + add hl, bc + ld a, [TimeOfDay] + ld bc, 7 * 2 + call AddNTimes +.randloop1 + call Random + and $3 + jr z, .randloop1 + dec a + ld c, a + ld b, $0 +rept 2 + add hl, bc +endr +; We now have the pointer to one of the last (rarest) three wild Pokemon found in that area. + inc hl + ld c, [hl] ; Contains the species index of this rare Pokemon + pop hl + ld de, 5 + 0 * 2 + add hl, de + inc hl ; Species index of the most common Pokemon on that route + ld b, 4 +.loop2 + ld a, [hli] + cp c ; Compare this most common Pokemon with the rare one stored in c. + jr z, .done + inc hl + dec b + jr nz, .loop2 +; This Pokemon truly is rare. + push bc + dec c + ld a, c + call CheckSeenMon + pop bc + jr nz, .done +; Since we haven't seen it, have the caller tell us about it. + ld de, StringBuffer1 + call CopyName1 + ld a, c + ld [wd265], a + call GetPokemonName + ld hl, UnknownText_0x2a51a + call PrintText + xor a + ld [ScriptVar], a + ret + +.done + ld a, $1 + ld [ScriptVar], a + ret +; 2a51a + +UnknownText_0x2a51a: ; 0x2a51a + ; I just saw some rare @ in @ . I'll call you if I see another rare #MON, OK? + text_jump UnknownText_0x1bd34b + db "@" +; 0x2a51f + +RandomPhoneWildMon: ; 2a51f + callba GetCallerLocation + ld d, b + ld e, c + ld hl, JohtoGrassWildMons + ld bc, GRASS_WILDDATA_LENGTH + call LookUpWildmonsForMapDE + jr c, .ok + ld hl, KantoGrassWildMons + call LookUpWildmonsForMapDE + +.ok + ld bc, 5 + 0 * 2 + add hl, bc + ld a, [TimeOfDay] + inc a + ld bc, 7 * 2 +.loop + dec a + jr z, .done + add hl, bc + jr .loop + +.done + call Random + and $3 + ld c, a + ld b, $0 +rept 2 + add hl, bc +endr + inc hl + ld a, [hl] + ld [wd265], a + call GetPokemonName + ld hl, StringBuffer1 + ld de, StringBuffer4 + ld bc, PKMN_NAME_LENGTH + jp CopyBytes +; 2a567 + +RandomPhoneMon: ; 2a567 +; Get a random monster owned by the trainer who's calling. + callba GetCallerLocation + ld hl, TrainerGroups + ld a, d + dec a + ld c, a + ld b, 0 +rept 2 + add hl, bc +endr + ld a, BANK(TrainerGroups) + call GetFarHalfword + +.skip_trainer + dec e + jr z, .skipped +.skip + ld a, BANK(Trainers) + call GetFarByte + inc hl + cp -1 + jr nz, .skip + jr .skip_trainer +.skipped + +.skip_name + ld a, BANK(Trainers) + call GetFarByte + inc hl + cp "@" + jr nz, .skip_name + + ld a, BANK(Trainers) + call GetFarByte + inc hl + ld bc, 2 + cp 0 + jr z, .got_mon_length + ld bc, 2 + NUM_MOVES + cp 1 + jr z, .got_mon_length + ld bc, 2 + 1 + cp 2 + jr z, .got_mon_length + ld bc, 2 + 1 + NUM_MOVES +.got_mon_length + + ld e, 0 + push hl +.count_mon + inc e + add hl, bc + ld a, BANK(Trainers) + call GetFarByte + cp -1 + jr nz, .count_mon + pop hl + +.rand + call Random + and 7 + cp e + jr nc, .rand + + inc a +.get_mon + dec a + jr z, .got_mon + add hl, bc + jr .get_mon +.got_mon + + inc hl ; species + ld a, BANK(Trainers) + call GetFarByte + ld [wd265], a + call GetPokemonName + ld hl, StringBuffer1 + ld de, StringBuffer4 + ld bc, PKMN_NAME_LENGTH + jp CopyBytes +; 2a5e9 + + +JohtoGrassWildMons: ; 0x2a5e9 +INCLUDE "data/wild/johto_grass.asm" + +JohtoWaterWildMons: ; 0x2b11d +INCLUDE "data/wild/johto_water.asm" + +KantoGrassWildMons: ; 0x2b274 +INCLUDE "data/wild/kanto_grass.asm" + +KantoWaterWildMons: ; 0x2b7f7 +INCLUDE "data/wild/kanto_water.asm" + +SwarmGrassWildMons: ; 0x2b8d0 +INCLUDE "data/wild/swarm_grass.asm" + +SwarmWaterWildMons: ; 0x2b92f +INCLUDE "data/wild/swarm_water.asm" |