Merge branch 'upcoming' into overworldsnow

This commit is contained in:
kittenchilly 2023-09-07 14:29:30 -05:00
commit e20383b0a4
10 changed files with 415 additions and 63 deletions

View File

@ -1312,6 +1312,12 @@
.4byte \failInstr
.endm
.macro jumpifcantfling battler:req, jumpInstr:req
callnative BS_JumpIfCantFling
.byte \battler
.4byte \jumpInstr
.endm
.macro jumpifholdeffect battler:req, holdEffect:req, jumpInstr:req
callnative BS_JumpIfHoldEffect
.byte \battler
@ -2039,11 +2045,6 @@
.4byte \jumpInstr
.endm
.macro jumpifcantfling battler:req, jumpInstr:req
various \battler, VARIOUS_JUMP_IF_CANT_FLING
.4byte \jumpInstr
.endm
.macro curecertainstatuses battler:req
various \battler, VARIOUS_CURE_CERTAIN_STATUSES
.endm

View File

@ -1882,28 +1882,28 @@ Move_MAGNET_RISE:
delay 0
createvisualtask AnimTask_BlendColorCycle, 2, (F_PAL_BG | F_PAL_BATTLERS), -31, 1, 5, 5, RGB(31, 31, 20)
playsewithpan SE_M_THUNDERBOLT2, SOUND_PAN_ATTACKER
createvisualtask AnimTask_WindUpLunge, 5, ANIM_OPPONENT_RIGHT, 0, -12, 4, 10, 10, 12, 6
createsprite gSparkElectricitySpriteTemplate, 0, 7, 32, 24, 190, 12, 0, 1, 0
createvisualtask AnimTask_WindUpLunge, 5, ANIM_ATTACKER, -12, 4, 10, 10, 12, 6
createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 32, 24, 190, 12, ANIM_ATTACKER, 1, 0
delay 0
createsprite gSparkElectricitySpriteTemplate, 0, 7, 80, 24, 22, 12, 0, 1, 0
createsprite gSparkElectricitySpriteTemplate, 0, 7, 156, 24, 121, 13, 0, 1, 1
createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 80, 24, 22, 12, ANIM_ATTACKER, 1, 0
createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 156, 24, 121, 13, ANIM_ATTACKER, 1, 1
delay 0
playsewithpan SE_M_THUNDERBOLT2, SOUND_PAN_ATTACKER
delay 4
createsprite gSparkElectricitySpriteTemplate, 0, 7, 100, 24, 60, 10, 0, 1, 0
createsprite gSparkElectricitySpriteTemplate, 0, 7, 170, 24, 42, 11, 0, 1, 1
createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 100, 24, 60, 10, ANIM_ATTACKER, 1, 0
createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 170, 24, 42, 11, ANIM_ATTACKER, 1, 1
delay 0
createsprite gSparkElectricitySpriteTemplate, 0, 7, 238, 24, 165, 10, 0, 1, 1
createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 238, 24, 165, 10, ANIM_ATTACKER, 1, 1
delay 0
createsprite gSparkElectricitySpriteTemplate, 0, 7, 32, 24, 190, 12, 0, 1, 0
createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 32, 24, 190, 12, ANIM_ATTACKER, 1, 0
delay 0
createsprite gSparkElectricitySpriteTemplate, 0, 7, 80, 24, 22, 12, 0, 1, 0
createsprite gSparkElectricitySpriteTemplate, 0, 7, 156, 24, 121, 13, 0, 1, 1
createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 80, 24, 22, 12, ANIM_ATTACKER, 1, 0
createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 156, 24, 121, 13, ANIM_ATTACKER, 1, 1
delay 0
createsprite gSparkElectricitySpriteTemplate, 0, 7, 100, 24, 60, 10, 0, 1, 0
createsprite gSparkElectricitySpriteTemplate, 0, 7, 170, 24, 42, 11, 0, 1, 1
createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 100, 24, 60, 10, ANIM_ATTACKER, 1, 0
createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 170, 24, 42, 11, ANIM_ATTACKER, 1, 1
delay 0
createsprite gSparkElectricitySpriteTemplate, 0, 7, 238, 24, 165, 10, 0, 1, 1
createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 238, 24, 165, 10, ANIM_ATTACKER, 1, 1
delay 0
createvisualtask AnimTask_BlendColorCycle, 2, (F_PAL_BG | F_PAL_BATTLERS), -31, 1, 0, 0, RGB(31, 31, 20)
delay 20
@ -8927,7 +8927,7 @@ Boomburst_Doubles:
Move_FAIRY_LOCK::
loadspritegfx ANIM_TAG_CHAIN_LINK @Chain Colour
loadspritegfx ANIM_TAG_FAIRY_LOCK_CHAINS @Fairy Lock Chain
loadspritegfx ANIM_TAG_FAIRY_LOCK_CHAINS @AnimTask is missing for Fairy Lock Chain
setalpha 8, 8
monbg ANIM_ATK_PARTNER
createvisualtask AnimTask_BlendBattleAnimPal, 0xa, F_PAL_BG, 0x1, 0x0, 0x8, 0x6B1F

View File

@ -918,12 +918,10 @@ BattleScript_SkyDropFlyingAlreadyConfused:
goto BattleScript_ThrashConfuses
BattleScript_EffectFling:
attackcanceler
jumpifcantfling BS_ATTACKER, BattleScript_FailedFromAtkString
jumpifstatus3 BS_ATTACKER, STATUS3_EMBARGO, BattleScript_FailedFromAtkString
jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_MAGIC_ROOM, BattleScript_FailedFromAtkString
setlastuseditem BS_ATTACKER
removeitem BS_ATTACKER
attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
pause B_WAIT_TIME_SHORT
@ -966,6 +964,10 @@ BattleScript_FlingEnd:
trysymbiosis
goto BattleScript_MoveEnd
BattleScript_FlingFailConsumeItem::
removeitem BS_ATTACKER
goto BattleScript_FailedFromAtkString
BattleScript_FlingFlameOrb:
setmoveeffect MOVE_EFFECT_BURN
seteffectprimary

View File

@ -10,6 +10,7 @@ extern const u8 BattleScript_MakeMoveMissed[];
extern const u8 BattleScript_PrintMoveMissed[];
extern const u8 BattleScript_MoveMissedPause[];
extern const u8 BattleScript_MoveMissed[];
extern const u8 BattleScript_FlingFailConsumeItem[];
extern const u8 BattleScript_FailedFromAtkString[];
extern const u8 BattleScript_ButItFailed[];
extern const u8 BattleScript_StatUp[];

View File

@ -54,7 +54,8 @@
#define WEATHER_HAS_EFFECT ((!IsAbilityOnField(ABILITY_CLOUD_NINE) && !IsAbilityOnField(ABILITY_AIR_LOCK)))
#define IS_WHOLE_SIDE_ALIVE(battler)((IsBattlerAlive(battler) && IsBattlerAlive(BATTLE_PARTNER(battler))))
#define IS_WHOLE_SIDE_ALIVE(battler) ((IsBattlerAlive(battler) && IsBattlerAlive(BATTLE_PARTNER(battler))))
#define IS_ALIVE_AND_PRESENT(battler) (IsBattlerAlive(battler) && IsBattlerSpritePresent(battler))
// for Natural Gift and Fling
struct TypePower
@ -191,7 +192,7 @@ void ClearIllusionMon(u32 battler);
bool32 SetIllusionMon(struct Pokemon *mon, u32 battler);
bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 battler);
u8 GetBattleMoveSplit(u32 moveId);
bool32 CanFling(u8 battler);
bool32 CanFling(u32 battler);
bool32 IsTelekinesisBannedSpecies(u16 species);
bool32 IsHealBlockPreventingMove(u32 battler, u32 move);
bool32 HasEnoughHpToEatBerry(u32 battler, u32 hpFraction, u32 itemId);

View File

@ -230,7 +230,6 @@
#define VARIOUS_SET_SKY_DROP 138
#define VARIOUS_CLEAR_SKY_DROP 139
#define VARIOUS_SKY_DROP_YAWN 140
#define VARIOUS_JUMP_IF_CANT_FLING 141
#define VARIOUS_JUMP_IF_HOLD_EFFECT 142
#define VARIOUS_CURE_CERTAIN_STATUSES 143
#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 144

View File

@ -435,30 +435,25 @@ static void Cmd_unloadspritegfx(void)
static u8 GetBattleAnimMoveTargets(u8 battlerArgIndex, u8 *targets)
{
u8 numTargets = 1;
u8 numTargets = 0;
int idx = 0;
u32 battler = gBattleAnimArgs[battlerArgIndex];
switch (GetBattlerMoveTargetType(gBattleAnimAttacker, gAnimMoveIndex))
{
case MOVE_TARGET_BOTH:
targets[0] = gBattleAnimArgs[battlerArgIndex];
numTargets = 1;
if (IsBattlerAlive(BATTLE_PARTNER(targets[0])))
{
targets[1] = BATTLE_PARTNER(targets[0]);
numTargets = 2;
}
break;
case MOVE_TARGET_FOES_AND_ALLY:
targets[0] = gBattleAnimArgs[battlerArgIndex];
numTargets = 1;
if (IsBattlerAlive(BATTLE_PARTNER(targets[0])))
{
targets[1] = BATTLE_PARTNER(targets[0]);
if (IS_ALIVE_AND_PRESENT(BATTLE_PARTNER(BATTLE_OPPOSITE(battler)))) {
targets[idx++] = BATTLE_PARTNER(BATTLE_OPPOSITE(battler));
numTargets++;
}
if (IsBattlerAlive(BATTLE_PARTNER(BATTLE_OPPOSITE(targets[0]))))
{
targets[2] = BATTLE_PARTNER(BATTLE_OPPOSITE(targets[0]));
// fallthrough
case MOVE_TARGET_BOTH:
if (IS_ALIVE_AND_PRESENT(battler)) {
targets[idx++] = battler;
numTargets++;
}
battler = BATTLE_PARTNER(battler);
if (IS_ALIVE_AND_PRESENT(battler)) {
targets[idx++] = battler;
numTargets++;
}
break;
@ -551,6 +546,8 @@ static void CreateSpriteOnTargets(const struct SpriteTemplate *template, u8 argV
subpriority = GetSubpriorityForMoveAnim(argVar);
ntargets = GetBattleAnimMoveTargets(battlerArgIndex, targets);
if (ntargets == 0)
return;
for (i = 0; i < ntargets; i++) {
@ -676,6 +673,8 @@ static void Cmd_createvisualtaskontargets(void)
}
numArgs = GetBattleAnimMoveTargets(battlerArgIndex, targets);
if (numArgs == 0)
return;
for (i = 0; i < numArgs; i++)
{

View File

@ -1370,9 +1370,15 @@ static void Cmd_attackcanceler(void)
}
gHitMarker |= HITMARKER_OBEYS;
if (NoTargetPresent(gBattlerAttacker, gCurrentMove) && (!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)))
// Check if no available target present on the field.
if (NoTargetPresent(gBattlerAttacker, gCurrentMove)
&& (!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)))
{
gBattlescriptCurrInstr = BattleScript_FailedFromAtkString;
if (gBattleMoves[gCurrentMove].effect == EFFECT_FLING) // Edge case for removing a mon's item when there is no target available after using Fling.
gBattlescriptCurrInstr = BattleScript_FlingFailConsumeItem;
else
gBattlescriptCurrInstr = BattleScript_FailedFromAtkString;
if (!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))
CancelMultiTurnMoves(gBattlerAttacker);
return;
@ -10554,15 +10560,6 @@ static void Cmd_various(void)
gBattlescriptCurrInstr = cmd->failInstr;
return;
}
case VARIOUS_JUMP_IF_CANT_FLING:
{
VARIOUS_ARGS(const u8 *jumpInstr);
if (!CanFling(battler))
gBattlescriptCurrInstr = cmd->jumpInstr;
else
gBattlescriptCurrInstr = cmd->nextInstr;
return;
}
case VARIOUS_CURE_CERTAIN_STATUSES:
{
VARIOUS_ARGS();
@ -15787,11 +15784,22 @@ void BS_CalcMetalBurstDmg(void)
}
}
void BS_JumpIfCantFling(void)
{
NATIVE_ARGS(u8 battler, const u8 *jumpInstr);
u32 battler = GetBattlerForBattleScript(cmd->battler);
if (!CanFling(battler))
gBattlescriptCurrInstr = cmd->jumpInstr;
else
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_JumpIfMoreThanHalfHP(void)
{
NATIVE_ARGS(u8 battler, const u8 *jumpInstr);
u8 battler = GetBattlerForBattleScript(cmd->battler);
u32 battler = GetBattlerForBattleScript(cmd->battler);
if (gBattleMons[battler].hp > (gBattleMons[battler].maxHP + 1) / 2)
gBattlescriptCurrInstr = cmd->jumpInstr;
else

View File

@ -6559,8 +6559,9 @@ static u8 DamagedStatBoostBerryEffect(u8 battler, u8 statId, u8 split)
if (IsBattlerAlive(battler)
&& TARGET_TURN_DAMAGED
&& CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)
&& !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)
&& GetBattleMoveSplit(gCurrentMove) == split)
&& (gBattleScripting.overrideBerryRequirements
|| (!DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && GetBattleMoveSplit(gCurrentMove) == split))
)
{
BufferStatChange(battler, statId, STRINGID_STATROSE);
@ -6766,6 +6767,12 @@ static u8 ItemEffectMoveEnd(u32 battler, u16 holdEffect)
case HOLD_EFFECT_SP_DEFENSE_UP:
effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, FALSE);
break;
case HOLD_EFFECT_KEE_BERRY: // consume and boost defense if used physical move
effect = DamagedStatBoostBerryEffect(battler, STAT_DEF, SPLIT_PHYSICAL);
break;
case HOLD_EFFECT_MARANGA_BERRY: // consume and boost sp. defense if used special move
effect = DamagedStatBoostBerryEffect(battler, STAT_SPDEF, SPLIT_SPECIAL);
break;
case HOLD_EFFECT_RANDOM_STAT_UP:
effect = RandomStatRaiseBerry(battler, gLastUsedItem, FALSE);
break;
@ -10625,11 +10632,9 @@ static u8 GetFlingPowerFromItemId(u16 itemId)
return ItemId_GetFlingPower(itemId);
}
// Make sure the input bank is any bank on the specific mon's side
bool32 CanFling(u8 battler)
bool32 CanFling(u32 battler)
{
u16 item = gBattleMons[battler].item;
u16 itemEffect = ItemId_GetHoldEffect(item);
if (item == ITEM_NONE
#if B_KLUTZ_FLING_INTERACTION >= GEN_5

View File

@ -0,0 +1,336 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_FLING].effect == EFFECT_FLING);
}
SINGLE_BATTLE_TEST("Fling fails if pokemon holds no item")
{
u16 item;
PARAMETRIZE {item = ITEM_NONE; }
PARAMETRIZE {item = ITEM_RAZOR_CLAW; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(item); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_FLING);}
} SCENE {
MESSAGE("Wobbuffet used Fling!");
if (item != ITEM_NONE) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
HP_BAR(opponent);
} else {
MESSAGE("But it failed!");
}
}
}
SINGLE_BATTLE_TEST("Fling fails if pokemon is under the effects of Embargo or Magic Room")
{
u16 move;
PARAMETRIZE {move = MOVE_CELEBRATE; }
PARAMETRIZE {move = MOVE_EMBARGO; }
PARAMETRIZE {move = MOVE_MAGIC_ROOM; }
GIVEN {
ASSUME(gBattleMoves[MOVE_EMBARGO].effect == EFFECT_EMBARGO);
ASSUME(gBattleMoves[MOVE_MAGIC_ROOM].effect == EFFECT_MAGIC_ROOM);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_RAZOR_CLAW); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); }
TURN { MOVE(player, MOVE_FLING); }
} SCENE {
MESSAGE("Wobbuffet used Fling!");
if (move == MOVE_CELEBRATE) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
HP_BAR(opponent);
} else {
MESSAGE("But it failed!");
}
}
}
SINGLE_BATTLE_TEST("Fling fails for pokemon with Klutz ability")
{
u16 ability;
PARAMETRIZE {ability = ABILITY_KLUTZ; }
PARAMETRIZE {ability = ABILITY_RUN_AWAY; }
GIVEN {
ASSUME(P_GEN_4_POKEMON == TRUE);
ASSUME(B_KLUTZ_FLING_INTERACTION >= GEN_5);
PLAYER(SPECIES_BUNEARY) { Item(ITEM_RAZOR_CLAW); Ability(ability); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_FLING); }
} SCENE {
MESSAGE("Buneary used Fling!");
if (ability != ABILITY_KLUTZ) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
HP_BAR(opponent);
} else {
MESSAGE("But it failed!");
}
}
}
SINGLE_BATTLE_TEST("Fling's thrown item can be regained with Recycle")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_RECYCLE].effect == EFFECT_RECYCLE);
PLAYER(SPECIES_WOBBUFFET) {Item(ITEM_RAZOR_CLAW); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_FLING);}
TURN { MOVE(player, MOVE_RECYCLE);}
TURN { MOVE(player, MOVE_FLING);}
} SCENE {
MESSAGE("Wobbuffet used Fling!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
HP_BAR(opponent);
MESSAGE("Wobbuffet used Recycle!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_RECYCLE, player);
MESSAGE("Wobbuffet found one Razor Claw!");
MESSAGE("Wobbuffet used Fling!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
HP_BAR(opponent);
}
}
SINGLE_BATTLE_TEST("Fling - Item is lost even when there is no target")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_SELF_DESTRUCT].effect == EFFECT_EXPLOSION);
PLAYER(SPECIES_WOBBUFFET) {Item(ITEM_RAZOR_CLAW); Speed(2); }
OPPONENT(SPECIES_WOBBUFFET) {Speed(5); }
OPPONENT(SPECIES_WOBBUFFET) {Speed(5); }
} WHEN {
TURN { MOVE(opponent, MOVE_SELF_DESTRUCT); MOVE(player, MOVE_FLING); SEND_OUT(opponent, 1); }
TURN { MOVE(player, MOVE_FLING); }
} SCENE {
MESSAGE("Foe Wobbuffet used SelfDestruct!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SELF_DESTRUCT, opponent);
HP_BAR(player);
MESSAGE("Foe Wobbuffet fainted!");
MESSAGE("Wobbuffet used Fling!");
MESSAGE("But it failed!");
MESSAGE("Wobbuffet used Fling!");
MESSAGE("But it failed!");
} THEN {
EXPECT_EQ(player->item, ITEM_NONE);
}
}
SINGLE_BATTLE_TEST("Fling - Item is lost when target protects itself")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_PROTECT].effect == EFFECT_PROTECT);
PLAYER(SPECIES_WOBBUFFET) {Item(ITEM_RAZOR_CLAW); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_PROTECT); MOVE(player, MOVE_FLING);}
TURN { MOVE(player, MOVE_FLING); }
} SCENE {
MESSAGE("Foe Wobbuffet used Protect!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponent);
MESSAGE("Wobbuffet used Fling!");
MESSAGE("Foe Wobbuffet protected itself!");
MESSAGE("Wobbuffet used Fling!");
MESSAGE("But it failed!");
} THEN {
EXPECT_EQ(player->item, ITEM_NONE);
}
}
SINGLE_BATTLE_TEST("Fling doesn't consume the item if pokemon is asleep/frozen/paralyzed")
{
u32 status;
u16 item;
PARAMETRIZE {status = STATUS1_SLEEP_TURN(2); item = ITEM_RAZOR_CLAW; }
PARAMETRIZE {status = STATUS1_PARALYSIS; item = ITEM_RAZOR_CLAW; }
PARAMETRIZE {status = STATUS1_FREEZE; item = ITEM_RAZOR_CLAW; }
PARAMETRIZE {status = STATUS1_SLEEP_TURN(2); item = ITEM_NONE; }
PARAMETRIZE {status = STATUS1_PARALYSIS; item = ITEM_NONE; }
PARAMETRIZE {status = STATUS1_FREEZE; item = ITEM_NONE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) {Item(item); Status1(status); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
if (status == STATUS1_FREEZE) {
TURN { MOVE(player, MOVE_FLING, WITH_RNG(RNG_FROZEN, FALSE)); }
TURN { MOVE(player, MOVE_FLING, WITH_RNG(RNG_FROZEN, TRUE)); }
} else if (status == STATUS1_PARALYSIS) {
TURN { MOVE(player, MOVE_FLING, WITH_RNG(RNG_PARALYSIS, FALSE)); }
TURN { MOVE(player, MOVE_FLING, WITH_RNG(RNG_PARALYSIS, TRUE)); }
} else {
TURN { MOVE(player, MOVE_FLING); }
TURN { MOVE(player, MOVE_FLING); }
}
} SCENE {
if (status == STATUS1_FREEZE) {
MESSAGE("Wobbuffet is frozen solid!");
MESSAGE("Wobbuffet was defrosted!");
}
else if (status == STATUS1_PARALYSIS) {
MESSAGE("Wobbuffet is paralyzed! It can't move!");
}
else {
MESSAGE("Wobbuffet is fast asleep.");
MESSAGE("Wobbuffet woke up!");
}
MESSAGE("Wobbuffet used Fling!");
if (item != ITEM_NONE) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
HP_BAR(opponent);
} else {
MESSAGE("But it failed!");
}
} THEN {
EXPECT_EQ(player->item, ITEM_NONE);
}
}
SINGLE_BATTLE_TEST("Fling applies special effects when throwing specific Items")
{
u16 item, effect;
PARAMETRIZE {item = ITEM_FLAME_ORB; effect = EFFECT_WILL_O_WISP; }
PARAMETRIZE {item = ITEM_TOXIC_ORB; effect = EFFECT_TOXIC; }
PARAMETRIZE {item = ITEM_POISON_BARB; effect = EFFECT_POISON; }
PARAMETRIZE {item = ITEM_LIGHT_BALL; effect = EFFECT_PARALYZE; }
PARAMETRIZE {item = ITEM_RAZOR_FANG; effect = EFFECT_FLINCH_HIT; }
PARAMETRIZE {item = ITEM_KINGS_ROCK; effect = EFFECT_FLINCH_HIT; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(item); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_FLING); }
} SCENE {
MESSAGE("Wobbuffet used Fling!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
HP_BAR(opponent);
switch (effect)
{
case EFFECT_WILL_O_WISP:
MESSAGE("Foe Wobbuffet was burned!");
STATUS_ICON(opponent, STATUS1_BURN);
break;
case EFFECT_PARALYZE:
MESSAGE("Foe Wobbuffet is paralyzed! It may be unable to move!");
STATUS_ICON(opponent, STATUS1_PARALYSIS);
break;
case EFFECT_POISON:
MESSAGE("Foe Wobbuffet was poisoned!");
STATUS_ICON(opponent, STATUS1_POISON);
break;
case EFFECT_TOXIC:
MESSAGE("Foe Wobbuffet is badly poisoned!");
STATUS_ICON(opponent, STATUS1_TOXIC_POISON);
break;
case EFFECT_FLINCH_HIT:
MESSAGE("Foe Wobbuffet flinched!");
break;
}
}
}
SINGLE_BATTLE_TEST("Fling - thrown berry's effect activates for the target even if the trigger conditions are not met")
{
u16 item, effect;
u8 statId = 0;
u32 status1 = STATUS1_NONE;
PARAMETRIZE { item = ITEM_ORAN_BERRY; effect = HOLD_EFFECT_RESTORE_HP; }
PARAMETRIZE { item = ITEM_SITRUS_BERRY; effect = HOLD_EFFECT_RESTORE_HP; }
PARAMETRIZE { item = ITEM_CHESTO_BERRY; effect = HOLD_EFFECT_CURE_SLP; status1 = STATUS1_SLEEP; }
PARAMETRIZE { item = ITEM_CHERI_BERRY; effect = HOLD_EFFECT_CURE_PAR; status1 = STATUS1_PARALYSIS; }
PARAMETRIZE { item = ITEM_PECHA_BERRY; effect = HOLD_EFFECT_CURE_PSN; status1 = STATUS1_POISON; }
PARAMETRIZE { item = ITEM_PECHA_BERRY; effect = HOLD_EFFECT_CURE_PSN; status1 = STATUS1_TOXIC_POISON; }
PARAMETRIZE { item = ITEM_RAWST_BERRY; effect = HOLD_EFFECT_CURE_BRN; status1 = STATUS1_BURN; }
PARAMETRIZE { item = ITEM_ASPEAR_BERRY; effect = HOLD_EFFECT_CURE_FRZ; status1 = STATUS1_FREEZE; }
PARAMETRIZE { item = ITEM_APICOT_BERRY; effect = HOLD_EFFECT_SP_DEFENSE_UP; statId = STAT_SPDEF; }
PARAMETRIZE { item = ITEM_MARANGA_BERRY; effect = HOLD_EFFECT_MARANGA_BERRY; statId = STAT_SPDEF; }
PARAMETRIZE { item = ITEM_GANLON_BERRY; effect = HOLD_EFFECT_DEFENSE_UP; statId = STAT_DEF; }
PARAMETRIZE { item = ITEM_KEE_BERRY; effect = HOLD_EFFECT_KEE_BERRY; statId = STAT_DEF; }
PARAMETRIZE { item = ITEM_LIECHI_BERRY; effect = HOLD_EFFECT_ATTACK_UP; statId = STAT_ATK; }
PARAMETRIZE { item = ITEM_PETAYA_BERRY; effect = HOLD_EFFECT_SP_ATTACK_UP; statId = STAT_SPATK; }
PARAMETRIZE { item = ITEM_SALAC_BERRY; effect = HOLD_EFFECT_SPEED_UP; statId = STAT_SPEED; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(item); }
OPPONENT(SPECIES_WOBBUFFET) { Status1(status1); HP(399); MaxHP(400); }
} WHEN {
TURN { MOVE(player, MOVE_FLING); }
} SCENE {
MESSAGE("Wobbuffet used Fling!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
HP_BAR(opponent);
if (effect == HOLD_EFFECT_RESTORE_HP) {
if (item == ITEM_ORAN_BERRY) {
MESSAGE("Foe Wobbuffet's Oran Berry restored health!");
} else {
MESSAGE("Foe Wobbuffet's Sitrus Berry restored health!");
}
HP_BAR(opponent);
}
else if (status1 != STATUS1_NONE) {
if (status1 == STATUS1_BURN) {
MESSAGE("Foe Wobbuffet's Rawst Berry healed its burn!");
} else if (status1 == STATUS1_SLEEP) {
MESSAGE("Foe Wobbuffet's Chesto Berry woke it from its sleep!");
} else if (status1 == STATUS1_FREEZE) {
MESSAGE("Foe Wobbuffet's Aspear Berry defrosted it!");
} else if (status1 == STATUS1_PARALYSIS) {
MESSAGE("Foe Wobbuffet's Cheri Berry cured paralysis!");
} else if (status1 == STATUS1_TOXIC_POISON || status1 == STATUS1_POISON) {
MESSAGE("Foe Wobbuffet's Pecha Berry cured poison!");
}
NOT STATUS_ICON(opponent, status1);
}
else if (statId != 0) {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
if (statId == STAT_ATK) {
MESSAGE("Using Liechi Berry, the Attack of Foe Wobbuffet rose!");
} else if (statId == STAT_DEF) {
if (item == ITEM_GANLON_BERRY) {
MESSAGE("Using Ganlon Berry, the Defense of Foe Wobbuffet rose!");
} else {
MESSAGE("Using Kee Berry, the Defense of Foe Wobbuffet rose!");
}
} else if (statId == STAT_SPDEF) {
if (item == ITEM_APICOT_BERRY) {
MESSAGE("Using Apicot Berry, the Sp. Def of Foe Wobbuffet rose!");
} else {
MESSAGE("Using Maranga Berry, the Sp. Def of Foe Wobbuffet rose!");
}
} else if (statId == STAT_SPEED) {
MESSAGE("Using Salac Berry, the Speed of Foe Wobbuffet rose!");
} else if (statId == STAT_SPATK) {
MESSAGE("Using Petaya Berry, the Sp. Atk of Foe Wobbuffet rose!");
}
}
} THEN {
if (effect == HOLD_EFFECT_RESTORE_HP) {
EXPECT_EQ(opponent->hp, opponent->maxHP);
} else if (status1 != STATUS1_NONE) {
EXPECT_EQ(opponent->status1, STATUS1_NONE);
}
else if (statId != 0) {
EXPECT_EQ(opponent->statStages[statId], DEFAULT_STAT_STAGE + 1);
}
}
}