I recently saw Petuh 2.0's post on a new type of switching AI, but I found that it was far too manual for my tastes. Therefore, I tried to implement it myself.
This script is copied off of the already existing Wonder Guard check script:
It works perfectly (After the ellipses is just the code for selecting which new Pokemon to send out). Essentially, if you send out a Pokemon, and if the opponent can't do Super Effective damage, they switch. All I need to do now is make changes so that if YOU are the one using a super effective move (and you have to use the move; you can't just have it available), then they switch to their best counter.
This code snippet works as follows: If you have a move which is super effective against the opponent, they switch.
This is where I have hit a wall. This code, I feel, should work. What's supposed to happen is the opponent switches if you use a move that was super effective, the opponent will switch next turn. However, the opponent never switches out. Still a little unsure as to how gLastLandedMoves works, tbh.
NOTE: I simplified the "deciding who to switch to" code to something simpler because the game is pretty good at deciding who to switch to. The old code was specifically about finding a Pokemon with a super-effective move. It didn't take the Pokemon's type into account.
EDIT: I've found something weird. If you implement this script:
Then the opponent will switch whenever their last move is not Move_None. However, if you replace
with
nothing happens. I would assume that the opponent would switch when you use a move that isn't Move_None. However, they just don't. So weird!
EDIT 2: Ok, so I took the original code Petuh 2.0 made and upgraded it for Battle Engine Upgrade usage and it looks like this:
How it works is exactly correct. But in reverse. If the opponent uses a move that does super effective damage to YOU, then THEY switch. I tried switching gActiveBattler to opposingBattler, but the effect stays the same.
If anyone's familiar with this type of hacking and has any ideas, please let me know. Thanks!
This script is copied off of the already existing Wonder Guard check script:
Code:
u8 opposingPosition;
u8 opposingBattler;
s32 i, j;
s32 firstId;
s32 lastId; // + 1
struct Pokemon *party = NULL;
u16 move;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
return FALSE;
opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(gActiveBattler));
// Check if Pokemon has a super effective move.
for (opposingBattler = GetBattlerAtPosition(opposingPosition), i = 0; i < MAX_MON_MOVES; i++)
{
move = gBattleMons[gActiveBattler].moves[i];
if (move != MOVE_NONE)
{
// If Attacker has super effective move, don't switch.
if (AI_GetTypeEffectiveness(move, gActiveBattler, opposingBattler) >= UQ_4_12(2.0))
return FALSE;
}
}
...
This code snippet works as follows: If you have a move which is super effective against the opponent, they switch.
Code:
static bool8 EnemyMonHasSpecificSuperEffectiveRevealedMove(void)
{
u8 opposingPosition;
u8 opposingBattler;
s32 i, j;
s32 firstId;
s32 lastId; // + 1
struct Pokemon *party = NULL;
u16 move;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
return FALSE;
opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(gActiveBattler));
// Check if Pokemon has a super effective move.
for (opposingBattler = GetBattlerAtPosition(opposingPosition), i = 0; i < MAX_MON_MOVES; i++)
{
move = gBattleMons[opposingBattler].moves[i];
if (move != MOVE_NONE)
{
if (AI_GetTypeEffectiveness(move, opposingBattler, gActiveBattler) >= UQ_4_12(2.0))
{
GetAIPartyIndexes(gActiveBattler, &firstId, &lastId);
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
// Find a Pokemon in the party that has a super effective move.
for (i = firstId; i < lastId; i++)
{
if (GetMonData(&party[i], MON_DATA_HP) == 0)
continue;
if (GetMonData(&party[i], MON_DATA_SPECIES2) == SPECIES_NONE)
continue;
if (GetMonData(&party[i], MON_DATA_SPECIES2) == SPECIES_EGG)
continue;
if (i == gBattlerPartyIndexes[gActiveBattler])
continue;
for (opposingBattler = GetBattlerAtPosition(opposingPosition), j = 0; j < MAX_MON_MOVES; j++)
{
move = GetMonData(&party[i], MON_DATA_MOVE1 + j);
if (move != MOVE_NONE)
{
if (AI_GetTypeEffectiveness(move, gActiveBattler, opposingBattler) >= UQ_4_12(2.0) && Random() % 3 < 2)
{
// We found a mon.
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = i;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
}
}
}
}
}
}
return FALSE;
}
This is where I have hit a wall. This code, I feel, should work. What's supposed to happen is the opponent switches if you use a move that was super effective, the opponent will switch next turn. However, the opponent never switches out. Still a little unsure as to how gLastLandedMoves works, tbh.
Code:
static bool8 EnemyMonHasSpecificSuperEffectiveRevealedMove(void)
{
u8 opposingPosition;
u8 opposingBattler;
s32 i, j;
s32 firstId;
s32 lastId; // + 1
struct Pokemon *party = NULL;
u16 move;
opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(gActiveBattler));
opposingBattler = GetBattlerAtPosition(opposingPosition);
if (gLastLandedMoves[opposingBattler] == 0)
return FALSE;
if (gLastLandedMoves[opposingBattler] == 0xFFFF)
return FALSE;
if (gBattleMoves[gLastLandedMoves[opposingBattler]].power == 0)
return FALSE;
move = gLastLandedMoves[opposingBattler];
if (move != MOVE_NONE)
{
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = PARTY_SIZE;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
return FALSE;
}
EDIT: I've found something weird. If you implement this script:
Code:
static bool8 EnemyMonHasSpecificSuperEffectiveRevealedMove(void)
{
u8 opposingPosition;
u8 opposingBattler;
s32 i, j;
s32 firstId;
s32 lastId; // + 1
struct Pokemon *party = NULL;
u16 move;
opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(gActiveBattler));
opposingBattler = GetBattlerAtPosition(opposingPosition);
move = gLastLandedMoves[opposingBattler];
if (move!=MOVE_NONE)
{
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = PARTY_SIZE;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
return FALSE;
}
Code:
move = gLastLandedMoves[opposingBattler];
Code:
move = gLastLandedMoves[gActiveBattler];
EDIT 2: Ok, so I took the original code Petuh 2.0 made and upgraded it for Battle Engine Upgrade usage and it looks like this:
Code:
static bool8 EnemyMonHasSpecificSuperEffectiveRevealedMove(void)
{
u8 opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(gActiveBattler));
u8 opposingBattler = GetBattlerAtPosition(opposingPosition);
CalcPartyMonTypeEffectivenessMultiplier(gLastLandedMoves[gActiveBattler], gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].ability);
if (gMoveResultFlags & MOVE_RESULT_SUPER_EFFECTIVE) {
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = PARTY_SIZE;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
return FALSE;
}
If anyone's familiar with this type of hacking and has any ideas, please let me know. Thanks!
Last edited: