Fixed Ice Face, implemented tests (#5171)

* Fixed Ice Face, implemented tests

* Fixed agbcc and bad battle mon looping

* Fixed the ShouldChangeFormInWeather function again

* Cleaned up End of Turn weather form changes, simplified Ice Face

---------

Co-authored-by: Hedara <hedara90@gmail.com>
This commit is contained in:
hedara90 2024-08-15 13:51:39 +02:00 committed by GitHub
parent 18980b20a3
commit 45f10d734f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 146 additions and 42 deletions

View file

@ -763,7 +763,6 @@ struct BattleStruct
bool8 effectsBeforeUsingMoveDone:1; // Mega Evo and Focus Punch/Shell Trap effects.
u8 targetsDone[MAX_BATTLERS_COUNT]; // Each battler as a bit.
u16 overwrittenAbilities[MAX_BATTLERS_COUNT]; // abilities overwritten during battle (keep separate from battle history in case of switching)
bool8 allowedToChangeFormInWeather[PARTY_SIZE][NUM_BATTLE_SIDES]; // For each party member and side, used by Ice Face.
u8 battleBondTransformed[NUM_BATTLE_SIDES]; // Bitfield for each party.
u8 storedHealingWish:4; // Each battler as a bit.
u8 storedLunarDance:4; // Each battler as a bit.

View file

@ -3114,8 +3114,6 @@ static void BattleStartClearSetData(void)
gBattleStruct->itemLost[B_SIDE_PLAYER][i].originalItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
gBattleStruct->itemLost[B_SIDE_OPPONENT][i].originalItem = GetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM);
gPartyCriticalHits[i] = 0;
gBattleStruct->allowedToChangeFormInWeather[i][B_SIDE_PLAYER] = FALSE;
gBattleStruct->allowedToChangeFormInWeather[i][B_SIDE_OPPONENT] = FALSE;
}
gBattleStruct->swapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky

View file

@ -1671,7 +1671,6 @@ enum
ENDTURN_ION_DELUGE,
ENDTURN_FAIRY_LOCK,
ENDTURN_RETALIATE,
ENDTURN_WEATHER_FORM,
ENDTURN_STATUS_HEAL,
ENDTURN_RAINBOW,
ENDTURN_SEA_OF_FIRE,
@ -2171,18 +2170,6 @@ u8 DoFieldEndTurnEffects(void)
gSideTimers[B_SIDE_OPPONENT].retaliateTimer--;
gBattleStruct->turnCountersTracker++;
break;
case ENDTURN_WEATHER_FORM:
for (i = 0; i < gBattlersCount; i++)
{
if (AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, i, 0, 0, 0))
{
effect++;
break;
}
}
if (effect == 0)
gBattleStruct->turnCountersTracker++;
break;
case ENDTURN_STATUS_HEAL:
for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; gBattlerAttacker++)
{
@ -3894,21 +3881,6 @@ static const u16 sWeatherFlagsInfo[][3] =
[ENUM_WEATHER_FOG] = {B_WEATHER_FOG_TEMPORARY, B_WEATHER_FOG_PERMANENT, HOLD_EFFECT_NONE},
};
static void ShouldChangeFormInWeather(u32 battler)
{
int i;
int side = GetBattlerSide(battler);
struct Pokemon *party = GetSideParty(side);
for (i = 0; i < PARTY_SIZE; i++)
{
if (GetMonData(&party[i], MON_DATA_SPECIES) == SPECIES_EISCUE_NOICE_FACE)
gBattleStruct->allowedToChangeFormInWeather[i][side] = TRUE;
else
gBattleStruct->allowedToChangeFormInWeather[i][side] = FALSE;
}
}
bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility)
{
u16 battlerAbility = GetBattlerAbility(battler);
@ -3922,7 +3894,6 @@ bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility)
else if (B_ABILITY_WEATHER < GEN_6 && viaAbility && !(gBattleWeather & sWeatherFlagsInfo[weatherEnumId][1]))
{
gBattleWeather = (sWeatherFlagsInfo[weatherEnumId][0] | sWeatherFlagsInfo[weatherEnumId][1]);
ShouldChangeFormInWeather(battler);
return TRUE;
}
else if (!(gBattleWeather & (sWeatherFlagsInfo[weatherEnumId][0] | sWeatherFlagsInfo[weatherEnumId][1])))
@ -3932,7 +3903,6 @@ bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility)
gWishFutureKnock.weatherDuration = 8;
else
gWishFutureKnock.weatherDuration = 5;
ShouldChangeFormInWeather(battler);
return TRUE;
}
return FALSE;
@ -4961,6 +4931,17 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
effect++;
}
break;
case ABILITY_ICE_FACE:
if (IsBattlerWeatherAffected(battler, B_WEATHER_HAIL | B_WEATHER_SNOW)
&& gBattleMons[battler].species == SPECIES_EISCUE_NOICE_FACE
&& !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED))
{
// TODO: Convert this to a proper FORM_CHANGE type.
gBattleMons[battler].species = SPECIES_EISCUE_ICE_FACE;
BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3);
effect++;
}
break;
}
break;
case ABILITYEFFECT_ENDTURN:
@ -6285,11 +6266,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_ICE_FACE:
if (IsBattlerWeatherAffected(battler, B_WEATHER_HAIL | B_WEATHER_SNOW)
&& gBattleMons[battler].species == SPECIES_EISCUE_NOICE_FACE
&& !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)
&& gBattleStruct->allowedToChangeFormInWeather[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)])
&& !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED))
{
// TODO: Convert this to a proper FORM_CHANGE type.
gBattleStruct->allowedToChangeFormInWeather[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)] = FALSE;
gBattleMons[battler].species = SPECIES_EISCUE_ICE_FACE;
BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3);
effect++;

View file

@ -1,9 +1,137 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Ice Face blocks physical moves, changing Eiscue into its Noice Face form"); // Include Special move in test
TO_DO_BATTLE_TEST("Ice Face is restored if hail or snow begins while Noice Face Eiscue is out");
TO_DO_BATTLE_TEST("Ice Face is restored if Noice Face Eiscue is sent in while hail or snow is active");
TO_DO_BATTLE_TEST("Ice Face is not restored if Eiscue changes into Noice Face form while there's already hail");
TO_DO_BATTLE_TEST("Ice Face form change persists after switching out");
TO_DO_BATTLE_TEST("Ice Face doesn't transform Eiscue if Cloud Nine/Air Lock is on the field");
SINGLE_BATTLE_TEST("Ice Face blocks physical moves, changing Eiscue into its Noice Face form")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
PLAYER(SPECIES_EISCUE);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_TACKLE); }
} SCENE {
ABILITY_POPUP(player, ABILITY_ICE_FACE);
MESSAGE("Eiscue transformed!");
}
}
SINGLE_BATTLE_TEST("Ice Face does not block special moves, Eiscue stays in Ice Face form")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
ASSUME(gMovesInfo[MOVE_EMBER].category == DAMAGE_CATEGORY_SPECIAL);
PLAYER(SPECIES_EISCUE);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_EMBER); }
} SCENE {
NOT ABILITY_POPUP(player, ABILITY_ICE_FACE);
}
}
SINGLE_BATTLE_TEST("Ice Face is restored if hail or snow begins while Noice Face Eiscue is out")
{
u32 move;
PARAMETRIZE { move = MOVE_SNOWSCAPE; }
PARAMETRIZE { move = MOVE_HAIL; }
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
ASSUME(gMovesInfo[MOVE_SNOWSCAPE].effect == EFFECT_SNOWSCAPE);
ASSUME(gMovesInfo[MOVE_HAIL].effect == EFFECT_HAIL);
PLAYER(SPECIES_EISCUE);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_TACKLE); }
TURN { MOVE(opponent, move); }
TURN { MOVE(opponent, MOVE_TACKLE); }
} SCENE {
ABILITY_POPUP(player, ABILITY_ICE_FACE);
MESSAGE("Eiscue transformed!");
ABILITY_POPUP(player, ABILITY_ICE_FACE);
MESSAGE("Eiscue transformed!");
ABILITY_POPUP(player, ABILITY_ICE_FACE);
MESSAGE("Eiscue transformed!");
}
}
SINGLE_BATTLE_TEST("Ice Face is restored if Noice Face Eiscue is sent in while hail or snow is active")
{
u32 move;
PARAMETRIZE { move = MOVE_SNOWSCAPE; }
PARAMETRIZE { move = MOVE_HAIL; }
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
ASSUME(gMovesInfo[MOVE_SNOWSCAPE].effect == EFFECT_SNOWSCAPE);
ASSUME(gMovesInfo[MOVE_HAIL].effect == EFFECT_HAIL);
PLAYER(SPECIES_EISCUE);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_TACKLE); }
TURN { SWITCH(player, 1); MOVE(opponent, move); }
TURN { SWITCH(player, 0); MOVE(opponent, MOVE_TACKLE); }
} SCENE {
ABILITY_POPUP(player, ABILITY_ICE_FACE);
MESSAGE("Eiscue transformed!");
ABILITY_POPUP(player, ABILITY_ICE_FACE);
MESSAGE("Eiscue transformed!");
ABILITY_POPUP(player, ABILITY_ICE_FACE);
MESSAGE("Eiscue transformed!");
}
}
SINGLE_BATTLE_TEST("Ice Face is not restored if Eiscue changes into Noice Face form while there's already hail or snow")
{
u32 move;
PARAMETRIZE { move = MOVE_SNOWSCAPE; }
PARAMETRIZE { move = MOVE_HAIL; }
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
ASSUME(gMovesInfo[MOVE_SNOWSCAPE].effect == EFFECT_SNOWSCAPE);
ASSUME(gMovesInfo[MOVE_HAIL].effect == EFFECT_HAIL);
PLAYER(SPECIES_EISCUE) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, move); MOVE(opponent, MOVE_TACKLE); }
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_TACKLE); }
} SCENE {
ABILITY_POPUP(player, ABILITY_ICE_FACE);
MESSAGE("Eiscue transformed!");
MESSAGE("Eiscue used Celebrate!");
MESSAGE("Eiscue fainted!");
}
}
SINGLE_BATTLE_TEST("Ice Face form change persists after switching out")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
PLAYER(SPECIES_EISCUE) { HP(1); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_TACKLE); }
TURN { SWITCH(player, 1); MOVE(opponent, MOVE_CELEBRATE); }
TURN { SWITCH(player, 0); MOVE(opponent, MOVE_TACKLE); SEND_OUT(player, 1); }
} SCENE {
ABILITY_POPUP(player, ABILITY_ICE_FACE);
MESSAGE("Eiscue transformed!");
MESSAGE("Eiscue fainted!");
}
}
SINGLE_BATTLE_TEST("Ice Face doesn't transform Eiscue if Cloud Nine/Air Lock is on the field")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
PLAYER(SPECIES_EISCUE) { HP(1); }
OPPONENT(SPECIES_RAYQUAZA) { Ability(ABILITY_AIR_LOCK); }
} WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_TACKLE); }
TURN { MOVE(player, MOVE_SNOWSCAPE); MOVE(opponent, MOVE_TACKLE); }
} SCENE {
ABILITY_POPUP(player, ABILITY_ICE_FACE);
MESSAGE("Eiscue transformed!");
MESSAGE("Eiscue fainted!");
}
}