Port the remaining battle items, the stats screen and hBattleTurn at the menu
- Run every non-ball item effect usable in battle from the ROM's ItemEffects: Full Restore, revives, bitter medicine, Bitter Berry, Ethers and Elixers, X items, X Accuracy, Guard Spec, Dire Hit and Poké Doll. - Read happiness changes from HappinessChanges, including the larger level-up gain where a Pokémon was caught. - Model hBattleTurn at the battle menu, including the trainer AI's writes, and drop the status-heal refusal. - Port the stats screen for battles and Bill's PC. - Compare the send-out and withdraw texts, RestoreHealth, RestorePP, ChangeHappiness and CalcPlayerStats with the original routines. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cfd083c16d
commit
b13e09ec20
22 files changed
+1547
-171
No files matched your search
@@ -1,10 +1,12 @@
|
||||
import { RomReader } from "./reader";
|
||||
import { decompress } from "./lz";
|
||||
import {
|
||||
BATTLE,
|
||||
INTRO,
|
||||
NUM_ITEMS,
|
||||
NUM_POKEMON,
|
||||
NUM_TRAINER_CLASSES,
|
||||
STATS,
|
||||
SYMBOLS,
|
||||
} from "./profile";
|
||||
import { defaultTextContext, readString } from "../scripts/text";
|
||||
@@ -178,6 +180,43 @@ export class PokemonData {
|
||||
);
|
||||
}
|
||||
|
||||
/** PrintType: the name of a type from TypeNames. */
|
||||
typeName(type: number): string {
|
||||
if (!Number.isInteger(type) || type < 0 || type > 27)
|
||||
throw new Error("Unknown type.");
|
||||
const r = this.reader;
|
||||
return readString(
|
||||
r,
|
||||
r.near(STATS.TypeNames + type * 2, r.bank(STATS.TypeNames)),
|
||||
defaultTextContext(""),
|
||||
);
|
||||
}
|
||||
/** GetGender: the Attack and Speed DVs against the species' ratio;
|
||||
* undefined for genderless species. */
|
||||
gender(species: number, dvs: number): "male" | "female" | undefined {
|
||||
const ratio = this.baseData(species).genderRatio;
|
||||
if (ratio === 0xff) return undefined; // GENDER_UNKNOWN
|
||||
if (!ratio) return "male"; // GENDER_F0
|
||||
if (ratio === 0xfe) return "female"; // GENDER_F100
|
||||
const value = ((dvs >> 8) & 0xf0) | ((dvs >> 4) & 0x0f);
|
||||
return ratio < value ? "male" : "female";
|
||||
}
|
||||
/** PrintTempMonStats' labels: Attack, Defense, Sp. Atk, Sp. Def, Speed. */
|
||||
statNames(): string[] {
|
||||
return readString(
|
||||
this.reader,
|
||||
BATTLE["PrintTempMonStats.StatNames"],
|
||||
defaultTextContext(""),
|
||||
64,
|
||||
)
|
||||
.split("\n")
|
||||
.filter(Boolean);
|
||||
}
|
||||
/** A string of the Pokémon stats screen. */
|
||||
statsString(label: keyof typeof STATS): string {
|
||||
return readString(this.reader, STATS[label], defaultTextContext(""));
|
||||
}
|
||||
|
||||
move(move: number): MoveData {
|
||||
if (!Number.isInteger(move) || move < 1 || move > 251)
|
||||
throw new Error("Unknown move.");
|
||||
|
||||
@@ -320,6 +320,23 @@ export const INTRO = {
|
||||
"GetTimeOfDayString.day_string": 0x90b7b,
|
||||
} as const;
|
||||
|
||||
/** The Pokémon stats screen's strings and the type names, keyed by their
|
||||
* PRET labels so that \`npm run check:reference\` can verify each address. */
|
||||
export const STATS = {
|
||||
"LoadPinkPage.Status_Type": 0x4e119,
|
||||
"LoadPinkPage.OK_str": 0x4e127,
|
||||
"LoadPinkPage.ExpPointStr": 0x4e12b,
|
||||
"LoadPinkPage.LevelUpStr": 0x4e136,
|
||||
"LoadPinkPage.ToStr": 0x4e13f,
|
||||
"LoadPinkPage.PkrsStr": 0x4e142,
|
||||
"LoadGreenPage.Item": 0x4e1a0,
|
||||
"LoadGreenPage.ThreeDashes": 0x4e1a5,
|
||||
"LoadGreenPage.Move": 0x4e1a9,
|
||||
IDNoString: 0x4e21e,
|
||||
OTString: 0x4e222,
|
||||
TypeNames: 0x5097b,
|
||||
} as const;
|
||||
|
||||
/** Pokémon Center and house PCs, Bill's PC and Oak's PC: routines, menu
|
||||
* data, strings and texts, keyed by their PRET labels so that
|
||||
* \`npm run check:reference\` can verify each address by name. */
|
||||
@@ -495,6 +512,24 @@ export const BATTLE = {
|
||||
ItemCantUseOnEggText: 0xf810,
|
||||
OakThisIsntTheTimeText: 0x10af3,
|
||||
UseOnWhichPKMNString: 0x504f3,
|
||||
FullRestoreEffect: 0xf128,
|
||||
ReviveEffect: 0xf0c8,
|
||||
RevivalHerbEffect: 0xf0a9,
|
||||
EnergypowderEffect: 0xf18c,
|
||||
EnergyRootEffect: 0xf190,
|
||||
HealPowderEffect: 0xefad,
|
||||
BitterBerryEffect: 0xf16a,
|
||||
RestorePPEffect: 0xf5bf,
|
||||
XItemEffect: 0xf4c5,
|
||||
XAccuracyEffect: 0xf482,
|
||||
GuardSpecEffect: 0xf4ab,
|
||||
DireHitEffect: 0xf4b8,
|
||||
PokeDollEffect: 0xf48f,
|
||||
XItemStats: 0xf504,
|
||||
HappinessChanges: 0x7221,
|
||||
ItemLooksBitterText: 0xf80b,
|
||||
RestoreThePPOfWhichMoveText: 0xf72a,
|
||||
PPRestoredText: 0xf739,
|
||||
HungOnText: 0x80e99,
|
||||
HurtByBurnText: 0x807f8,
|
||||
HurtByPoisonText: 0x807e2,
|
||||
|
||||
Reference in new issue
Block a user