Open Route 31, Violet City and Sprout Tower (#31)
Enable Route 31 and its gate, Dark Cave's Violet entrance, Violet City with its buildings and Sprout Tower. Port the script commands they use: gettrainername, askforphonenumber (with AddPhoneNumber's room for Mom and Elm; addcellnum now reports failure as the original does), checkpokemail, loadmenu/_2dmenu/closewindow, giveegg and trade (NPCTrade, with wTradeFlags saved). Eggs keep their species with an egg flag, as wPartySpecies does. The pack's TM/HM counts receive, check and toss TMs and HMs, which are named TM01-HM07. The playthrough continues through Route 31 (with Mom's call), Violet City and Sprout Tower to Elder Li's Flash. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ec3d1cd5c4
commit
7909302db1
16 files changed
+585
-63
No files matched your search
@@ -8,7 +8,7 @@ import {
|
||||
restoredPP,
|
||||
} from "../battle/battle";
|
||||
import { receiveItem, removeFromSlot, type ItemSlot } from "../party/bag";
|
||||
import { calcStats, maxPP, type PartyMon } from "../party/pokemon";
|
||||
import { calcStats, maxPP, partyMonDetails, type PartyMon } from "../party/pokemon";
|
||||
import type { GameTime } from "../world/game-time";
|
||||
import { PartyEvolution, evoStoneCompatible } from "./evolution";
|
||||
import {
|
||||
@@ -60,7 +60,6 @@ const ITEM_MENUS: Record<string, ItemAction[]> = {
|
||||
"MenuHeader_HoldableItem.MenuData": ["give", "toss", "quit"],
|
||||
};
|
||||
const {
|
||||
EGG,
|
||||
ITEMMENU_CURRENT,
|
||||
ITEMMENU_PARTY,
|
||||
ITEMMENU_CLOSE,
|
||||
@@ -435,14 +434,14 @@ export class StartMenuRun {
|
||||
party.map((mon) =>
|
||||
// PlacePartyMonEvoStoneCompatibility replaces the HP bar.
|
||||
action === C.PARTYMENUACTION_EVO_STONE
|
||||
? mon.species === EGG
|
||||
? mon.egg
|
||||
? ""
|
||||
: this.string(
|
||||
evoStoneCompatible(r, mon.species, item)
|
||||
? MENU["PlacePartyMonEvoStoneCompatibility.string_able"]
|
||||
: MENU["PlacePartyMonEvoStoneCompatibility.string_not_able"],
|
||||
)
|
||||
: `:L${mon.level} HP ${mon.hp}/${mon.stats[0]}${mon.hp ? statusName(mon.status) : " FNT"}`,
|
||||
: partyMonDetails(mon),
|
||||
),
|
||||
// InitPartyMenuWithCancel: the last row chosen, if still listed.
|
||||
this.cursors.party >= 1 && this.cursors.party <= party.length
|
||||
@@ -467,7 +466,7 @@ export class StartMenuRun {
|
||||
/** GetMonSubmenuItems: field moves the Pokémon knows, then STATS,
|
||||
* SWITCH, MOVE, ITEM or MAIL, and CANCEL if there is room. */
|
||||
private monSubmenuItems(mon: PartyMon) {
|
||||
if (mon.species === EGG)
|
||||
if (mon.egg)
|
||||
return [MONMENUITEM_STATS, MONMENUITEM_SWITCH, MONMENUITEM_CANCEL];
|
||||
const r = this.reader,
|
||||
items: number[] = [];
|
||||
@@ -621,7 +620,7 @@ export class StartMenuRun {
|
||||
/** GiveTakePartyMonItem: GIVE opens the pack, TAKE returns the item. */
|
||||
private *giveTakePartyMonItem(slot: number): Gen {
|
||||
const mon = this.state.party[slot];
|
||||
if (mon.species === EGG) return;
|
||||
if (mon.egg) return;
|
||||
const choice = yield* this.menu(
|
||||
[mon.nickname],
|
||||
this.stringList(MENU["GiveTakeItemMenuData.Items"] + 2, 2),
|
||||
@@ -751,7 +750,7 @@ export class StartMenuRun {
|
||||
* or next party member's moves, skipping Eggs, unless a move is being
|
||||
* moved. */
|
||||
private *managePokemonMoves(slot: number): Gen {
|
||||
if (this.state.party[slot].species === EGG) return;
|
||||
if (this.state.party[slot].egg) return;
|
||||
const where = this.string(MENU.String_MoveWhere);
|
||||
let cursor = 0;
|
||||
for (;;) {
|
||||
@@ -807,7 +806,7 @@ export class StartMenuRun {
|
||||
private cycleMoveScreen(slot: number, direction: "left" | "right") {
|
||||
const party = this.state.party;
|
||||
let current = slot;
|
||||
const egg = (index: number) => party[index].species === EGG;
|
||||
const egg = (index: number) => party[index].egg;
|
||||
let step: "left" | "right" | "done" = direction;
|
||||
for (let guard = 0; step !== "done" && guard < 64; guard++) {
|
||||
if (step === "right") {
|
||||
@@ -1021,7 +1020,7 @@ export class StartMenuRun {
|
||||
for (;;) {
|
||||
const slot = yield* this.partyMenu(PARTYMENUACTION_GIVE_ITEM);
|
||||
if (slot < 0) return;
|
||||
if (this.state.party[slot].species === EGG) {
|
||||
if (this.state.party[slot].egg) {
|
||||
yield* this.print(MENU["GiveItem.AnEggCantHoldAnItemText"]);
|
||||
continue;
|
||||
}
|
||||
@@ -1152,7 +1151,7 @@ export class StartMenuRun {
|
||||
case MENU.SacredAshEffect:
|
||||
// _SacredAsh: SacredAshScript heals the party once the menu closes,
|
||||
// if a Pokémon that is not an Egg has fainted (CheckAnyFaintedMon).
|
||||
if (!this.state.party.some((mon) => mon.species !== EGG && !mon.hp))
|
||||
if (!this.state.party.some((mon) => !mon.egg && !mon.hp))
|
||||
return false;
|
||||
this.useDisposableItem(use);
|
||||
this.deferred = MENU.SacredAshScript;
|
||||
@@ -1275,7 +1274,7 @@ export class StartMenuRun {
|
||||
): Gen<number> {
|
||||
const slot = yield* this.partyMenu(action, undefined, item);
|
||||
if (slot < 0) return -1;
|
||||
if (this.state.party[slot].species === EGG) {
|
||||
if (this.state.party[slot].egg) {
|
||||
yield* this.print(BATTLE.ItemCantUseOnEggText);
|
||||
return -1;
|
||||
}
|
||||
@@ -1305,7 +1304,7 @@ export class StartMenuRun {
|
||||
}
|
||||
private changeHappiness(slot: number, action: number) {
|
||||
const mon = this.state.party[slot];
|
||||
if (mon.species === EGG) return;
|
||||
if (mon.egg) return;
|
||||
const tier = mon.happiness < 100 ? 0 : mon.happiness < 200 ? 1 : 2;
|
||||
mon.happiness = changedHappiness(
|
||||
mon.happiness,
|
||||
@@ -1563,13 +1562,3 @@ interface FieldItemUse {
|
||||
index: number;
|
||||
}
|
||||
|
||||
const STATUS_NAMES: [number, string][] = [
|
||||
[0x08, " PSN"],
|
||||
[0x10, " BRN"],
|
||||
[0x20, " FRZ"],
|
||||
[0x40, " PAR"],
|
||||
];
|
||||
function statusName(status: number) {
|
||||
if (status & 7) return " SLP";
|
||||
return STATUS_NAMES.find(([bit]) => status & bit)?.[1] ?? "";
|
||||
}
|
||||
Reference in new issue
Block a user