- Battle Animation Pipeline:
* Eliminate 90-frame audio polling stall in anim_vm end/waitsound opcodes,
allowing attack animations to transition instantly into target hit flicker
and HP bar drain.
* Correct visual task counting in AnimVm:visualCount to match pret gAnimVisualTaskCount.
* Signal bg task completion on restorebg (vm.args[7] = -1).
* Fix termination conditions on shake tasks (ShakeMon, ShakeMon2, ShakeBattleTerrain),
WaterSport droplet arcs, and StartSinAnimTimer.
* Handle RGB555 color args in start_blend_anim_sprite_color and route P.destroyTask
to AnimTasks.destroy.
- RNG System & Seeding Parity:
* Replace math.random in Party.giveMon with Rng.Random32() for personality values
and Rng.Random() for IV bitfield extraction (HP/Atk/Def/Spe/SpA/SpD) matching GBA format.
* Seed RNG on Title Screen A/Start press via Rng.seedNewGame() (matching SeedRngAndSetTrainerId)
and perturb RNG state on title menu inputs.
* Route NPC overworld idle/wander timers and wild encounter slot rolls through Rng.compat.
- Pokédex Habitat & Area Maps:
* Fix encounter tables extraction and map indexing to resolve Pokemon habitat
locations across Kanto/Sevii maps rather than showing Area Unknown.
* Render steady semi-transparent red overlays for Pokédex area map locations.
- Multichoice Menus & UI:
* Implement multichoice table extraction and data population for Viridian blackboard
status ailments and special dialog interactions.
* Improve choice box borders, pagination, and Town Map wall viewing.
- Overworld Events & Flags:
* Fix Route 1 entrance girl NPC spawning and script triggers after starter selection.
* Ensure consistent save reload state in Oak's Lab.
Add ROM-backed contextual L/R help with article navigation and safe pause/resume. Record recent field scenes and gameplay events for the skippable Continue recap, with playback isolated from live progress.
Integrate extraction and cache validation, preserve bundled script flags during import, and cover navigation, persistence, event recording, playback isolation, and both ROM revisions with tests.
A link battle runs under cable rules and LinkBattle keeps them: openItems
prints "Items can't be used in a link battle!" and the wire knows move,
struggle, locked, switch and RUN. Right for the Cable Club, wrong for a
mode that is not the Cable Club -- a battle royale played over
LinkState.newFromSession fights with real, damaged parties, and the
potions and X items on the ground are its whole economy; against a bot
the bag works, against a person it says no. The mode cannot fix it:
submit, resolveLockstep and the decoder are closures, and there is no
action that means "nothing" to spend the turn on.
opts.items = true on newHost/newGuest (off by default, set on both
machines like turnLimit): the bag is BattleState.openItems -- the vanilla
BagMenu against this battle, whose picker already offers the clamped
copies -- and the effect is ItemEffects.use as in any fight. What
changes is what spending the turn means: itemUsed puts { kind = "item",
item, index, move } on the wire as the turn's action instead of running
the AI's reply. Both machines and a spectator resolve it before switches
and moves: the user's side is already applied (the bag did it), the other
side applies the same effect to its own copies of that side through
src/link/LinkItems.lua -- ItemEffects.use behind a battle whose player is
the user's battler and a save whose party is the user's copies, nothing
consumed -- and prints "<name> used <ITEM>!" plus the effect's lines.
Every effect reachable in a battle is deterministic, so the per-turn
hash still agrees. BagMenu hands itemUsed the item, target and move it
used; a local battle ignores them. A ball on the cable is refused
(ItemEffects), the way the doll is in any trainer battle.
tests/engine/link_items.lua: cable rules by default; opted in, the host's
POTION heals the guest's copy before the moves, both print the lines,
one turn, hashes agree; a spectator fed the same two messages heals its
copy too. docs/modding.md and docs/rfcs/0021-link-battle-items.md.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Two contexts call LearnMove.begin with different pushMsg semantics:
- Battle (Ui.push): single-arg, ignores callback -> pump() must poll
Ui.dialogPending() to wait for the player to dismiss the message
- Party menu / rare candy (PartyMenu.showMessage): honours the callback,
calling it when the player presses A -> finish() must fire inline
Fix: set _pending='done' for the pump() path (battle) AND restore the
say() callback for the direct path (party menu). A guard on _pending
prevents double-finish. pump() now checks Ui.dialogPending() before
acting on 'done' so the 'X learned Y!' message stays visible until
the player dismisses it in both contexts.
LearnMove.begin's free-slot path called say(text, cb) expecting pushMsg
to invoke the callback once the message is dismissed. The battle UI's
hooks.pushMsg is Ui.push which only accepts (text) and silently drops
the callback, so finish(ok) was never called, LearnMove._active stayed
true forever → soft lock (reported as Charmander learning Ember).
Fix: set _pending="done" + _pendingResult before say() so pump() can
complete the sequence on the next update tick once the dialog drains,
matching how the 4-move full path already uses _pending="delete".
The say() callback is still wired so contexts whose pushMsg does honour
it (party_menu TM flow) finish inline as before.
A full-colour icon pack renders white with purple blotches on any screen
that declares an SGB palette zone, and only in ADVANCED. Colour there is
applied after the frame is drawn: a shader reads each pixel's red channel
and swaps in one of four palette colours. That suits the game's own art,
which is already four greys. Full-colour art is not. A yellow body is
nearly all high red, so it clears 0.83 and comes back as colour 0, white in
every palette, while the darker pixels land in colour 2, which MEWMON
paints {115,33,165}.
Art that should be left alone says so with a trueColor flag and is re-blit
unshaded. Battle pics, trainer portraits and overworld sprites all carry
one. Menu icons had no way to. The icons record has no such field, and
Sprites.iconPath returned a path alone where Sprites.path and
Sprites.playerPic both return path, trueColor. Nowhere to put the flag and
nothing to read it, so the art always met the shader.
R.sprites is the precedent for allowing it. Overworld walkers are OBJ art
drawn through an OBJ palette, the same hardware class as a menu icon, and
they carry the flag already.
iconPath now takes the record's flag through opts and returns it, and a
pokemon.icon hook may set ctx.trueColor for art it substitutes, which is
the contract pokemon.sprite already has.
PartyMenu.drawIcon skips the OBP bake for flagged art and reports its
covering rect. The bake matters as much as the shader does: obpIcon is
itself a four-shade remap on the red channel, so it flattens full-colour
art before the zone pass ever runs. The flag overrides `name` rather than
being read beside it, because a hook can substitute full-colour art for a
species that resolved to a built-in class through icons.byDex, leaving name
set. The entry-shape split from #274 does not catch that case.
The reported rect is 16x16 for the two OAM-block branches and the file's
own size for single-frame art, matching what each branch actually draws.
No vanilla icon record sets the flag, so both rect buckets stay empty on a
vanilla boot and the zone lists stay exactly the ones the states returned.
- Change application ID to 'com.theboisclub.pokemonred.dev' for development builds.
- Introduce FireRed manifest handling in build scripts and ensure its validation during packaging.
- Update various scripts to include FireRed resources in the build process.
- fixed a lot of the cachefs extraction to work on android
- Add full 743 trainer ROM extraction from gTrainers with 4-tier party struct support
- Account for flat IV scaling math ((rawIv * 31) / 255) and enforce 0 EVs for trainer Pokémon
- Decompose 32-bit AI script flags for runtime execution
- Implement backwards-search fallback for boss dialogue disconnect (0x1, 0x3, 0x9)
- Implement TrainerSight line-of-sight raycast with elevation & ledge masking and spinning trainer turn hooks
- Support pre-battle intro dialogue, encounter music, and in-battle defeat quotes
- Implement authentic prize money calculation and reward triggering
- Fix move name resolution for table-wrapped party moves in battle UI and party menus
- Implement pure ROM extraction for Trainer Card backgrounds and badges
- Connect TrainerCardExtract to RomExtractorGen3 and CacheContract
- Update TrainerCard, FrlgFont, Chrome, PcChrome, PokedexChrome, and SummaryChrome to route exclusively through CacheFs
- Remove all legacy fallback paths to src/import/gba/chrome and hardcoded pret directories
- Add standalone procedural fallbacks for field effects and Pokecenter heal