From fa0ab3621fba9c2bb02f0d37abdbd2986d9c4e81 Mon Sep 17 00:00:00 2001 From: thibautbus <310327033+thibautbus@users.noreply.github.com> Date: Tue, 22 Sep 2026 15:20:31 +0200 Subject: [PATCH] Record FireRed gym, Elite Four and champion wins by class id The quest log told a gym leader, Elite Four or champion win from the trainer's class name ("LEADER", "ELITE FOUR", "CHAMPION"). With a translated class every such win fell back to the plain trainer event, and in French, where the gym LEADER class reads CHAMPION, every gym win would be logged as a champion battle. pret switches on the class id (pokefirered/src/quest_log_battle.c:25); the battle state now keeps the trainer's class id next to its name, and the recorder reads it. --- src/core/game3/battle/init.lua | 2 ++ src/core/game3/quest_log_recorder.lua | 10 ++++++---- tests/game3_quest_log_integration_test.lua | 13 ++++++++++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/core/game3/battle/init.lua b/src/core/game3/battle/init.lua index a962f468..83e3534d 100644 --- a/src/core/game3/battle/init.lua +++ b/src/core/game3/battle/init.lua @@ -529,10 +529,12 @@ function Battle.start(opts) })) st.trainerId = trainerId + st.trainerClass = trainerInfo and tonumber(trainerInfo.class) st.trainerClassName = trainerInfo and trainerInfo.className st.trainerName = (trainerInfo and trainerInfo.name) or opts.trainerName -- pokefirered/src/battle_message.c:394 the link opponent is named, never classed if st.link and not st.unionRoom and st.peerName then + st.trainerClass = nil st.trainerClassName = "" st.trainerName = st.peerName end diff --git a/src/core/game3/quest_log_recorder.lua b/src/core/game3/quest_log_recorder.lua index 48568013..f27576da 100644 --- a/src/core/game3/quest_log_recorder.lua +++ b/src/core/game3/quest_log_recorder.lua @@ -91,12 +91,14 @@ function R.battle(session,st) local outcome=hp>=math.floor(max/3)*2 and 'Handily' or (hp>=math.floor(max/3) and 'Tenaciously' or 'Somehow') local args={D0=loc,D1=st.trainerName or 'TRAINER',D2=enemy,D3=player,D4={text=outcome}} local key='TookOnTrainersMonWithMonAndWon' - local class=st.trainerClassName or '' - if class=='LEADER' then key='TookOnGymLeadersMonWithMonAndWon' - elseif class=='ELITE FOUR' then + -- pokefirered/src/quest_log_battle.c:25 switches on the class id, which a + -- mod renaming the class leaves alone (include/constants/trainers.h:267-273) + local class=tonumber(st.trainerClass) + if class==84 then key='TookOnGymLeadersMonWithMonAndWon' + elseif class==87 then key='TookOnEliteFoursMonWithMonAndWon' args={D0=st.trainerName,D1=enemy,D2=player,D3={text=outcome}} - elseif class=='CHAMPION' then + elseif class==90 then key='PlayerBattledChampionRival';args={D0=session.name,D1=st.trainerName} end R.event(session,key,args) diff --git a/tests/game3_quest_log_integration_test.lua b/tests/game3_quest_log_integration_test.lua index a83b5c73..2be33983 100644 --- a/tests/game3_quest_log_integration_test.lua +++ b/tests/game3_quest_log_integration_test.lua @@ -42,9 +42,20 @@ local a={'TEST'};Recorder.event(session,'ArrivedInLocation',a);a[1]='WRONG' assert(session.questLog.scenes[#session.questLog.scenes].events[2].args[1]=='TEST') local other={map='FR_OTHER'};Recorder.event(other,'ArrivedInLocation',a);assert(other.questLog==nil) local Pokemon=require('src.core.game3.pokemon');Pokemon.displayMonName=function(m)return m.name end -local st={wild=false,result='win',trainerName='BROCK',trainerClassName='LEADER', +-- The French cart calls a gym LEADER "CHAMPION": the class id decides, not its name. +local st={wild=false,result='win',trainerName='BROCK',trainerClass=84,trainerClassName='CHAMPION', player={mon={name='BULBASAUR',hp=20,maxHp=30}},enemy={mon={name='ONIX'}}} Recorder.battle(session,st) local e=session.questLog.scenes[#session.questLog.scenes].events[3] assert(e.key=='TookOnGymLeadersMonWithMonAndWon' and e.args.D4.text=='Handily') +local function keyFor(class,className) + local s={wild=false,result='win',trainerName='X',trainerClass=class,trainerClassName=className, + player={mon={name='BULBASAUR',hp=20,maxHp=30}},enemy={mon={name='ONIX'}}} + Recorder.battle(session,s) + local evs=session.questLog.scenes[#session.questLog.scenes].events + return evs[#evs].key +end +assert(keyFor(87,'CONSEIL 4')=='TookOnEliteFoursMonWithMonAndWon') +assert(keyFor(90,'MAÎTRE')=='PlayerBattledChampionRival') +assert(keyFor(82,'LEADER')=='TookOnTrainersMonWithMonAndWon') print('PASS Quest Log Continue, legacy save, quit, RNG isolation, event scoping and battle summary')