Port the fishing rods and wild Magikarp
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>
This commit is contained in:
1 parent
4cb4676c7d
commit
397dcef44c
20 files changed
+681
-47
No files matched your search
@@ -0,0 +1,45 @@
|
||||
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 };
|
||||
}
|
||||
Reference in new issue
Block a user