• Just a reminder that providing specifics on, sharing links to, or naming websites where ROMs can be accessed is against the rules. If your post has any of this information it will be removed.
  • Ever thought it'd be cool to have your art, writing, or challenge runs featured on PokéCommunity? Click here for info - we'd love to spotlight your work!
  • Our weekly protagonist poll is now up! Vote for your favorite Conquest protagonist in the poll by clicking here.
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

[Script] Specials That Change Trainer Attributes

  • 124
    Posts
    9
    Years
    • Seen Apr 5, 2024
    I wanted to make a stadium area where you are given the choice to battle trainers in either single or double battles, but I see I have to define both trainers, one for single and one for double, but that would take a lot of additional trainer slots.

    So I was wondering if there were any specials or any other commands that can make a battle double even if its only defined as single.

    If there aren't any, how would a special like that be written so I could make my own? Any existing commands or specials that already edit a trainer's attribute that was already defined?
     
    No, there aren't any such specials.
    I don't think a special is what you'd want to use here anyway.
    If I were you, I'd just use a flag and make the relevant tweaks to CreateNPCTrainerParty, the function that fills gEnemyParty with a trainer's party data before a trainer battle starts.
    Ex:
    Code:
    diff --git a/include/constants/flags.h b/include/constants/flags.h
    index 8d98e3aa0..53d548930 100644
    --- a/include/constants/flags.h
    +++ b/include/constants/flags.h
    @@ -42,7 +42,7 @@
     #define TEMP_FLAGS_END   FLAG_TEMP_1F
     #define NUM_TEMP_FLAGS   (TEMP_FLAGS_END - TEMP_FLAGS_START + 1)
     
    [color=red]-#define FLAG_UNUSED_0x020    0x20 // Unused Flag[/color]
    [color=seagreen]+#define FLAG_FORCE_DOUBLE_TRAINER_BATTLES    0x20 // Originally Unused Flag[/color]
     #define FLAG_UNUSED_0x021    0x21 // Unused Flag
     #define FLAG_UNUSED_0x022    0x22 // Unused Flag
     #define FLAG_UNUSED_0x023    0x23 // Unused Flag
    diff --git a/src/battle_main.c b/src/battle_main.c
    index c19089deb..5bc17dadf 100644
    --- a/src/battle_main.c
    +++ b/src/battle_main.c
    @@ -1962,6 +1962,7 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
         u8 fixedIV;
         s32 i, j;
         u8 monsCount;
    [color=seagreen]+    bool8 isDoubleBattle = gTrainers[trainerNum].doubleBattle;[/color]
     
         if (trainerNum == TRAINER_SECRET_BASE)
             return 0;
    @@ -1985,10 +1986,13 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
                 monsCount = gTrainers[trainerNum].partySize;
             }
     
    [color=seagreen]+        if (FlagGet(FLAG_FORCE_DOUBLE_TRAINER_BATTLES) && monsCount >= 2)
    +            isDoubleBattle = TRUE;
    +[/color]
             for (i = 0; i < monsCount; i++)
             {
     
    [color=red]-            if (gTrainers[trainerNum].doubleBattle == TRUE)[/color]
    [color=seagreen]+            if (isDoubleBattle == TRUE)[/color]
                     personalityValue = 0x80;
                 else if (gTrainers[trainerNum].encounterMusic_gender & F_TRAINER_FEMALE)
                     personalityValue = 0x78; // Use personality more likely to result in a female Pokémon
    @@ -2067,7 +2071,7 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
                 }
             }
     
    [color=red]-        gBattleTypeFlags |= gTrainers[trainerNum].doubleBattle;[/color]
    [color=seagreen]+        gBattleTypeFlags |= isDoubleBattle;[/color]
         }
     
         return gTrainers[trainerNum].partySize;
     
    No, there aren't any such specials.
    I don't think a special is what you'd want to use here anyway.
    If I were you, I'd just use a flag and make the relevant tweaks to CreateNPCTrainerParty, the function that fills gEnemyParty with a trainer's party data before a trainer battle starts.
    Ex:
    Code:
    diff --git a/include/constants/flags.h b/include/constants/flags.h
    index 8d98e3aa0..53d548930 100644
    --- a/include/constants/flags.h
    +++ b/include/constants/flags.h
    @@ -42,7 +42,7 @@
     #define TEMP_FLAGS_END   FLAG_TEMP_1F
     #define NUM_TEMP_FLAGS   (TEMP_FLAGS_END - TEMP_FLAGS_START + 1)
     
    [color=red]-#define FLAG_UNUSED_0x020    0x20 // Unused Flag[/color]
    [color=seagreen]+#define FLAG_FORCE_DOUBLE_TRAINER_BATTLES    0x20 // Originally Unused Flag[/color]
     #define FLAG_UNUSED_0x021    0x21 // Unused Flag
     #define FLAG_UNUSED_0x022    0x22 // Unused Flag
     #define FLAG_UNUSED_0x023    0x23 // Unused Flag
    diff --git a/src/battle_main.c b/src/battle_main.c
    index c19089deb..5bc17dadf 100644
    --- a/src/battle_main.c
    +++ b/src/battle_main.c
    @@ -1962,6 +1962,7 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
         u8 fixedIV;
         s32 i, j;
         u8 monsCount;
    [color=seagreen]+    bool8 isDoubleBattle = gTrainers[trainerNum].doubleBattle;[/color]
     
         if (trainerNum == TRAINER_SECRET_BASE)
             return 0;
    @@ -1985,10 +1986,13 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
                 monsCount = gTrainers[trainerNum].partySize;
             }
     
    [color=seagreen]+        if (FlagGet(FLAG_FORCE_DOUBLE_TRAINER_BATTLES) && monsCount >= 2)
    +            isDoubleBattle = TRUE;
    +[/color]
             for (i = 0; i < monsCount; i++)
             {
     
    [color=red]-            if (gTrainers[trainerNum].doubleBattle == TRUE)[/color]
    [color=seagreen]+            if (isDoubleBattle == TRUE)[/color]
                     personalityValue = 0x80;
                 else if (gTrainers[trainerNum].encounterMusic_gender & F_TRAINER_FEMALE)
                     personalityValue = 0x78; // Use personality more likely to result in a female Pokémon
    @@ -2067,7 +2071,7 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
                 }
             }
     
    [color=red]-        gBattleTypeFlags |= gTrainers[trainerNum].doubleBattle;[/color]
    [color=seagreen]+        gBattleTypeFlags |= isDoubleBattle;[/color]
         }
     
         return gTrainers[trainerNum].partySize;

    hey lunos that actually made sense I was at that same function trying to edit it, just didnt know what to add to it.

    One question I do have is if I remove the line u mentioned:

    - gBattleTypeFlags |= gTrainers[trainerNum].doubleBattle;

    wouldnt this change how every battle this flag now needs instead of needing the ".doubleBattle = TRUE,"

    or it wouldnt change anything other than just also being able to use a flag to force a double battle even though the trainer attribute makes it a single?
     
    hey lunos that actually made sense I was at that same function trying to edit it, just didnt know what to add to it.

    One question I do have is if I remove the line u mentioned:

    - gBattleTypeFlags |= gTrainers[trainerNum].doubleBattle;

    wouldnt this change how every battle this flag now needs instead of needing the ".doubleBattle = TRUE,"

    or it wouldnt change anything other than just also being able to use a flag to force a double battle even though the trainer attribute makes it a single?

    It wouldn't change anything functionally speaking, because if you look at the top of the diff I posted, the local variable I introduced (isDoubleBattle) is set to gTrainers[trainerNum].doubleBattle by default.
    The doubleBattle field in a trainer's data is a boolean value that tells CreateNPCTrainerParty whether that trainer should be fought in a double battle or not.
    The line you brought up makes sure to set the BATTLE_TYPE_DOUBLE battle type flag based on the value of the doubleBattle field in the relevant trainer's data.
    What I did in the diff is to make CreateNPCTrainerParty handle the same functionality through a local variable instead, which I had to do because you can't manipulate the elements of an array directly. They can only be read. If the elements such as a trainer's doubleBattle present insi an array like gTrainers can't be edited directly, we have to delegate the work to a local variable that handles the default behavior plus whatever else we want.
     
    Last edited:
    It wouldn't change anything functionally speaking, because if you look at the top of the diff I posted, the local variable I introduced (isDoubleBattle) is set to gTrainers[trainerNum].doubleBattle by default.
    The doubleBattle field in a trainer's data is a boolean value that tells CreateNPCTrainerParty whether that trainer should be fought in a double battle or not.
    The line you brought up makes sure to set the BATTLE_TYPE_DOUBLE battle type flag based on the value of the doubleBattle field in the relevant trainer's data.
    What I did in the diff is to make CreateNPCTrainerParty handle the same functionality through a local variable instead, which I had to do because you can't manipulate the elements of an array directly. They can only be read. If the elements such as a trainer's doubleBattle present insi an array like gTrainers can't be edited directly, we have to delegate the work to a local variable that handles the default behavior plus whatever else we want.

    that's great, I will be implementing ur lines, thanks
     
    Back
    Top