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.
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
```
=== TRAINER_TIANA ===

View File

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

View File

@ -2026,7 +2026,24 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
u8 retVal;
if (trainerNum == TRAINER_SECRET_BASE)
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;
}

View File

@ -150,6 +150,9 @@ struct Trainer
struct String pool_prune;
int pool_prune_line;
struct String copy_pool;
int copy_pool_line;
struct String macro;
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 = 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"))
{
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)) {}
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;
if (!p->error)
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++;
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->species = token_string(&species);
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");
}
@ -1863,6 +1879,13 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par
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)
{
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, " .partySize = %d,\n", trainer->party_size);
fprintf(f, " .poolSize = %d,\n", trainer->pokemon_n);
fprintf(f, " .party = (const struct TrainerMon[])\n");
fprintf(f, " {\n");
if (is_empty_string(trainer->copy_pool))
{
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, " .party = (const struct TrainerMon[])\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];
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");
if (is_empty_string(trainer->copy_pool))
fprintf(f, " },\n");
fprintf(f, " },\n");
}
}