Decoupled trainer gender from encounter music (#8892)

This commit is contained in:
Frank DeBlasio 2026-01-12 11:45:44 -05:00 committed by GitHub
parent 550469891a
commit 6dfcde7d48
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 28 additions and 29 deletions

View File

@ -359,22 +359,23 @@ enum TrainerClassID
TRAINER_CLASS_COUNT,
};
#define TRAINER_ENCOUNTER_MUSIC_MALE 0 // standard male encounter music
#define TRAINER_ENCOUNTER_MUSIC_FEMALE 1 // standard female encounter music
#define TRAINER_ENCOUNTER_MUSIC_GIRL 2 // used for male Tubers and Young Couples too
#define TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS 3
#define TRAINER_ENCOUNTER_MUSIC_INTENSE 4
#define TRAINER_ENCOUNTER_MUSIC_COOL 5
#define TRAINER_ENCOUNTER_MUSIC_MALE 0 // Used for Youngsters, Bug Catchers, male School Kids, Sailors, male running and cycling Triathletes, male Pokémon Breeders, and Campers
#define TRAINER_ENCOUNTER_MUSIC_FEMALE 1 // Used for Lasses, Ladies, Beauties, Aroma Ladies, female running and cycling Triathletes, female Pokémon Breeders, and Parasol Ladies
#define TRAINER_ENCOUNTER_MUSIC_GIRL 2 // Used for Tubers, Picnickers, female School Kids, and Young Couples
#define TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS 3 // Used for Ninja Boys, Collectors, Hex Maniacs, Poké Maniacs, and Bug Maniacs
#define TRAINER_ENCOUNTER_MUSIC_INTENSE 4 // Used for Guitarists, Psychics, Black Belts, Battle Girls, Dragon Tamers, Experts, and Old Couples
#define TRAINER_ENCOUNTER_MUSIC_COOL 5 // Used for Cool Trainers, Pokémon Rangers, and Bird Keepers
#define TRAINER_ENCOUNTER_MUSIC_AQUA 6
#define TRAINER_ENCOUNTER_MUSIC_MAGMA 7
#define TRAINER_ENCOUNTER_MUSIC_SWIMMER 8
#define TRAINER_ENCOUNTER_MUSIC_TWINS 9 // used for other trainer classes too
#define TRAINER_ENCOUNTER_MUSIC_SWIMMER 8 // Used for Swimmers, swimming Triathletes, and Sis and Bros
#define TRAINER_ENCOUNTER_MUSIC_TWINS 9 // Used for Twins, Poké Fans, and Sr. and Jr.s
#define TRAINER_ENCOUNTER_MUSIC_ELITE_FOUR 10
#define TRAINER_ENCOUNTER_MUSIC_HIKER 11 // used for other trainer classes too
#define TRAINER_ENCOUNTER_MUSIC_HIKER 11 // Used for Hikers, Ruin Maniacs, Kindlers, and Fishermen
#define TRAINER_ENCOUNTER_MUSIC_INTERVIEWER 12
#define TRAINER_ENCOUNTER_MUSIC_RICH 13 // Rich Boys and Gentlemen
#define TRAINER_ENCOUNTER_MUSIC_RICH 13 // Used for Rich Boys and Gentlemen
#define F_TRAINER_FEMALE (1 << 7)
#define TRAINER_GENDER_MALE 0
#define TRAINER_GENDER_FEMALE 1
// Trainer party defines
#define TRAINER_MON_MALE 1

View File

@ -119,7 +119,8 @@ struct Trainer
u16 items[MAX_TRAINER_ITEMS];
struct StartingStatuses startingStatus; // this trainer starts a battle with a given status. see include/constants/battle.h for values
u8 trainerClass;
u8 encounterMusic_gender; // last bit is gender
u8 encounterMusic:7;
u8 gender:1;
enum TrainerPicID trainerPic;
u8 trainerName[TRAINER_NAME_LENGTH + 1];
u8 battleType:2;

View File

@ -1905,7 +1905,7 @@ u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer
if (trainer->battleType != TRAINER_BATTLE_TYPE_SINGLES)
personalityValue = 0x80;
else if (trainer->encounterMusic_gender & F_TRAINER_FEMALE)
else if (trainer->gender == TRAINER_GENDER_FEMALE)
personalityValue = 0x78; // Use personality more likely to result in a female Pokémon
else
personalityValue = 0x88; // Use personality more likely to result in a male Pokémon
@ -3824,7 +3824,7 @@ static void TryDoEventsBeforeFirstTurn(void)
if (ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT), TRAINER_SLIDE_BEFORE_FIRST_TURN))
{
// Ensures only trainer A slide is played in single-trainer doubles (B == A / B == TRAINER_NONE) and 2v1 multibattles (B == 0xFFFF)
if (!((TRAINER_BATTLE_PARAM.opponentB == TRAINER_BATTLE_PARAM.opponentA)
if (!((TRAINER_BATTLE_PARAM.opponentB == TRAINER_BATTLE_PARAM.opponentA)
|| (TRAINER_BATTLE_PARAM.opponentB == TRAINER_NONE)
|| (TRAINER_BATTLE_PARAM.opponentB == 0xFFFF)))
{

View File

@ -113,7 +113,7 @@ void FillPartnerParty(u16 trainerId)
StringCopy(trainerName, gBattlePartners[difficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName);
SetMonData(&gPlayerParty[i + 3], MON_DATA_OT_NAME, trainerName);
j = gBattlePartners[difficulty][SanitizeTrainerId(trainerId - TRAINER_PARTNER(PARTNER_NONE))].encounterMusic_gender >> 7;
j = gBattlePartners[difficulty][SanitizeTrainerId(trainerId - TRAINER_PARTNER(PARTNER_NONE))].gender;
SetMonData(&gPlayerParty[i + 3], MON_DATA_OT_GENDER, &j);
}
}

View File

@ -5087,7 +5087,7 @@ u8 GetTrainerEncounterMusicId(u16 trainerOpponentId)
else if (InTrainerHillChallenge())
return GetTrainerEncounterMusicIdInTrainerHill(trainerOpponentId);
else
return gTrainers[difficulty][sanitizedTrainerId].encounterMusic_gender & (F_TRAINER_FEMALE - 1);
return gTrainers[difficulty][sanitizedTrainerId].encounterMusic;
}
u16 ModifyStatByNature(u8 nature, u16 stat, enum Stat statIndex)
@ -5617,7 +5617,7 @@ u32 GetRelearnerTMMoves(struct Pokemon *mon, u16 *moves)
if (!CanLearnTeachableMove(species, move))
continue;
if (!MonKnowsMove(mon, move))
moves[numMoves++] = move;
}

View File

@ -115,7 +115,7 @@ struct Trainer
struct String encounter_music;
int encounter_music_line;
enum Gender gender;
struct String gender;
int gender_line;
struct String pic;
@ -1206,8 +1206,7 @@ static bool parse_trainer(struct Parser *p, const struct Parsed *parsed, struct
if (trainer->gender_line)
any_error = !set_show_parse_error(p, key.location, "duplicate 'Gender'");
trainer->gender_line = value.location.line;
if (!token_gender(p, &value, &trainer->gender))
any_error = !show_parse_error(p);
trainer->gender = token_string(&value);
}
else if (is_literal_token(&key, "Pic"))
{
@ -1825,23 +1824,21 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par
fprintf(f, ",\n");
}
fprintf(f, " .encounterMusic_gender =\n");
if (trainer->gender == GENDER_FEMALE)
if (!is_empty_string(trainer->gender))
{
fprintf(f, "#line %d\n", trainer->gender_line);
fprintf(f, "F_TRAINER_FEMALE | \n");
fprintf(f, " .gender = ");
fprint_constant(f, "TRAINER_GENDER", trainer->gender);
fprintf(f, ",\n");
}
if (!is_empty_string(trainer->encounter_music))
{
fprintf(f, "#line %d\n", trainer->encounter_music_line);
fprintf(f, " ");
fprintf(f, " .encounterMusic = ");
fprint_constant(f, "TRAINER_ENCOUNTER_MUSIC", trainer->encounter_music);
fprintf(f, ",\n");
}
else
{
fprintf(f, "0");
}
fprintf(f, ",\n");
if (trainer->items_n > 0)
{