• 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.

[Pokeemerald] Let Enemy Trainers Use Revival Items Correctly

247
Posts
6
Years
    • Seen May 2, 2024
    Normally, if you were to give an opposing trainer a Revive, Max Revive, or a Revival Herb, they would use it once their current Pokémon was at low health, which would end up doing nothing. The following changes will allow the A.I. to be able to use their revival items only when they have a fainted Pokémon on their team, and they will properly use it on that fainted Pokémon.

    With these changes, the A.I. will use their revival item as soon as they notice that they have a fainted Pokemon on their team. There are a lot of files that need to be adjusted for this, but each of the changes are pretty minor, so don't get overwhelmed. These changes are made to work with the Battle Engine Upgrade (as of June 14th, 2021), but it would only take a few simple tweaks to make this work without the BEU. If you need help with that, just let me know.

    asm/macros/battle_script.inc
    Spoiler:
    charmap.txt
    Spoiler:
    data/battle_scripts_2.s
    Spoiler:
    include
    Spoiler:

    src
    Spoiler:
    With that, you now can give your enemy trainers Revives, Revival Herbs, or whatever other revive items you have to make them all that much more challenging!
     
    Last edited:
    853
    Posts
    3
    Years
    • Seen Nov 9, 2023
    Great tutorial and addition, I just wanted to make a little note, that to make the best use of this feature, anyone planning to add it, should make additions to their trainer ai,
    and probably add some conditions that would allow the enemy to make switch plays to sack members of their team for strategy, like we do.

    Otherwise they'd probably do something like revive the first pokemon you knock out, or at best they just use it in a strategically boring way.
    and that would only add time, and not challenge.

    Just thinking on this now, I've got two different ways that could be done,

    I call it the, "God Save the Queen" strategy and the "Invincible Knight Siegfried" Strategy.

    They're pretty simple really, the former is based around using revives on support pokemon, sacrificing them to prolong the main pokemon.

    While the latter, is more offensive, that's based around having a strong attacker barrel into the player team, and revive it when it dies.

    Imagine an intimidate archanine, somewhat hard to beat already, takes down 2 of your team before it finally dies,
    then the opponent switches in support pokemon which applies debuffs, or then maybe sets up baton pass buffs,
    only to bring back that same archanine even stronger then before.

    Anyone those are my thoughts.
     

    Jessler

    PidgeyFox
    33
    Posts
    6
    Years
  • Hey, just to let you know, this code doesn't really work. It will automatically use a revive just about instantly due to the way PARTY_SIZE works. I fixed this using a similar method to how they calculate validMons in battle_ai_switch_items.c by replacing the HP !=0 with == 0. Here's the code.


    battle_ai_switch_items.c
    Spoiler:


    battle_script_commands.c

    Spoiler:


    Now the AI will use a revive as soon as their first Mon faints. So the trigger for using the revive is fixed. Yay! Unfortunately, the revive still doesn't actually do anything. The message pops up correctly and the revive is removed from their items, but they don't send the revived Mon back out. The battle simply ends after you KO the rest of their team. This is where I'm stuck, but at least I've made progress. Hopefully someone else will come along and finish this.
     
    247
    Posts
    6
    Years
    • Seen May 2, 2024
    Hey, just to let you know, this code doesn't really work. It will automatically use a revive just about instantly due to the way PARTY_SIZE works.

    That is interesting. I just tested my version of this code, and it properly revived the first fainted mon, consuming the item and bringing the mon back to half or full health, depending on the revival item used. They also eventually send the revived mon back out with my version. Are you sure you didn't miss something in the tutorial? I can't recreate this error on my end. Is the issue that the trainer is automatically using the revive item, regardless of whether there's a fainted mon or not?
     

    Jessler

    PidgeyFox
    33
    Posts
    6
    Years
  • Hm, I'll check back to make sure, but I think I did everything. The issue began with the trainers using items immediately regardless of a fainted mon, but after the changes I made they now revive them at the proper moment. It still doesn't do anything, though.

    EDIT: Yeah, went through it all again just to make sure. Did you maybe leave out a change you made to get this working? I'm guessing the game flags their Pokemon as unusable after it faints and you'd have to revert that to allow them to send it back out, no?
     
    Last edited:
    247
    Posts
    6
    Years
    • Seen May 2, 2024
    EDIT: Yeah, went through it all again just to make sure. Did you maybe leave out a change you made to get this working? I'm guessing the game flags their Pokemon as unusable after it faints and you'd have to revert that to allow them to send it back out, no?

    As far as I can tell, there is no flag to determine if a Pokemon is out of the fight or not. If they're at 0 HP, then they're out.

    I just created a new repository that is a copy of pret's master pokeemerald branch. I then added the Revive AI stuff, following the steps on this tutorial to the letter, other than needing to change the constants in charmap.txt, include/battle_message.h, include/constants/battle_script_commands.h, and include/constants/battle_string_ids.h, since pret's repository doesn't have the battle engine upgrade stuff. I then gave myself a couple lvl 100 Pokemon and gave the first gym battle Roxanne a Revive, and finally warped to the gym via Professor Birch's lab.

    On the first turn, Roxanne did not use her Revive. Geodude used Rock Throw. I took out her first Geodude. Roxanne sends out her second Geodude.
    On the second turn, Roxanne used her Revive, with the message appearing properly. I took out her second Geodude. Roxanne then sends out her first Geodude, this time at half health.

    I've attached pictures of a comparison between my repository and pret's to show that there are no differences between them other than what I've stated here.
    Spoiler:
    This is as thoroughly as I can test without accessing your repository. I don't know why my version of the code doesn't work for you, but I know for a fact that my code does work.
     
    180
    Posts
    6
    Years
    • Seen Apr 15, 2024
    Hi!
    I wanted to implement this, but it doesnt work for me
    It just uses a Revive at first turn in the battle, and if i use Jessler's fix, itll never use the revive at all!
    Ive checked the code again, and nothing seems to be wrong...
     
    247
    Posts
    6
    Years
    • Seen May 2, 2024
    Hi!
    I wanted to implement this, but it doesnt work for me
    It just uses a Revive at first turn in the battle, and if i use Jessler's fix, itll never use the revive at all!
    Ive checked the code again, and nothing seems to be wrong...

    I'd love to help, but I'd need to see snapshots of all the code changes that you made.
     
    247
    Posts
    6
    Years
    • Seen May 2, 2024
    I copy-pasted the things you showed in the post

    i added the images of the relevant src changes in this imgur link
    https://imgur.com/a/tqLmtSe

    Based on those pictures, you certainly did everything correctly. Like I said with Jessler, I've tested this code with a clean pokeemerald repository, and it works as described. The only way I could help you more is if I poked around your repository, trying to see some conflict with the code that I wasn't aware of. The critical code in relation to deciding when to actually use the item is in ShouldUseItem, but as far as I can tell, you added the stuff in that function properly.
     

    Lunos

    Random Uruguayan User
    3,114
    Posts
    15
    Years
  • Hi!
    I wanted to implement this, but it doesnt work for me
    It just uses a Revive at first turn in the battle, and if i use Jessler's fix, itll never use the revive at all!
    Ive checked the code again, and nothing seems to be wrong...
    Someone I know got the same issue and they started to look into a solution, they asked me to bring what they have here:
    S9oezXK.png
     
    247
    Posts
    6
    Years
    • Seen May 2, 2024
    Someone I know got the same issue.....

    This is really bizarre. I just now cloned pret's repo, added the code exactly as it is in the tutorial, and then gave Roxanne a revive. It operated exactly as intended. The only changes I made were updating some function names and constants, which I will now update in the tutorial, but nothing having to do with the code itself. I don't understand why that extra check would be necessary to get it to run for someone else. I would also assume that the added if-statement should only have one greater-than sign, not two. I don't see how bit-shifting something 0 to the right would fix anything.
     

    DoesntKnowHowToPlay

    Tiny Umbrella with Lots and Lots of Good
    265
    Posts
    12
    Years
    • Seen Feb 24, 2024
    Bit-shifting something by 0 to the right means that statement evaluates as just itself. You can read that if statement as if the ">> 0" bit wasn't there at all, since integers and booleans are interchangeable; any non-zero value will evaluate as true. (It is probably intended to be one greater than, but it's more or less equivalent either way.)

    I have a guess as to a potential problem here: you're looping through the enemy party from 0 to PARTY_SIZE, looking for a Pokemon with 0 HP. This isn't something you can blindly do in a general case, because PARTY_SIZE is just a constant 6, and there are trainers with less than 6 pokemon; an empty teamslot has 0 HP, and will prompt the AI to try using a revive even if all of its actual pokemon are healthy. Usually the game identifies null slots by looking at their species and comparing it to SPECIES_NONE and SPECIES_EGG. Missiri's "fix" just makes the AI veto ever using a revive if the lead Pokemon has HP left if I'm reading it right.
     
    247
    Posts
    6
    Years
    • Seen May 2, 2024
    Bit-shifting something by 0 to the right means that statement evaluates as just itself. You can read that if statement as if the ">> 0" bit wasn't there at all, since integers and booleans are interchangeable; any non-zero value will evaluate as true. (It is probably intended to be one greater than, but it's more or less equivalent either way.)

    I suppose that makes sense. I didn't think of it that way.

    I have a guess as to a potential problem here: you're looping through the enemy party from 0 to PARTY_SIZE, looking for a Pokemon with 0 HP. This isn't something you can blindly do in a general case, because PARTY_SIZE is just a constant 6, and there are trainers with less than 6 pokemon; an empty teamslot has 0 HP, and will prompt the AI to try using a revive even if all of its actual pokemon are healthy. Usually the game identifies null slots by looking at their species and comparing it to SPECIES_NONE and SPECIES_EGG. Missiri's "fix" just makes the AI veto ever using a revive if the lead Pokemon has HP left if I'm reading it right.

    If my most recent test with a clean pret project ran into the same bug, I would probably agree with you. However, I tested the code against the normal Roxanne gym battle, where she has 3 Pokémon. If what you're saying is true, she should have used the revive on her first turn, as there would have been 3 empty slots to trigger a 0-hp check. But in my test, Roxanne would not use a revive until one of her Pokémon were fainted.
     
    2
    Posts
    8
    Years
    • Seen Mar 7, 2023
    I'm missiri. Im not very good at coding and I usually fumble my way through. heck I didnt even know I still had an account on here since Im rarely ever on until I just tried to create a new one. but heres a video demonstrating the very issue that I sought to fix. I know I followed the tutorial to the very letter because I copy pasted and removed the ← ← ← ← ← ← ← ← and the words following it. the only other changes I made to your code was to change a few pieces that needed it like FD 3E to FD 35 because pret doesnt go up to FD 3D. on the expansion no modifications are needed. it just works. but on base pret it doesnt Im sorry to say. I've tested it extensively. and Ive made no mistakes in copying your work. with the check I added it does indeed function. and DoesntKnowHowToPlay is correct. though I made a typo I set it to veto unless at least the first pokemon is fainted. so it works with my fix but doesnt without it at least any of the times Ive tried on base pret. Im not trying to say you dont know what youre doing or anything. I actually love what you did. its something the game should've had from the start and its just a really neat feature in general and i thank you for it. but it didnt work for me just as it didnt for diego. so I sought to remedy it with the tiny bit of understanding of decomps that I have.

    https://drive.google.com/file/d/1F5A8xPLSg_LHMXblsj8g49gJXSUZuMyr/view?usp=share_link
     
    247
    Posts
    6
    Years
    • Seen May 2, 2024
    After testing a bit with missiri's repo, I think DoesntKnowHowToPlay was right. When I made sure the loop accounted for empty slots in the enemy party, it worked correctly. I have updated the tutorial to reflect this. I still don't get why my repo doesn't need that extra check to avoid empty slots, but it is what it is.
     
    Back
    Top