Give the FireRed rival and champion the rival's name by class id

Trainers.info gave a trainer the player's chosen rival name only when its
class was called "RIVAL". A mod that translates the class (RIVALE in
German and Italian) made the rival battle as the ROM's placeholder TERRY,
and the champion, whose class is CHAMPION, was always TERRY. pret's
B_TXT_TRAINER1_NAME names TRAINER_CLASS_RIVAL_EARLY, _RIVAL_LATE and
_CHAMPION by the rival's name (pokefirered/src/battle_message.c:2078);
Trainers.info now does the same, by class id.
This commit is contained in:
thibautbus
2026-09-22 15:20:31 +02:00
parent 351b7b3cbb
commit 1c2a7d64de
2 changed files with 40 additions and 2 deletions
+12 -2
View File
@@ -8,6 +8,11 @@ local SPECIES_BULBASAUR = 1
local SPECIES_CHARMANDER = 4
local SPECIES_SQUIRTLE = 7
-- pokefirered/include/constants/trainers.h:264, :272, :273
local TRAINER_CLASS_RIVAL_EARLY = 81
local TRAINER_CLASS_RIVAL_LATE = 89
local TRAINER_CLASS_CHAMPION = 90
local TRAINER_RIVAL_OAKS_LAB_SQUIRTLE = 326
local TRAINER_RIVAL_OAKS_LAB_BULBASAUR = 327
local TRAINER_RIVAL_OAKS_LAB_CHARMANDER = 328
@@ -263,7 +268,8 @@ function Trainers.foeFromId(trainerId)
end
--- ROM-derived trainer presentation info (class / name / pic / partySize / dialogs).
-- opts.rivalName replaces placeholder "TERRY" for class RIVAL when provided.
-- opts.rivalName replaces the placeholder "TERRY" of the rival and champion
-- classes when provided.
function Trainers.info(trainerId, opts)
opts = opts or {}
trainerId = tonumber(trainerId)
@@ -289,7 +295,11 @@ function Trainers.info(trainerId, opts)
dialogs = t.dialogs,
}
if info.className == "RIVAL" and opts.rivalName and opts.rivalName ~= "" then
-- pokefirered/src/battle_message.c:2078 names these classes by the player's
-- rival, recognised by class id: a mod may rename the class itself.
local class = tonumber(info.class)
if (class == TRAINER_CLASS_RIVAL_EARLY or class == TRAINER_CLASS_RIVAL_LATE
or class == TRAINER_CLASS_CHAMPION) and opts.rivalName and opts.rivalName ~= "" then
info.name = opts.rivalName
end
return info
@@ -0,0 +1,28 @@
#!/usr/bin/env luajit
-- The rival and the champion take the player's chosen rival name by class id,
-- as pret's B_TXT_TRAINER1_NAME does (pokefirered/src/battle_message.c:2078),
-- so a mod that translates the class ("RIVALE", "MAÎTRE") keeps the name.
package.path = "./?.lua;./?/init.lua;" .. package.path
love = require("tests.love_stub")
local T = require("tests.harness")
local check = T.check
local Trainers = require("src.core.game3.scripting.trainers")
local rows = {
[326] = { id = 326, class = 81, className = "RIVALE", name = "TERRY", party = {} },
[438] = { id = 438, class = 90, className = "MAÎTRE", name = "TERRY", party = {} },
[500] = { id = 500, class = 89, className = "RIVAL", name = "TERRY", party = {} },
[347] = { id = 347, class = 82, className = "RIVAL", name = "IVAN", party = {} },
}
Trainers.get = function(id) return rows[tonumber(id)] end
local function nameOf(id) return Trainers.info(id, { rivalName = "GARY" }).name end
check(nameOf(326) == "GARY", "the early rival takes the rival name, whatever its class is called")
check(nameOf(500) == "GARY", "so does the late rival")
check(nameOf(438) == "GARY", "and the champion, as on the cart")
check(nameOf(347) == "IVAN", "another class keeps its own trainer's name, even one called RIVAL")
check(Trainers.info(326, {}).name == "TERRY", "with no rival name, the ROM's placeholder stays")
T.finish("game3_trainer_class_ids_test")