Fixes Neutralizing Gas Exits, Weather Abilities and Terrain Effects order (#6435)

This commit is contained in:
PhallenTree 2025-03-16 22:10:20 +00:00 committed by GitHub
parent eaf7549854
commit ddab689a07
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 356 additions and 20 deletions

View File

@ -7687,13 +7687,15 @@ BattleScript_ShedSkinActivates::
end3
BattleScript_ActivateWeatherAbilities:
saveattacker
savetarget
setbyte gBattlerTarget, 0
setbyte gBattlerAttacker, 0
BattleScript_ActivateWeatherAbilities_Loop:
copybyte sBATTLER, gBattlerTarget
copyarraywithindex gBattlerTarget, gBattlerByTurnOrder, gBattlerAttacker, 1
activateweatherchangeabilities BS_TARGET
addbyte gBattlerTarget, 1
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_ActivateWeatherAbilities_Loop
addbyte gBattlerAttacker, 1
jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_ActivateWeatherAbilities_Loop
restoreattacker
restoretarget
return
@ -7987,7 +7989,7 @@ BattleScript_AttackWeakenedByStrongWinds::
waitmessage B_WAIT_TIME_LONG
return
BattleScript_MimicryActivates_End3::
BattleScript_MimicryActivates::
pause B_WAIT_TIME_SHORT
call BattleScript_AbilityPopUp
printstring STRINGID_BATTLERTYPECHANGEDTO
@ -8013,16 +8015,18 @@ BattleScript_SnowWarningActivatesSnow::
end3
BattleScript_ActivateTerrainEffects:
saveattacker
savetarget
setbyte gBattlerTarget, 0
setbyte gBattlerAttacker, 0
BattleScript_ActivateTerrainSeed:
copybyte sBATTLER, gBattlerTarget
copyarraywithindex gBattlerTarget, gBattlerByTurnOrder, gBattlerAttacker, 1
doterrainseed BS_TARGET, BattleScript_ActivateTerrainAbility
removeitem BS_TARGET
BattleScript_ActivateTerrainAbility:
activateterrainchangeabilities BS_TARGET
addbyte gBattlerTarget, 0x1
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_ActivateTerrainSeed
addbyte gBattlerAttacker, 1
jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_ActivateTerrainSeed
restoreattacker
restoretarget
return
@ -9622,11 +9626,14 @@ BattleScript_NeutralizingGasExits::
pause B_WAIT_TIME_SHORT
printstring STRINGID_NEUTRALIZINGGASOVER
waitmessage B_WAIT_TIME_LONG
setbyte gBattlerTarget, 0
setbyte gBattlerAttacker, 0
BattleScript_NeutralizingGasExitsLoop:
copyarraywithindex gBattlerTarget, gBattlerByTurnOrder, gBattlerAttacker, 1
saveattacker
switchinabilities BS_TARGET
addbyte gBattlerTarget, 1
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_NeutralizingGasExitsLoop
restoreattacker
addbyte gBattlerAttacker, 1
jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_NeutralizingGasExitsLoop
restoreattacker
restoretarget
return

View File

@ -443,8 +443,6 @@ extern const u8 BattleScript_WanderingSpiritActivates[];
extern const u8 BattleScript_MirrorArmorReflect[];
extern const u8 BattleScript_GooeyActivates[];
extern const u8 BattleScript_PastelVeilActivates[];
extern const u8 BattleScript_MimicryActivatesEnd3[];
extern const u8 BattleScript_ApplyMimicry[];
extern const u8 BattleScript_AttackerFormChangeEnd3NoPopup[];
extern const u8 BattleScript_AttackerFormChangeWithStringEnd3NoPopup[];
extern const u8 BattleScript_AttackerFormChangeMoveEffect[];
@ -480,7 +478,7 @@ extern const u8 BattleScript_CommanderActivates[];
extern const u8 BattleScript_HospitalityActivates[];
extern const u8 BattleScript_ToxicDebrisActivates[];
extern const u8 BattleScript_EarthEaterActivates[];
extern const u8 BattleScript_MimicryActivates_End3[];
extern const u8 BattleScript_MimicryActivates[];
extern const u8 BattleScript_IceFaceNullsDamage[];
extern const u8 BattleScript_BattlerFormChangeWithStringEnd3[];
extern const u8 BattleScript_DampPreventsAftermath[];

View File

@ -6603,7 +6603,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
gDisableStructs[battler].terrainAbilityDone = TRUE;
ChangeTypeBasedOnTerrain(battler);
gBattlerAbility = gBattleScripting.battler = battler;
BattleScriptPushCursorAndCallback(BattleScript_MimicryActivates_End3);
BattleScriptPushCursorAndCallback(BattleScript_MimicryActivates);
effect++;
}
break;

View File

@ -110,10 +110,10 @@ DOUBLE_BATTLE_TEST("Forecast transforms all Castforms present in weather")
PARAMETRIZE { move = MOVE_HAIL; }
PARAMETRIZE { move = MOVE_SNOWSCAPE; }
GIVEN {
PLAYER(SPECIES_CASTFORM_NORMAL) { Ability(ABILITY_FORECAST); }
PLAYER(SPECIES_CASTFORM_NORMAL) { Ability(ABILITY_FORECAST); }
OPPONENT(SPECIES_CASTFORM_NORMAL) { Ability(ABILITY_FORECAST); }
OPPONENT(SPECIES_CASTFORM_NORMAL) { Ability(ABILITY_FORECAST); }
PLAYER(SPECIES_CASTFORM_NORMAL) { Ability(ABILITY_FORECAST); Speed(10); }
PLAYER(SPECIES_CASTFORM_NORMAL) { Ability(ABILITY_FORECAST); Speed(5); }
OPPONENT(SPECIES_CASTFORM_NORMAL) { Ability(ABILITY_FORECAST); Speed(7); }
OPPONENT(SPECIES_CASTFORM_NORMAL) { Ability(ABILITY_FORECAST); Speed(1); }
} WHEN {
TURN { MOVE(playerRight, move); }
} SCENE {

View File

@ -0,0 +1,273 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Neutralizing Gas activates on switch-in")
{
GIVEN {
PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { }
} SCENE {
ABILITY_POPUP(player, ABILITY_NEUTRALIZING_GAS);
MESSAGE("Neutralizing gas filled the area!");
}
}
SINGLE_BATTLE_TEST("Neutralizing Gas prevents opponent's switch-in ability from activating")
{
GIVEN {
PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); }
OPPONENT(SPECIES_ZEKROM) { Ability(ABILITY_TERAVOLT); }
} WHEN {
TURN { }
} SCENE {
ABILITY_POPUP(player, ABILITY_NEUTRALIZING_GAS);
NONE_OF {
ABILITY_POPUP(opponent, ABILITY_TERAVOLT);
MESSAGE("The opposing Zekrom is radiating a bursting aura!");
}
}
}
DOUBLE_BATTLE_TEST("Neutralizing Gas prevents ally's switch-in ability from activating")
{
GIVEN {
PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); }
PLAYER(SPECIES_ZEKROM) { Ability(ABILITY_TERAVOLT); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { }
} SCENE {
ABILITY_POPUP(playerLeft, ABILITY_NEUTRALIZING_GAS);
NONE_OF {
ABILITY_POPUP(playerRight, ABILITY_TERAVOLT);
MESSAGE("Zekrom is radiating a bursting aura!");
}
}
}
DOUBLE_BATTLE_TEST("Neutralizing Gas ignores all battlers' ability effects")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_SURF].target == MOVE_TARGET_FOES_AND_ALLY);
PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); }
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); }
OPPONENT(SPECIES_LANTURN) { Ability(ABILITY_WATER_ABSORB); }
OPPONENT(SPECIES_BELLIBOLT) { Ability(ABILITY_ELECTROMORPHOSIS); }
} WHEN {
TURN { MOVE(playerLeft, MOVE_SURF); MOVE(playerRight, MOVE_SURF); }
} SCENE {
ABILITY_POPUP(playerLeft, ABILITY_NEUTRALIZING_GAS);
MESSAGE("Neutralizing gas filled the area!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SURF, playerLeft);
NONE_OF {
ABILITY_POPUP(playerRight, ABILITY_TELEPATHY);
ABILITY_POPUP(opponentLeft, ABILITY_WATER_ABSORB);
ABILITY_POPUP(opponentRight, ABILITY_ELECTROMORPHOSIS);
}
HP_BAR(opponentLeft);
HP_BAR(playerRight);
HP_BAR(opponentRight);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SURF, playerRight);
NONE_OF {
ABILITY_POPUP(opponentLeft, ABILITY_WATER_ABSORB);
ABILITY_POPUP(opponentRight, ABILITY_ELECTROMORPHOSIS);
}
HP_BAR(playerLeft);
HP_BAR(opponentLeft);
HP_BAR(opponentRight);
}
}
SINGLE_BATTLE_TEST("Neutralizing Gas ignores multipliers from attacker's ability", s16 damage)
{
u32 ability;
PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; }
PARAMETRIZE { ability = ABILITY_LEVITATE; }
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
PLAYER(SPECIES_WEEZING) { Ability(ability); }
OPPONENT(SPECIES_AZUMARILL) { Ability(ABILITY_HUGE_POWER); }
} WHEN {
TURN { MOVE(opponent, MOVE_TACKLE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Neutralizing Gas ignores multipliers from target's ability", s16 damage)
{
u32 ability;
PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; }
PARAMETRIZE { ability = ABILITY_LEVITATE; }
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].makesContact == TRUE);
ASSUME(gMovesInfo[MOVE_TACKLE].type == TYPE_NORMAL);
PLAYER(SPECIES_WEEZING) { Ability(ability); }
OPPONENT(SPECIES_BEWEAR) { Ability(ABILITY_FLUFFY); }
} WHEN {
TURN { MOVE(player, MOVE_TACKLE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
}
}
DOUBLE_BATTLE_TEST("Neutralizing Gas ignores multipliers from target's ally's ability", s16 damage)
{
u32 ability;
PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; }
PARAMETRIZE { ability = ABILITY_LEVITATE; }
GIVEN {
PLAYER(SPECIES_WEEZING) { Ability(ability); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); }
OPPONENT(SPECIES_CLEFAIRY) { Ability(ABILITY_FRIEND_GUARD); }
} WHEN {
TURN { MOVE(playerLeft, MOVE_TACKLE, target: opponentLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerLeft);
HP_BAR(opponentLeft, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.75), results[1].damage);
}
}
DOUBLE_BATTLE_TEST("Neutralizing Gas ignores multipliers from ally's ability", s16 damage)
{
u32 ability;
PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; }
PARAMETRIZE { ability = ABILITY_LEVITATE; }
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
PLAYER(SPECIES_WEEZING) { Ability(ability); }
PLAYER(SPECIES_WO_CHIEN) { Ability(ABILITY_TABLETS_OF_RUIN); }
OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_TACKLE, target: opponentLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerLeft);
HP_BAR(opponentLeft, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.75), results[1].damage);
}
}
DOUBLE_BATTLE_TEST("Neutralizing Gas leaving the field allows abilities to activate in turn order")
{
u32 speedPlayerRight, speedOppLeft, speedOppRight;
PARAMETRIZE { speedPlayerRight = 5; speedOppLeft = 3; speedOppRight = 2; }
PARAMETRIZE { speedPlayerRight = 3; speedOppLeft = 5; speedOppRight = 2; }
PARAMETRIZE { speedPlayerRight = 2; speedOppLeft = 3; speedOppRight = 5; }
PARAMETRIZE { speedPlayerRight = 3; speedOppLeft = 2; speedOppRight = 5; }
PARAMETRIZE { speedPlayerRight = 2; speedOppLeft = 5; speedOppRight = 3; }
PARAMETRIZE { speedPlayerRight = 5; speedOppLeft = 2; speedOppRight = 3; }
GIVEN {
PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); Speed(4); }
PLAYER(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); Speed(speedPlayerRight); }
PLAYER(SPECIES_WOBBUFFET) { Speed(4); }
OPPONENT(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); Speed(speedOppLeft); }
OPPONENT(SPECIES_ZEKROM) { Ability(ABILITY_TERAVOLT); Speed(speedOppRight); }
} WHEN {
TURN { SWITCH(playerLeft, 2); }
} SCENE {
ABILITY_POPUP(playerLeft, ABILITY_NEUTRALIZING_GAS);
MESSAGE("Neutralizing gas filled the area!");
SWITCH_OUT_MESSAGE("Weezing");
MESSAGE("The effects of the neutralizing gas wore off!");
if (speedPlayerRight > speedOppLeft)
{
if (speedPlayerRight > speedOppRight) {
ABILITY_POPUP(playerRight, ABILITY_INTREPID_SWORD);
if (speedOppRight > speedOppLeft) {
ABILITY_POPUP(opponentRight, ABILITY_TERAVOLT);
ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE);
} else {
ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE);
ABILITY_POPUP(opponentRight, ABILITY_TERAVOLT);
}
} else {
ABILITY_POPUP(opponentRight, ABILITY_TERAVOLT);
ABILITY_POPUP(playerRight, ABILITY_INTREPID_SWORD);
ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE);
}
} else {
if (speedOppLeft > speedOppRight) {
ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE);
if (speedOppRight > speedPlayerRight) {
ABILITY_POPUP(opponentRight, ABILITY_TERAVOLT);
ABILITY_POPUP(playerRight, ABILITY_INTREPID_SWORD);
} else {
ABILITY_POPUP(playerRight, ABILITY_INTREPID_SWORD);
ABILITY_POPUP(opponentRight, ABILITY_TERAVOLT);
}
} else {
ABILITY_POPUP(opponentRight, ABILITY_TERAVOLT);
ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE);
ABILITY_POPUP(playerRight, ABILITY_INTREPID_SWORD);
}
}
SEND_IN_MESSAGE("Wobbuffet");
}
}
SINGLE_BATTLE_TEST("Neutralizing Gas prevents Insomnia from blocking Rest")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_REST) == EFFECT_REST);
PLAYER(SPECIES_DROWZEE) { Ability(ABILITY_INSOMNIA); HP(1); }
OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); }
} WHEN {
TURN { MOVE(player, MOVE_REST); }
} SCENE {
NOT ABILITY_POPUP(player, ABILITY_INSOMNIA);
// ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player);
// STATUS_ICON(player, sleep: TRUE);
ANIMATION(ANIM_TYPE_MOVE, MOVE_REST, player);
HP_BAR(player);
}
}
SINGLE_BATTLE_TEST("Neutralizing Gas prevents Trace from copying it")
{
GIVEN {
PLAYER(SPECIES_RALTS) { Ability(ABILITY_TRACE); }
OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); }
} WHEN {
TURN { }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS);
NONE_OF {
ABILITY_POPUP(player, ABILITY_TRACE);
ABILITY_POPUP(player, ABILITY_NEUTRALIZING_GAS);
}
}
}
SINGLE_BATTLE_TEST("Neutralizing Gas prevents Contrary inverting stat boosts")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_REST) == EFFECT_REST);
PLAYER(SPECIES_INKAY) { Ability(ABILITY_CONTRARY); }
OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); }
} WHEN {
TURN { MOVE(player, MOVE_SWORDS_DANCE); MOVE(opponent, MOVE_LEER); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_LEER, opponent);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
} THEN {
EXPECT_GT(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
EXPECT_LT(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE);
}
}

View File

@ -137,3 +137,61 @@ SINGLE_BATTLE_TEST("Psychic Seed raises the holder's Sp. Defense on Psychic Terr
EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1);
}
}
SINGLE_BATTLE_TEST("Seeds get consumed in Terrain even if holder is not affected by Terrain")
{
u32 species, ability, item;
PARAMETRIZE { species = SPECIES_TAPU_KOKO; ability = ABILITY_ELECTRIC_SURGE; item = ITEM_ELECTRIC_SEED; }
PARAMETRIZE { species = SPECIES_TAPU_BULU; ability = ABILITY_GRASSY_SURGE; item = ITEM_GRASSY_SEED; }
PARAMETRIZE { species = SPECIES_TAPU_FINI; ability = ABILITY_MISTY_SURGE; item = ITEM_MISTY_SEED; }
PARAMETRIZE { species = SPECIES_TAPU_LELE; ability = ABILITY_PSYCHIC_SURGE; item = ITEM_PSYCHIC_SEED; }
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_PIDGEY].types[0] == TYPE_FLYING || gSpeciesInfo[SPECIES_PIDGEY].types[1] == TYPE_FLYING);
PLAYER(SPECIES_PIDGEY) { Item(item); }
OPPONENT(species) { Ability(ability); }
} WHEN {
TURN { }
} SCENE {
ABILITY_POPUP(opponent, ability);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
} THEN {
EXPECT_EQ(player->item, ITEM_NONE);
}
}
SINGLE_BATTLE_TEST("Electric Seed is consumed on Electric Terrain before other abilities change the terrain")
{
GIVEN {
PLAYER(SPECIES_TAPU_BULU) { Ability(ABILITY_GRASSY_SURGE); Item(ITEM_ELECTRIC_SEED); Speed(5); }
OPPONENT(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); Item(ITEM_ELECTRIC_SEED); Speed(10); }
} WHEN {
TURN { }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_ELECTRIC_SURGE);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Using Electric Seed, the Defense of the opposing Tapu Koko rose!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Electric Seed, the Defense of Tapu Bulu rose!");
ABILITY_POPUP(player, ABILITY_GRASSY_SURGE);
}
}
SINGLE_BATTLE_TEST("Electric Seed doesn't activate on existing Electric Terrain before user's ability changes the terrain")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_TAPU_BULU) { Ability(ABILITY_GRASSY_SURGE); Item(ITEM_ELECTRIC_SEED); }
OPPONENT(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); }
} WHEN {
TURN { SWITCH(player, 1); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_ELECTRIC_SURGE);
SWITCH_OUT_MESSAGE("Wobbuffet");
SEND_IN_MESSAGE("Tapu Bulu");
NONE_OF {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Electric Seed, the Defense of Tapu Bulu rose!");
}
ABILITY_POPUP(player, ABILITY_GRASSY_SURGE);
}
}