trainerproc copy other trainer party (#7251)

This commit is contained in:
hedara90 2025-07-18 16:57:57 +02:00 committed by GitHub
parent e5cf6b1e6e
commit 05b1db8cc6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 59 additions and 9 deletions

View File

@ -52,6 +52,11 @@ By default, only `Default<position>PickFunction` and `PickLowest` are implemente
- `Pool Prune` (`.poolPruneIndex`) controls if members in the pool should be removed before party members are picked from the pool. - `Pool Prune` (`.poolPruneIndex`) controls if members in the pool should be removed before party members are picked from the pool.
By default, only `POOL_PRUNE_NONE`, which doesn't remove anything from the pool, and `POOL_PRUNE_TEST`, which removes Wobbuffet from the pool, are implemented. Must be an `enum` value in `enum PoolPruneOptions`. By default, only `POOL_PRUNE_NONE`, which doesn't remove anything from the pool, and `POOL_PRUNE_TEST`, which removes Wobbuffet from the pool, are implemented. Must be an `enum` value in `enum PoolPruneOptions`.
## Pool copy
The `Copy Pool` option can be used to have the trainer use the party or pool from a different trainer.
If you for example want some other trainer to have the same team/pool as Tiana, you'd use `Copy Pool: TRAINER_TIANA`.
If `Party Size` isn't defined for the current trainer, it will inherit from the copied trainer.
## Example pool ## Example pool
``` ```
=== TRAINER_TIANA === === TRAINER_TIANA ===

View File

@ -105,6 +105,7 @@ struct Trainer
/*0x22*/ u8 poolRuleIndex; /*0x22*/ u8 poolRuleIndex;
/*0x23*/ u8 poolPickIndex; /*0x23*/ u8 poolPickIndex;
/*0x24*/ u8 poolPruneIndex; /*0x24*/ u8 poolPruneIndex;
/*0x25*/ u16 overrideTrainer;
}; };
struct TrainerClass struct TrainerClass

View File

@ -2026,7 +2026,24 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
u8 retVal; u8 retVal;
if (trainerNum == TRAINER_SECRET_BASE) if (trainerNum == TRAINER_SECRET_BASE)
return 0; return 0;
retVal = CreateNPCTrainerPartyFromTrainer(party, GetTrainerStructFromId(trainerNum), firstTrainer, gBattleTypeFlags); if (GetTrainerStructFromId(trainerNum)->overrideTrainer)
{
struct Trainer tempTrainer;
memcpy(&tempTrainer, GetTrainerStructFromId(trainerNum), sizeof(struct Trainer));
const struct Trainer *origTrainer = GetTrainerStructFromId(tempTrainer.overrideTrainer);
tempTrainer.party = origTrainer->party;
tempTrainer.poolSize = origTrainer->poolSize;
if (tempTrainer.partySize == 0)
tempTrainer.partySize = origTrainer->partySize;
retVal = CreateNPCTrainerPartyFromTrainer(party, (const struct Trainer *)(&tempTrainer), firstTrainer, gBattleTypeFlags);
}
else
{
retVal = CreateNPCTrainerPartyFromTrainer(party, GetTrainerStructFromId(trainerNum), firstTrainer, gBattleTypeFlags);
}
return retVal; return retVal;
} }

View File

@ -150,6 +150,9 @@ struct Trainer
struct String pool_prune; struct String pool_prune;
int pool_prune_line; int pool_prune_line;
struct String copy_pool;
int copy_pool_line;
struct String macro; struct String macro;
int macro_line; int macro_line;
}; };
@ -1283,6 +1286,13 @@ static bool parse_trainer(struct Parser *p, const struct Parsed *parsed, struct
trainer->pool_prune_line = value.location.line; trainer->pool_prune_line = value.location.line;
trainer->pool_prune = token_string(&value); trainer->pool_prune = token_string(&value);
} }
else if (is_literal_token(&key, "Copy Pool"))
{
if (trainer->copy_pool_line)
any_error = !set_show_parse_error(p, key.location, "duplicate 'Copy Pool'");
trainer->copy_pool_line = value.location.line;
trainer->copy_pool = token_string(&value);
}
else if (is_literal_token(&key, "Macro")) else if (is_literal_token(&key, "Macro"))
{ {
if (trainer->macro_line) if (trainer->macro_line)
@ -1317,7 +1327,7 @@ static bool parse_trainer(struct Parser *p, const struct Parsed *parsed, struct
while (match_empty_line(p)) {} while (match_empty_line(p)) {}
if (!parse_pokemon_header(p, &nickname, &species, &gender, &item)) if (!parse_pokemon_header(p, &nickname, &species, &gender, &item))
{ {
if (i > 0 || ends_with(trainer->id, "_NONE")) if (i > 0 || ends_with(trainer->id, "_NONE") || !is_empty_string(trainer->copy_pool))
break; break;
if (!p->error) if (!p->error)
set_parse_error(p, p->location, "expected nickname or species"); set_parse_error(p, p->location, "expected nickname or species");
@ -1331,6 +1341,12 @@ static bool parse_trainer(struct Parser *p, const struct Parsed *parsed, struct
} }
trainer->pokemon_n++; trainer->pokemon_n++;
if (!is_empty_string(trainer->copy_pool))
{
set_show_parse_error(p, p->location, "trainer is set to copy mons from other trainer, but defines their own party");
}
pokemon->nickname = token_string(&nickname); pokemon->nickname = token_string(&nickname);
pokemon->species = token_string(&species); pokemon->species = token_string(&species);
if (is_empty_token(&gender)) if (is_empty_token(&gender))
@ -1529,7 +1545,7 @@ static bool parse_trainer(struct Parser *p, const struct Parsed *parsed, struct
} }
} }
if (trainer->party_size_line && trainer->party_size > trainer->pokemon_n) if (trainer->party_size_line && trainer->party_size > trainer->pokemon_n && is_empty_string(trainer->copy_pool))
{ {
set_show_parse_error(p, p->location, "partySize larger than supplied pool"); set_show_parse_error(p, p->location, "partySize larger than supplied pool");
} }
@ -1863,6 +1879,13 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par
fprintf(f, ",\n"); fprintf(f, ",\n");
} }
if (!is_empty_string(trainer->copy_pool))
{
fprintf(f, "#line %d\n", trainer->copy_pool_line);
fprintf(f, " .overrideTrainer = ");
fprint_string(f, trainer->copy_pool);
fprintf(f, ",\n");
}
if (trainer->macro_line) if (trainer->macro_line)
{ {
fprintf(f, "#line %d\n", trainer->macro_line); fprintf(f, "#line %d\n", trainer->macro_line);
@ -1875,18 +1898,21 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par
{ {
fprintf(f, "#line %d\n", trainer->party_size_line); fprintf(f, "#line %d\n", trainer->party_size_line);
fprintf(f, " .partySize = %d,\n", trainer->party_size); fprintf(f, " .partySize = %d,\n", trainer->party_size);
fprintf(f, " .poolSize = %d,\n", trainer->pokemon_n); if (is_empty_string(trainer->copy_pool))
fprintf(f, " .party = (const struct TrainerMon[])\n"); {
fprintf(f, " {\n"); fprintf(f, " .poolSize = %d,\n", trainer->pokemon_n);
fprintf(f, " .party = (const struct TrainerMon[])\n");
fprintf(f, " {\n");
}
} }
else else if (is_empty_string(trainer->copy_pool))
{ {
fprintf(f, " .partySize = %d,\n", trainer->pokemon_n); fprintf(f, " .partySize = %d,\n", trainer->pokemon_n);
fprintf(f, " .party = (const struct TrainerMon[])\n"); fprintf(f, " .party = (const struct TrainerMon[])\n");
fprintf(f, " {\n"); fprintf(f, " {\n");
} }
for (int j = 0; j < trainer->pokemon_n; j++) for (int j = 0; j < trainer->pokemon_n && is_empty_string(trainer->copy_pool); j++)
{ {
struct Pokemon *pokemon = &trainer->pokemon[j]; struct Pokemon *pokemon = &trainer->pokemon[j];
fprintf(f, " {\n"); fprintf(f, " {\n");
@ -2049,7 +2075,8 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par
fprintf(f, " },\n"); fprintf(f, " },\n");
} }
fprintf(f, " },\n"); if (is_empty_string(trainer->copy_pool))
fprintf(f, " },\n");
fprintf(f, " },\n"); fprintf(f, " },\n");
} }
} }