Fixes Trace turn order (#4941)
* Fixes Trace turn order * Update battle_script_commands.c * Update test/battle/ability/trace.c --------- Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>
This commit is contained in:
parent
0613af5604
commit
7b6ff1b560
@ -196,10 +196,10 @@ struct SpecialStatus
|
||||
u8 statLowered:1;
|
||||
u8 lightningRodRedirected:1;
|
||||
u8 restoredBattlerSprite: 1;
|
||||
u8 traced:1;
|
||||
u8 faintedHasReplacement:1;
|
||||
u8 focusBanded:1;
|
||||
u8 focusSashed:1;
|
||||
u8 unused:1;
|
||||
// End of byte
|
||||
u8 sturdied:1;
|
||||
u8 stormDrainRedirected:1;
|
||||
|
||||
@ -29,17 +29,15 @@
|
||||
#define ABILITYEFFECT_IMMUNITY 6
|
||||
#define ABILITYEFFECT_SYNCHRONIZE 7
|
||||
#define ABILITYEFFECT_ATK_SYNCHRONIZE 8
|
||||
#define ABILITYEFFECT_TRACE1 9
|
||||
#define ABILITYEFFECT_TRACE2 10
|
||||
#define ABILITYEFFECT_MOVE_END_OTHER 11
|
||||
#define ABILITYEFFECT_NEUTRALIZINGGAS 12
|
||||
#define ABILITYEFFECT_FIELD_SPORT 13 // Only used if B_SPORT_TURNS >= GEN_6
|
||||
#define ABILITYEFFECT_ON_WEATHER 14
|
||||
#define ABILITYEFFECT_ON_TERRAIN 15
|
||||
#define ABILITYEFFECT_SWITCH_IN_TERRAIN 16
|
||||
#define ABILITYEFFECT_SWITCH_IN_WEATHER 17
|
||||
#define ABILITYEFFECT_OPPORTUNIST 18
|
||||
#define ABILITYEFFECT_SWITCH_IN_STATUSES 19
|
||||
#define ABILITYEFFECT_MOVE_END_OTHER 9
|
||||
#define ABILITYEFFECT_NEUTRALIZINGGAS 10
|
||||
#define ABILITYEFFECT_FIELD_SPORT 11 // Only used if B_SPORT_TURNS >= GEN_6
|
||||
#define ABILITYEFFECT_ON_WEATHER 12
|
||||
#define ABILITYEFFECT_ON_TERRAIN 13
|
||||
#define ABILITYEFFECT_SWITCH_IN_TERRAIN 14
|
||||
#define ABILITYEFFECT_SWITCH_IN_WEATHER 15
|
||||
#define ABILITYEFFECT_OPPORTUNIST 16
|
||||
#define ABILITYEFFECT_SWITCH_IN_STATUSES 17
|
||||
// Special cases
|
||||
#define ABILITYEFFECT_MUD_SPORT 252 // Only used if B_SPORT_TURNS >= GEN_6
|
||||
#define ABILITYEFFECT_WATER_SPORT 253 // Only used if B_SPORT_TURNS >= GEN_6
|
||||
|
||||
@ -4116,8 +4116,6 @@ static void TryDoEventsBeforeFirstTurn(void)
|
||||
if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, gBattlerAttacker, 0, 0, 0) != 0)
|
||||
return;
|
||||
}
|
||||
if (AbilityBattleEffects(ABILITYEFFECT_TRACE1, 0, 0, 0, 0) != 0)
|
||||
return;
|
||||
// Check all switch in items having effect from the fastest mon to slowest.
|
||||
while (gBattleStruct->switchInItemsCounter < gBattlersCount)
|
||||
{
|
||||
|
||||
@ -7140,8 +7140,7 @@ bool32 DoSwitchInAbilities(u32 battler)
|
||||
return (TryPrimalReversion(battler)
|
||||
|| AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0)
|
||||
|| (gBattleWeather & B_WEATHER_ANY && WEATHER_HAS_EFFECT && AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0))
|
||||
|| (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY && AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0))
|
||||
|| AbilityBattleEffects(ABILITYEFFECT_TRACE2, 0, 0, 0, 0));
|
||||
|| (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY && AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0)));
|
||||
}
|
||||
|
||||
static void UpdateSentMonFlags(u32 battler)
|
||||
@ -7289,6 +7288,14 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler)
|
||||
|
||||
gDisableStructs[battler].truantSwitchInHack = 0;
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (i != battler
|
||||
&& GetBattlerAbility(i) == ABILITY_TRACE
|
||||
&& AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, i, 0, 0, 0))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (DoSwitchInAbilities(battler) || ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, battler, FALSE))
|
||||
return TRUE;
|
||||
else if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0))
|
||||
@ -9226,7 +9233,6 @@ static void Cmd_various(void)
|
||||
case VARIOUS_RESET_SWITCH_IN_ABILITY_BITS:
|
||||
{
|
||||
VARIOUS_ARGS();
|
||||
gSpecialStatuses[battler].traced = FALSE;
|
||||
gSpecialStatuses[battler].switchInAbilityDone = FALSE;
|
||||
break;
|
||||
}
|
||||
@ -9459,7 +9465,6 @@ static void Cmd_various(void)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, 0, 0, 0);
|
||||
AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0);
|
||||
AbilityBattleEffects(ABILITYEFFECT_TRACE2, battler, 0, 0, 0);
|
||||
AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4247,6 +4247,50 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
gBattleScripting.battler = battler;
|
||||
switch (gLastUsedAbility)
|
||||
{
|
||||
case ABILITY_TRACE:
|
||||
{
|
||||
u32 chosenTarget;
|
||||
u32 target1;
|
||||
u32 target2;
|
||||
|
||||
if (gSpecialStatuses[battler].switchInAbilityDone)
|
||||
break;
|
||||
if (gBattleResources->flags->flags[battler] & RESOURCE_FLAG_TRACED)
|
||||
break;
|
||||
|
||||
side = (BATTLE_OPPOSITE(GetBattlerPosition(battler))) & BIT_SIDE;
|
||||
target1 = GetBattlerAtPosition(side);
|
||||
target2 = GetBattlerAtPosition(side + BIT_FLANK);
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
{
|
||||
if (!gAbilitiesInfo[gBattleMons[target1].ability].cantBeTraced && gBattleMons[target1].hp != 0
|
||||
&& !gAbilitiesInfo[gBattleMons[target2].ability].cantBeTraced && gBattleMons[target2].hp != 0)
|
||||
chosenTarget = GetBattlerAtPosition((RandomPercentage(RNG_TRACE, 50) * 2) | side), effect++;
|
||||
else if (!gAbilitiesInfo[gBattleMons[target1].ability].cantBeTraced && gBattleMons[target1].hp != 0)
|
||||
chosenTarget = target1, effect++;
|
||||
else if (!gAbilitiesInfo[gBattleMons[target2].ability].cantBeTraced && gBattleMons[target2].hp != 0)
|
||||
chosenTarget = target2, effect++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!gAbilitiesInfo[gBattleMons[target1].ability].cantBeTraced && gBattleMons[target1].hp != 0)
|
||||
chosenTarget = target1, effect++;
|
||||
}
|
||||
|
||||
if (effect != 0)
|
||||
{
|
||||
BattleScriptPushCursorAndCallback(BattleScript_TraceActivatesEnd3);
|
||||
gBattleResources->flags->flags[battler] &= ~RESOURCE_FLAG_TRACED;
|
||||
gBattleStruct->tracedAbility[battler] = gLastUsedAbility = gBattleMons[chosenTarget].ability;
|
||||
RecordAbilityBattle(chosenTarget, gLastUsedAbility); // Record the opposing battler has this ability
|
||||
battler = gBattlerAbility = gBattleScripting.battler = battler;
|
||||
|
||||
PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, chosenTarget, gBattlerPartyIndexes[chosenTarget])
|
||||
PREPARE_ABILITY_BUFFER(gBattleTextBuff2, gLastUsedAbility)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ABILITY_IMPOSTER:
|
||||
if (IsBattlerAlive(BATTLE_OPPOSITE(battler))
|
||||
&& !(gBattleMons[BATTLE_OPPOSITE(battler)].status2 & (STATUS2_TRANSFORMED | STATUS2_SUBSTITUTE))
|
||||
@ -4584,13 +4628,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
effect++;
|
||||
}
|
||||
break;
|
||||
case ABILITY_TRACE:
|
||||
if (!(gSpecialStatuses[battler].traced))
|
||||
{
|
||||
gBattleResources->flags->flags[battler] |= RESOURCE_FLAG_TRACED;
|
||||
gSpecialStatuses[battler].traced = TRUE;
|
||||
}
|
||||
break;
|
||||
case ABILITY_CLOUD_NINE:
|
||||
case ABILITY_AIR_LOCK:
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone)
|
||||
@ -5981,48 +6018,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ABILITYEFFECT_TRACE1:
|
||||
case ABILITYEFFECT_TRACE2:
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (gBattleMons[i].ability == ABILITY_TRACE && (gBattleResources->flags->flags[i] & RESOURCE_FLAG_TRACED))
|
||||
{
|
||||
u32 chosenTarget;
|
||||
u32 side = (BATTLE_OPPOSITE(GetBattlerPosition(i))) & BIT_SIDE; // side of the opposing Pokémon
|
||||
u32 target1 = GetBattlerAtPosition(side);
|
||||
u32 target2 = GetBattlerAtPosition(side + BIT_FLANK);
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
{
|
||||
if (!gAbilitiesInfo[gBattleMons[target1].ability].cantBeTraced && gBattleMons[target1].hp != 0
|
||||
&& !gAbilitiesInfo[gBattleMons[target2].ability].cantBeTraced && gBattleMons[target2].hp != 0)
|
||||
chosenTarget = GetBattlerAtPosition((RandomPercentage(RNG_TRACE, 50) * 2) | side), effect++;
|
||||
else if (!gAbilitiesInfo[gBattleMons[target1].ability].cantBeTraced && gBattleMons[target1].hp != 0)
|
||||
chosenTarget = target1, effect++;
|
||||
else if (!gAbilitiesInfo[gBattleMons[target2].ability].cantBeTraced && gBattleMons[target2].hp != 0)
|
||||
chosenTarget = target2, effect++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!gAbilitiesInfo[gBattleMons[target1].ability].cantBeTraced && gBattleMons[target1].hp != 0)
|
||||
chosenTarget = target1, effect++;
|
||||
}
|
||||
|
||||
if (effect != 0)
|
||||
{
|
||||
BattleScriptPushCursorAndCallback(BattleScript_TraceActivatesEnd3);
|
||||
gBattleResources->flags->flags[i] &= ~RESOURCE_FLAG_TRACED;
|
||||
gBattleStruct->tracedAbility[i] = gLastUsedAbility = gBattleMons[chosenTarget].ability;
|
||||
RecordAbilityBattle(chosenTarget, gLastUsedAbility); // Record the opposing battler has this ability
|
||||
battler = gBattlerAbility = gBattleScripting.battler = i;
|
||||
|
||||
PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, chosenTarget, gBattlerPartyIndexes[chosenTarget])
|
||||
PREPARE_ABILITY_BUFFER(gBattleTextBuff2, gLastUsedAbility)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ABILITYEFFECT_NEUTRALIZINGGAS:
|
||||
// Prints message only. separate from ABILITYEFFECT_ON_SWITCHIN bc activates before entry hazards
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
|
||||
@ -79,3 +79,20 @@ SINGLE_BATTLE_TEST("Trace will copy an opponent's ability whenever it has the ch
|
||||
MESSAGE("Ralts TRACED Foe Torchic's Blaze!");
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Trace respects the turn order")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_DEOXYS_SPEED) { Speed(40); Ability(ABILITY_PRESSURE); }
|
||||
PLAYER(SPECIES_GARDEVOIR) { Speed(20); Ability(ABILITY_TRACE); }
|
||||
OPPONENT(SPECIES_HIPPOWDON) { Speed(10); Ability(ABILITY_SAND_STREAM); }
|
||||
OPPONENT(SPECIES_DEOXYS_SPEED) { Speed(30); Ability(ABILITY_PRESSURE); }
|
||||
} WHEN {
|
||||
TURN { }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(playerLeft, ABILITY_PRESSURE);
|
||||
ABILITY_POPUP(opponentRight, ABILITY_PRESSURE);
|
||||
ABILITY_POPUP(playerRight, ABILITY_TRACE);
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_SAND_STREAM);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user