• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • 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
    8
    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?
     

    Lunos

    Random Uruguayan User
  • 3,116
    Posts
    15
    Years
    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;
     
  • 124
    Posts
    8
    Years
    • Seen Apr 5, 2024
    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?
     

    Lunos

    Random Uruguayan User
  • 3,116
    Posts
    15
    Years
    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:
  • 124
    Posts
    8
    Years
    • Seen Apr 5, 2024
    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