mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-12-26 11:44:17 +01:00
Fix volt switch breaking ace pokemon
This commit is contained in:
parent
ff088752e7
commit
896b575c07
@ -3055,7 +3055,7 @@ BattleScript_EffectHitEscape:
|
||||
jumpifbyte CMP_NOT_EQUAL gBattleOutcome 0, BattleScript_HitEscapeEnd
|
||||
jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_HitEscapeEnd
|
||||
jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_HitEscapeEnd
|
||||
jumpifemergencyexited BS_TARGET, BattleScript_HitEscapeEnd
|
||||
jumpifemergencyexited BS_TARGET, BattleScript_HitEscapeEnd
|
||||
openpartyscreen BS_ATTACKER, BattleScript_HitEscapeEnd
|
||||
switchoutabilities BS_ATTACKER
|
||||
waitstate
|
||||
|
@ -643,6 +643,7 @@ struct BattleStruct
|
||||
struct StolenItem itemStolen[PARTY_SIZE]; // Player's team that had items stolen (two bytes per party member)
|
||||
u8 blunderPolicy:1; // should blunder policy activate
|
||||
u8 swapDamageCategory:1; // Photon Geyser, Shell Side Arm, Light That Burns the Sky
|
||||
u8 forcedSwitch:4; // For each battler
|
||||
u8 ballSpriteIds[2]; // item gfx, window gfx
|
||||
u8 stickyWebUser;
|
||||
u8 appearedInBattle; // Bitfield to track which Pokemon appeared in battle. Used for Burmy's form change
|
||||
|
@ -27,6 +27,15 @@ static bool32 AiExpectsToFaintPlayer(void);
|
||||
static bool32 AI_ShouldHeal(u32 healAmount);
|
||||
static bool32 AI_OpponentCanFaintAiWithMod(u32 healAmount);
|
||||
|
||||
static bool32 isAceMon(u32 battlerId, u32 monPartyId)
|
||||
{
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||
&& !(gBattleStruct->forcedSwitch)
|
||||
&& monPartyId == CalculateEnemyPartyCount()-1)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void GetAIPartyIndexes(u32 battlerId, s32 *firstId, s32 *lastId)
|
||||
{
|
||||
if (BATTLE_TWO_VS_ONE_OPPONENT && (battlerId & BIT_SIDE) == B_SIDE_OPPONENT)
|
||||
@ -109,8 +118,7 @@ static bool8 ShouldSwitchIfWonderGuard(void)
|
||||
continue;
|
||||
if (i == gBattlerPartyIndexes[gActiveBattler])
|
||||
continue;
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||
&& i == (CalculateEnemyPartyCount()-1))
|
||||
if (isAceMon(gActiveBattler, i))
|
||||
continue;
|
||||
|
||||
for (opposingBattler = GetBattlerAtPosition(opposingPosition), j = 0; j < MAX_MON_MOVES; j++)
|
||||
@ -202,8 +210,7 @@ static bool8 FindMonThatAbsorbsOpponentsMove(void)
|
||||
continue;
|
||||
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||
continue;
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||
&& i == (CalculateEnemyPartyCount()-1))
|
||||
if (isAceMon(gActiveBattler, i))
|
||||
continue;
|
||||
|
||||
|
||||
@ -283,9 +290,8 @@ static bool8 ShouldSwitchIfGameStatePrompt(void)
|
||||
|
||||
for (i = firstId; i < lastId; i++)
|
||||
{
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||
&& i == (CalculateEnemyPartyCount()-1))
|
||||
break;
|
||||
if (isAceMon(gActiveBattler, i))
|
||||
continue;
|
||||
|
||||
//Look for mon in party that is able to be switched into and has ability that sets terrain
|
||||
if (GetMonData(&party[i], MON_DATA_HP) != 0
|
||||
@ -576,8 +582,7 @@ static bool8 FindMonWithFlagsAndSuperEffective(u16 flags, u8 moduloPercent)
|
||||
continue;
|
||||
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||
continue;
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||
&& i == (CalculateEnemyPartyCount()-1))
|
||||
if (isAceMon(gActiveBattler, i))
|
||||
continue;
|
||||
|
||||
|
||||
@ -619,6 +624,7 @@ bool32 ShouldSwitch(void)
|
||||
struct Pokemon *party;
|
||||
s32 i;
|
||||
s32 availableToSwitch;
|
||||
bool32 hasAceMon = FALSE;
|
||||
|
||||
if (gBattleMons[gActiveBattler].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION))
|
||||
return FALSE;
|
||||
@ -668,15 +674,22 @@ bool32 ShouldSwitch(void)
|
||||
continue;
|
||||
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||
continue;
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||
&& i == (CalculateEnemyPartyCount()-1))
|
||||
if (isAceMon(gActiveBattler, i))
|
||||
{
|
||||
hasAceMon = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
availableToSwitch++;
|
||||
}
|
||||
|
||||
if (availableToSwitch == 0)
|
||||
return FALSE;
|
||||
{
|
||||
if (hasAceMon) // If the ace mon is the only available mon, use it
|
||||
availableToSwitch++;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//NOTE: The sequence of the below functions matter! Do not change unless you have carefully considered the outcome.
|
||||
//Since the order is sequencial, and some of these functions prompt switch to specific party members.
|
||||
@ -758,8 +771,7 @@ void AI_TrySwitchOrUseItem(void)
|
||||
continue;
|
||||
if (monToSwitchId == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||
continue;
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||
&& monToSwitchId == (CalculateEnemyPartyCount()-1))
|
||||
if (isAceMon(gActiveBattler, monToSwitchId))
|
||||
continue;
|
||||
|
||||
break;
|
||||
@ -916,7 +928,7 @@ u8 GetMostSuitableMonToSwitchInto(void)
|
||||
s32 lastId = 0; // + 1
|
||||
struct Pokemon *party;
|
||||
s32 i, j, aliveCount = 0;
|
||||
u8 invalidMons = 0;
|
||||
u32 invalidMons = 0, aceMonId = PARTY_SIZE;
|
||||
|
||||
if (*(gBattleStruct->monToSwitchIntoId + gActiveBattler) != PARTY_SIZE)
|
||||
return *(gBattleStruct->monToSwitchIntoId + gActiveBattler);
|
||||
@ -958,12 +970,19 @@ u8 GetMostSuitableMonToSwitchInto(void)
|
||||
|| gBattlerPartyIndexes[battlerIn2] == i
|
||||
|| i == *(gBattleStruct->monToSwitchIntoId + battlerIn1)
|
||||
|| i == *(gBattleStruct->monToSwitchIntoId + battlerIn2)
|
||||
|| (GetMonAbility(&party[i]) == ABILITY_TRUANT && IsTruantMonVulnerable(gActiveBattler, opposingBattler)) // While not really invalid per say, not really wise to switch into this mon.
|
||||
|| ((AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON)
|
||||
&& i == (CalculateEnemyPartyCount() - 1))) //Save Ace Pokemon for last
|
||||
|| (GetMonAbility(&party[i]) == ABILITY_TRUANT && IsTruantMonVulnerable(gActiveBattler, opposingBattler))) // While not really invalid per say, not really wise to switch into this mon.)
|
||||
{
|
||||
invalidMons |= gBitTable[i];
|
||||
}
|
||||
else if (isAceMon(gActiveBattler, i))// Save Ace Pokemon for last.
|
||||
{
|
||||
aceMonId = i;
|
||||
invalidMons |= gBitTable[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
aliveCount++;
|
||||
}
|
||||
}
|
||||
|
||||
bestMonId = GetBestMonBatonPass(party, firstId, lastId, invalidMons, aliveCount);
|
||||
@ -978,6 +997,11 @@ u8 GetMostSuitableMonToSwitchInto(void)
|
||||
if (bestMonId != PARTY_SIZE)
|
||||
return bestMonId;
|
||||
|
||||
// If ace mon is the last available Pokemon and U-Turn/Volt Switch was used - switch to the mon.
|
||||
if (aceMonId != PARTY_SIZE
|
||||
&& (gBattleMoves[gLastUsedMove].effect == EFFECT_HIT_ESCAPE || gBattleMoves[gLastUsedMove].effect == EFFECT_PARTING_SHOT))
|
||||
return aceMonId;
|
||||
|
||||
return PARTY_SIZE;
|
||||
}
|
||||
|
||||
|
@ -6844,6 +6844,7 @@ static void Cmd_switchineffects(void)
|
||||
gBattlerFainted++;
|
||||
}
|
||||
}
|
||||
gBattleStruct->forcedSwitch &= ~(gBitTable[gActiveBattler]);
|
||||
gBattlescriptCurrInstr += 2;
|
||||
}
|
||||
}
|
||||
@ -11410,6 +11411,8 @@ static void Cmd_forcerandomswitch(void)
|
||||
*(gBattleStruct->battlerPartyIndexes + gBattlerTarget) = gBattlerPartyIndexes[gBattlerTarget];
|
||||
gBattlescriptCurrInstr = BattleScript_RoarSuccessSwitch;
|
||||
|
||||
gBattleStruct->forcedSwitch |= gBitTable[gBattlerTarget];
|
||||
|
||||
do
|
||||
{
|
||||
i = Random() % monsCount;
|
||||
|
@ -1706,12 +1706,36 @@ static const struct TrainerMonNoItemCustomMoves sParty_Jessica5[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static const struct TrainerMonItemDefaultMoves sParty_Winston1[] = {
|
||||
static const struct TrainerMonItemCustomMoves sParty_Winston1[] = {
|
||||
{
|
||||
.iv = 0,
|
||||
.lvl = 7,
|
||||
.species = SPECIES_ZIGZAGOON,
|
||||
.heldItem = ITEM_NUGGET
|
||||
.lvl = 10,
|
||||
.species = SPECIES_EMOLGA,
|
||||
.heldItem = ITEM_NONE,
|
||||
.moves = {MOVE_VOLT_SWITCH, MOVE_NONE, MOVE_NONE, MOVE_NONE},
|
||||
},
|
||||
/*
|
||||
{
|
||||
.iv = 0,
|
||||
.lvl = 4,
|
||||
.species = SPECIES_ABRA,
|
||||
.heldItem = ITEM_NONE,
|
||||
.moves = {MOVE_VOLT_SWITCH, MOVE_NONE, MOVE_NONE, MOVE_NONE},
|
||||
},
|
||||
{
|
||||
.iv = 0,
|
||||
.lvl = 8,
|
||||
.species = SPECIES_KADABRA,
|
||||
.heldItem = ITEM_NONE,
|
||||
.moves = {MOVE_VOLT_SWITCH, MOVE_NONE, MOVE_NONE, MOVE_NONE},
|
||||
},
|
||||
*/
|
||||
{
|
||||
.iv = 250,
|
||||
.lvl = 24,
|
||||
.species = SPECIES_ZEBSTRIKA,
|
||||
.heldItem = ITEM_SITRUS_BERRY,
|
||||
.moves = {MOVE_VOLT_SWITCH, MOVE_VOLT_SWITCH, MOVE_VOLT_SWITCH, MOVE_VOLT_SWITCH},
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1641,8 +1641,8 @@ const struct Trainer gTrainers[] = {
|
||||
.trainerName = _("WINSTON"),
|
||||
.items = {ITEM_FULL_RESTORE, ITEM_NONE, ITEM_NONE, ITEM_NONE},
|
||||
.doubleBattle = FALSE,
|
||||
.aiFlags = AI_FLAG_CHECK_BAD_MOVE,
|
||||
.party = ITEM_DEFAULT_MOVES(sParty_Winston1),
|
||||
.aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_ACE_POKEMON,
|
||||
.party = ITEM_CUSTOM_MOVES(sParty_Winston1),
|
||||
},
|
||||
|
||||
[TRAINER_MOLLIE] =
|
||||
|
Loading…
Reference in New Issue
Block a user