- 250
- Posts
- 7
- Years
- Seen Apr 23, 2025
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
charmap.txt
data/battle_scripts_2.s
Then, at the bottom of the file:
include
src
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!
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:
Add this at the bottom:
Code:
.macro usereviveonopponent
various 0, VARIOUS_USE_REVIVE_ON_OPPONENT
.endm
Spoiler:
Add this immediately below "B_ACTIVE_NAME2 = FD 3D @ no Illusion check"
Code:
B_TARGET_OF_REVIVE = FD 3E
Spoiler:
Code:
gBattlescriptsForUsingItem:: @ 82DBD3C
.4byte BattleScript_PlayerUsesItem
.4byte BattleScript_OpponentUsesHealItem @ AI_ITEM_FULL_RESTORE
.4byte BattleScript_OpponentUsesHealItem @ AI_ITEM_HEAL_HP
.4byte BattleScript_OpponentUsesStatusCureItem @ AI_ITEM_CURE_CONDITION
.4byte BattleScript_OpponentUsesXItem @ AI_ITEM_X_STAT
.4byte BattleScript_OpponentUsesGuardSpecs @ AI_ITEM_GUARD_SPECS
.4byte BattleScript_OpponentUsesReviveItem @ AI_ITEM_REVIVE ← ← ← ← ← ← Add this
Code:
BattleScript_OpponentUsesReviveItem::
printstring STRINGID_EMPTYSTRING3
pause 0x30
playse SE_USE_ITEM
printstring STRINGID_TRAINER1USEDITEM
waitmessage 0x40
usereviveonopponent
printstring STRINGID_PKMNSITEMREVIVED
waitmessage 0x40
setbyte sMOVEEND_STATE, 0xF
moveend 0x1, 0x0
finishaction
Spoiler:
include/battle_ai_switch_items.h
include/battle_message.h
include/constants/battle_script_commands.h
include/constants/battle_string_ids.h
Spoiler:
Code:
AI_ITEM_X_STAT,
AI_ITEM_GUARD_SPECS,
AI_ITEM_REVIVE, ← ← ← ← ← ← Add this here
AI_ITEM_NOT_RECOGNIZABLE
Spoiler:
Add immediately below "#define B_TXT_ACTIVE_NAME2 0x3D // no Illusion check"
Code:
#define B_TXT_TARGET_OF_REVIVE 0x3E
Spoiler:
Add immediately below "#define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 104"
Code:
#define VARIOUS_USE_REVIVE_ON_OPPONENT 105
Spoiler:
Add immediately below "#define STRINGID_MICLEBERRYACTIVATES 566"
Also, change BATTLESTRINGS_COUNT from 567 to 568
Code:
#define STRINGID_PKMNSITEMREVIVED 567
src
Spoiler:
src/battle_ai_switch_items.c
src/battle_message.c
src/battle_script_commands.c
src/battle_util.c
Spoiler:
Code:
static u8 GetAI_ItemType(u16 itemId, const u8 *itemEffect)
{
if (itemId == ITEM_FULL_RESTORE)
return AI_ITEM_FULL_RESTORE;
else if(itemEffect[4] & ITEM4_REVIVE) ← ← ← ← ← ← Add this here
return AI_ITEM_REVIVE; ← ← ← ← ← ← Add this here
else if (itemEffect[4] & ITEM4_HEAL_HP)
..................................................
..................................................
.................................................
static bool8 ShouldUseItem(void)
{
...............................
for (i = 0; i < MAX_TRAINER_ITEMS; i++)
{
u8 loop; ← ← ← ← ← ← Add this
u16 item;
............................
if (gDisableStructs[gActiveBattler].isFirstTurn != 0 && gSideTimers[battlerSide].mistTimer == 0)
shouldUse = TRUE;
break;
case AI_ITEM_REVIVE: ← ← ← ← ← ← ← Add this case
for(loop = 0; loop < PARTY_SIZE; loop++)
{
if(GetMonData(&party[loop], MON_DATA_HP) == 0 &&
GetMonData(&party[loop], MON_DATA_SPECIES2) != SPECIES_NONE &&
GetMonData(&party[loop], MON_DATA_SPECIES2) != SPECIES_EGG)
{
shouldUse = TRUE;
break;
}
}
break;
case AI_ITEM_NOT_RECOGNIZABLE:
return FALSE;
Spoiler:
Code:
static const u8 sText_PkmnHungOnWithX[] = _("{B_DEF_NAME_WITH_PREFIX} hung on\nusing its {B_LAST_ITEM}!");
static const u8 sText_PkmnsItemRevived[] = _("{B_TARGET_OF_REVIVE} was revived!"); ← ← ← ← ← ← ← Add this
const u8 gText_EmptyString3[] = _("");
..................................................................
[STRINGID_PKMNHUNGONWITHX - BATTLESTRINGS_TABLE_START] = sText_PkmnHungOnWithX,
[STRINGID_PKMNSITEMREVIVED - BATTLESTRINGS_TABLE_START] = sText_PkmnsItemRevived, ← ← ← ← ← ← ← Add this
[STRINGID_EMPTYSTRING3 - BATTLESTRINGS_TABLE_START] = gText_EmptyString3,
.................................................................
.................................................................
................................................................
u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst)
{
...............................................................
case B_TXT_SCR_ACTIVE_NAME_WITH_PREFIX: // scripting active battlerId name with prefix
HANDLE_NICKNAME_STRING_CASE(gBattleScripting.battler)
break;
case B_TXT_TARGET_OF_REVIVE: ← ← ← ← ← ← Add this case
toCpy = sText_FoePkmnPrefix;
while (*toCpy != EOS)
{
dst[dstID] = *toCpy;
dstID++;
toCpy++;
}
GetMonData(&gEnemyParty[gBattleStruct->wildVictorySong], MON_DATA_NICKNAME, text);
gBattleStruct->wildVictorySong = 0;
StringGet_Nickname(text);
toCpy = text;
break;
case B_TXT_CURRENT_MOVE: // current move name
Spoiler:
Code:
static void Cmd_various(void)
{
.......................................................
gBattlescriptCurrInstr += 7; // exit if loop failed (failsafe)
}
return;
case VARIOUS_USE_REVIVE_ON_OPPONENT: ← ← ← ← ← ← ← ← Add this case at the end of this switch statement
for(i = 0; i < PARTY_SIZE; i++)
{
u16 currentMonMax = GetMonData(&gEnemyParty[i], MON_DATA_MAX_HP);
u16 currentMonHalf = currentMonMax / 2;
if(GetMonData(&gEnemyParty[i], MON_DATA_HP) == 0)
{
gBattleStruct->wildVictorySong = i;
switch(gLastUsedItem)
{
// Half health (revive)
case ITEM_REVIVE:
SetMonData(&gEnemyParty[i], MON_DATA_HP, ¤tMonHalf);
break;
// Full Health (max revive, revival herb)
case ITEM_MAX_REVIVE:
case ITEM_REVIVAL_HERB:
SetMonData(&gEnemyParty[i], MON_DATA_HP, ¤tMonMax);
break;
}
break;
}
}
break;
}
gBattlescriptCurrInstr += 3;
Spoiler:
Code:
void HandleAction_UseItem(void)
{
.............................................
case AI_ITEM_FULL_RESTORE:
case AI_ITEM_HEAL_HP:
case AI_ITEM_REVIVE: ← ← ← ← ← ← ← Add this
break;
Last edited: