The Old, Good and Super Rods run FishFunction facing water: the map's fish group and Fish pick no fish, no bite, or a Pokémon from FishGroups and the time of day's TimeFishGroups. The player casts and jiggles with the fishing frames drawn from LoadFishingGFX's tiles, shows "!" on a bite, and the hooked Pokémon attacks as BATTLETYPE_FISH. Facing pieces now use signed offsets, which the rod above and left of the player needs. Wild Magikarp no longer stop a battle: LoadEnemyMon redraws their DVs through CalcMagikarpLength and its filters, as the original does. The length routine matches the original in the reference emulator. Part of #27 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
46 lines
1.6 KiB
TypeScript
46 lines
1.6 KiB
TypeScript
import type { RomReader } from "../rom/reader";
|
|
import { OVERWORLD } from "../rom/profile";
|
|
|
|
/** The fishing rods' encounters (engine/events/fish.asm and
|
|
* data/wild/fish.asm). */
|
|
export interface FishMon {
|
|
species: number;
|
|
level: number;
|
|
}
|
|
|
|
/** FISHGROUP_DATA_LENGTH: the bite chance, then a table per rod. */
|
|
const FISHGROUP_DATA_LENGTH = 7;
|
|
/** NITE_F: TimeFishGroups' second species from the night on. */
|
|
const NITE_F = 2;
|
|
|
|
/** Fish: rod 0 (Old), 1 (Good) or 2 (Super) in FishGroups entry `group`
|
|
* (FISHGROUP_*, never FISHGROUP_NONE). A bite when Random falls below the
|
|
* group's chance, then the first entry whose chance a second Random does
|
|
* not exceed; species 0 picks the time of day's TimeFishGroups entry.
|
|
* Undefined when nothing bites. GetFishGroupIndex's swarm groups need
|
|
* DAILYFLAGS1_FISH_SWARM_F and wFishingSwarmFlag, which only trainer calls
|
|
* set; they are not ported, so the map's own group is used. */
|
|
export function fish(
|
|
r: RomReader,
|
|
group: number,
|
|
rod: number,
|
|
timeOfDay: number,
|
|
random: () => number,
|
|
): FishMon | undefined {
|
|
const entry = OVERWORLD.FishGroups + (group - 1) * FISHGROUP_DATA_LENGTH;
|
|
if (random() >= r.byte(entry)) return undefined;
|
|
let p = r.near(entry + 1 + rod * 2, r.bank(entry));
|
|
const roll = random();
|
|
while (roll > r.byte(p)) p += 3;
|
|
let species = r.byte(p + 1),
|
|
level = r.byte(p + 2);
|
|
if (!species) {
|
|
// .TimeEncounter: the level byte indexes TimeFishGroups.
|
|
const time =
|
|
OVERWORLD.TimeFishGroups + level * 4 + (timeOfDay >= NITE_F ? 2 : 0);
|
|
species = r.byte(time);
|
|
level = r.byte(time + 1);
|
|
}
|
|
return { species, level };
|
|
}
|