27/02/26 Master to upcoming merge (#9384)
Some checks are pending
CI / build (push) Waiting to run
CI / docs_validate (push) Waiting to run
CI / allcontributors (push) Waiting to run

This commit is contained in:
Bassoonian 2026-02-28 15:58:05 +01:00 committed by GitHub
commit 885180ff8b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
46 changed files with 980 additions and 213 deletions

View File

@ -651,6 +651,15 @@
"contributions": [
"bug"
]
},
{
"login": "KnightGallade",
"name": "KnightGallade",
"avatar_url": "https://avatars.githubusercontent.com/u/189022270?v=4",
"profile": "https://github.com/KnightGallade",
"contributions": [
"bug"
]
}
],
"contributorsPerLine": 7,

View File

@ -93,6 +93,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center" valign="top" width="14.28%"><a href="https://github.com/PacFire"><img src="https://avatars.githubusercontent.com/u/108960850?v=4?s=100" width="100px;" alt="PacFire"/><br /><sub><b>PacFire</b></sub></a><br /><a href="#design-PacFire" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ChrispyChris27"><img src="https://avatars.githubusercontent.com/u/173648816?v=4?s=100" width="100px;" alt="ChrispyChris27"/><br /><sub><b>ChrispyChris27</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=ChrispyChris27" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LogicalLlama"><img src="https://avatars.githubusercontent.com/u/248230900?v=4?s=100" width="100px;" alt="LogicalLlama"/><br /><sub><b>LogicalLlama</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/issues?q=author%3ALogicalLlama" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/KnightGallade"><img src="https://avatars.githubusercontent.com/u/189022270?v=4?s=100" width="100px;" alt="KnightGallade"/><br /><sub><b>KnightGallade</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/issues?q=author%3AKnightGallade" title="Bug reports">🐛</a></td>
</tr>
</tbody>
<tfoot>

View File

@ -648,3 +648,7 @@
.macro shake_battle_platforms priority=2, x_offset:req, y_offset:req, shakes:req, delay:req
createvisualtask AnimTask_ShakeBattlePlatforms, \priority, \x_offset, \y_offset, \shakes, \delay
.endm
.macro create_surf_wave priority=2, palette:req
createvisualtask AnimTask_CreateSurfWave, \priority, \palette
.endm

View File

@ -4409,7 +4409,7 @@ FlameBurstSpread:
gBattleAnimMove_SludgeWave::
panse SE_M_WHIRLPOOL, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 0x2, 0x0
createvisualtask AnimTask_CreateSurfWave, 2, ANIM_SURF_PAL_SLUDGE_WAVE
create_surf_wave palette=ANIM_SURF_PAL_SLUDGE_WAVE
waitforvisualfinish
end
@ -12875,7 +12875,7 @@ gBattleAnimMove_ZippyZap::
gBattleAnimMove_SplishySplash::
loadspritegfx ANIM_TAG_SPARK_2
createvisualtask AnimTask_CreateSurfWave, 2, ANIM_SURF_PAL_SURF
create_surf_wave palette=ANIM_SURF_PAL_SURF
delay 24
panse SE_M_SURF, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, +2, 0
waitforvisualfinish
@ -27017,7 +27017,7 @@ gBattleAnimMove_Crabhammer::
end
gBattleAnimMove_Surf::
createvisualtask AnimTask_CreateSurfWave, 2, ANIM_SURF_PAL_SURF
create_surf_wave palette=ANIM_SURF_PAL_SURF
delay 24
panse SE_M_SURF, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, +2, 0
waitforvisualfinish
@ -29320,7 +29320,7 @@ ArmThrustLeft:
gBattleAnimMove_MuddyWater::
panse SE_M_WHIRLPOOL, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, +2, 0
createvisualtask AnimTask_CreateSurfWave, 2, ANIM_SURF_PAL_MUDDY_WATER
create_surf_wave palette=ANIM_SURF_PAL_MUDDY_WATER
waitforvisualfinish
end
@ -32493,7 +32493,7 @@ FinishAcidDownpour:
createsprite gAcidDownpourReversalSpriteTemplate, ANIM_ATTACKER, 2, 0x1a, 0xd2
delay 32
panse SE_M_WHIRLPOOL, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 0x2, 0x0
createvisualtask AnimTask_CreateSurfWave, 0x2, ANIM_SURF_PAL_SLUDGE_WAVE
create_surf_wave priority=0x2, palette=ANIM_SURF_PAL_SLUDGE_WAVE
createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_TARGET, 2, 0, 7, (RGB(28, 3, 22) | RGB_ALPHA)
createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 2, 50, 1
call AcidDownpourFlare
@ -33388,7 +33388,7 @@ gBattleAnimMove_HydroVortex::
loadspritegfx ANIM_TAG_WATER_ORB @whirlpool
createvisualtask AnimTask_AllBattlersInvisibleExceptAttackerAndTarget, 0xA
waitforvisualfinish
createvisualtask AnimTask_CreateSurfWave, 0x2, 0x0
create_surf_wave priority=0x2, palette=0x0
delay 24
panse SE_M_SURF, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 0x2, 0x0
waitforvisualfinish

View File

@ -1422,6 +1422,7 @@ BattleScript_ToxicThreadTryPsn::
BattleScript_EffectVenomDrench::
attackcanceler
jumpifsubstituteblocks BattleScript_ButItFailed
jumpifstatus BS_TARGET, STATUS1_PSN_ANY, BattleScript_EffectVenomDrenchCanBeUsed
goto BattleScript_ButItFailed
BattleScript_EffectVenomDrenchCanBeUsed:
@ -3856,6 +3857,7 @@ BattleScript_EffectWaterSport::
BattleScript_EffectTickle::
attackcanceler
jumpifsubstituteblocks BattleScript_ButItFailed
jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_ATK, MIN_STAT_STAGE, BattleScript_TickleDoMoveAnim
jumpifstat BS_TARGET, CMP_EQUAL, STAT_DEF, MIN_STAT_STAGE, BattleScript_CantLowerMultipleStats
BattleScript_TickleDoMoveAnim::

View File

@ -236,6 +236,7 @@ enum VolatileFlags
F(VOLATILE_BEADS_OF_RUIN, beadsOfRuin, (u32, 1)) \
F(VOLATILE_IS_TRANSFORMED_MON_SHINY, isTransformedMonShiny, (u32, 1)) \
F(VOLATILE_TRANSFORMED_MON_PID, transformedMonPID, (u32, UINT32_MAX)) \
F(VOLATILE_TRANSFORMED_MON_SPECIES, transformedMonSpecies, (u32, NUM_SPECIES)) \
F(VOLATILE_DISABLED_MOVE, disabledMove, (u32, MOVES_COUNT_ALL)) \
F(VOLATILE_ENCORED_MOVE, encoredMove, (u32, MOVES_COUNT_ALL)) \
F(VOLATILE_PROTECT_USES, consecutiveMoveUses, (u32, UINT8_MAX)) \

View File

@ -691,6 +691,10 @@ enum SpeciesGfxChange
SPECIES_GFX_CHANGE_GHOST_UNVEIL,
};
// Surf wave palettes
#define ANIM_SURF_PAL_SURF 0
#define ANIM_SURF_PAL_MUDDY_WATER 1
// Flags given to various functions to indicate which palettes to consider.
// Handled by UnpackSelectedBattlePalettes
#define F_PAL_BG (1 << 0)

View File

@ -161,6 +161,8 @@ enum FormChanges
FORM_CHANGE_OVERWORLD_WEATHER,
// Form change that activates when the Pokémon is deposited into the PC or Daycare.
FORM_CHANGE_DEPOSIT,
// Form change for Minior, which appears unchanged when encountered in the wild
FORM_CHANGE_BEGIN_WILD_ENCOUNTER,
};
#endif // GUARD_CONSTANTS_FORM_CHANGE_TYPES_H

View File

@ -11,6 +11,15 @@
#define MAPGRID_COLLISION_SHIFT 10
#define MAPGRID_ELEVATION_SHIFT 12
enum
{
ELEVATION_TRANSITION = 0,
ELEVATION_SURF = 1,
ELEVATION_DEFAULT = 3,
ELEVATION_MULTI_LEVEL = 15,
ELEVATION_INVALID = 0xFFFF
};
#define PACK_METATILE(metatileId) PACK(metatileId, MAPGRID_METATILE_ID_SHIFT, MAPGRID_METATILE_ID_MASK)
#define PACK_COLLISION(collision) PACK(collision, MAPGRID_COLLISION_SHIFT, MAPGRID_COLLISION_MASK)
#define PACK_ELEVATION(elevation) PACK(elevation, MAPGRID_ELEVATION_SHIFT, MAPGRID_ELEVATION_MASK)

View File

@ -124,6 +124,9 @@ SECTIONS {
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* DWARF 5*/
.debug_line_str 0 : { *(.debug_line_str) }
/* Discard everything not specifically mentioned above. */
/DISCARD/ :
{

View File

@ -6717,6 +6717,10 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId)
SwapStructData(&gBattleStruct->illusion[battlerAtk], &gBattleStruct->illusion[battlerPartner], data, sizeof(struct Illusion));
SwapStructData(&gBattleStruct->battlerState[battlerAtk], &gBattleStruct->battlerState[battlerPartner], data, sizeof(struct BattlerState));
// Swap those back since they aren't affected by ally switch
SWAP(gBattleStruct->battlerState[battlerAtk].storedHealingWish, gBattleStruct->battlerState[battlerPartner].storedHealingWish, temp);
SWAP(gBattleStruct->battlerState[battlerAtk].storedLunarDance, gBattleStruct->battlerState[battlerPartner].storedLunarDance, temp);
SWAP(gBattleSpritesDataPtr->battlerData[battlerAtk].invisible, gBattleSpritesDataPtr->battlerData[battlerPartner].invisible, temp);
SWAP(gTransformedPersonalities[battlerAtk], gTransformedPersonalities[battlerPartner], temp);
SWAP(gTransformedShininess[battlerAtk], gTransformedShininess[battlerPartner], temp);

View File

@ -1,6 +1,7 @@
#include "global.h"
#include "battle.h"
#include "battle_anim.h"
#include "battle_anim_internal.h"
#include "gpu_regs.h"
#include "graphics.h"
#include "palette.h"
@ -979,6 +980,8 @@ static void AnimSmallBubblePair_Step(struct Sprite *sprite)
void AnimTask_CreateSurfWave(u8 taskId)
{
CMD_ARGS(palette);
struct BattleAnimBgData animBg;
u8 taskId2;
u16 *x;
@ -1005,7 +1008,7 @@ void AnimTask_CreateSurfWave(u8 taskId)
AnimLoadCompressedBgTilemapHandleContest(&animBg, gBattleAnimBgTilemap_SurfContest, TRUE);
}
AnimLoadCompressedBgGfx(animBg.bgId, gBattleAnimBgImage_Surf, animBg.tilesOffset);
switch (gBattleAnimArgs[0])
switch (cmd->palette)
{
case ANIM_SURF_PAL_SURF:
default:

View File

@ -617,6 +617,13 @@ static void CB2_InitBattleInternal(void)
TryFormChange(&gEnemyParty[i], FORM_CHANGE_BEGIN_BATTLE);
}
if (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER))
{
TryFormChange(&gEnemyParty[0], FORM_CHANGE_BEGIN_WILD_ENCOUNTER);
if (IsDoubleBattle())
TryFormChange(&gEnemyParty[1], FORM_CHANGE_BEGIN_WILD_ENCOUNTER);
}
#if TESTING
gPlayerPartyCount = CalculatePartyCount(gPlayerParty);
gEnemyPartyCount = CalculatePartyCount(gEnemyParty);

View File

@ -1304,8 +1304,10 @@ static enum CancelerResult CancelerMoveEffectFailureTarget(struct BattleContext
}
break;
case EFFECT_SUCKER_PUNCH:
{
u32 defMove = GetBattlerChosenMove(battlerDef);
if (HasBattlerActedThisTurn(battlerDef)
|| (IsBattleMoveStatus(GetBattlerChosenMove(battlerDef)) && !gProtectStructs[battlerDef].noValidMoves))
|| (IsBattleMoveStatus(defMove) && !gProtectStructs[battlerDef].noValidMoves && GetMoveEffect(defMove) != EFFECT_ME_FIRST))
{
battleScript = BattleScript_ButItFailed;
}
@ -1314,6 +1316,8 @@ static enum CancelerResult CancelerMoveEffectFailureTarget(struct BattleContext
numAffectedTargets++;
continue;
}
}
break;
case EFFECT_UPPER_HAND:
{
@ -4056,10 +4060,22 @@ static enum Move GetAssistMove(void)
enum Move move = MOVE_NONE;
u32 chooseableMovesNo = 0;
struct Pokemon *party;
u8 battlerByPartyId[PARTY_SIZE];
enum Move validMoves[PARTY_SIZE * MAX_MON_MOVES] = {MOVE_NONE};
party = GetBattlerParty(gBattlerAttacker);
for (u32 i = 0; i < PARTY_SIZE; i++)
battlerByPartyId[i] = MAX_BATTLERS_COUNT;
for (u32 battler = 0; battler < gBattlersCount; battler++)
{
if (!IsBattlerAlly(battler, gBattlerAttacker))
continue;
if (gBattlerPartyIndexes[battler] < PARTY_SIZE)
battlerByPartyId[gBattlerPartyIndexes[battler]] = battler;
}
for (u32 monId = 0; monId < PARTY_SIZE; monId++)
{
if (monId == gBattlerPartyIndexes[gBattlerAttacker])
@ -4071,7 +4087,12 @@ static enum Move GetAssistMove(void)
for (u32 moveId = 0; moveId < MAX_MON_MOVES; moveId++)
{
enum Move move = GetMonData(&party[monId], MON_DATA_MOVE1 + moveId);
enum Move move;
if (battlerByPartyId[monId] != MAX_BATTLERS_COUNT)
move = gBattleMons[battlerByPartyId[monId]].moves[moveId];
else
move = GetMonData(&party[monId], MON_DATA_MOVE1 + moveId);
if (IsMoveAssistBanned(move))
continue;

View File

@ -2362,7 +2362,67 @@ static void SetNonVolatileStatus(enum BattlerId effectBattler, enum MoveEffect e
gBattleStruct->poisonPuppeteerConfusion = TRUE;
}
// To avoid confusion the arguments are naned battler/effectBattler since they can be different from gBattlerAttacker/gBattlerTarget
static inline bool32 IgnoreTargetingForMoveEffect(enum MoveEffect moveEffect) // Currently only used to determine move effects which happen even if the move's defined effectbattler is fainted
{
switch (moveEffect)
{
case MOVE_EFFECT_PAYDAY:
case MOVE_EFFECT_BUG_BITE:
case MOVE_EFFECT_FLAME_BURST:
case MOVE_EFFECT_STEALTH_ROCK:
case MOVE_EFFECT_STEELSURGE:
case MOVE_EFFECT_SUN:
case MOVE_EFFECT_RAIN:
case MOVE_EFFECT_SANDSTORM:
case MOVE_EFFECT_HAIL:
case MOVE_EFFECT_MISTY_TERRAIN:
case MOVE_EFFECT_GRASSY_TERRAIN:
case MOVE_EFFECT_ELECTRIC_TERRAIN:
case MOVE_EFFECT_PSYCHIC_TERRAIN:
case MOVE_EFFECT_DEFOG:
case MOVE_EFFECT_REFLECT:
case MOVE_EFFECT_LIGHT_SCREEN:
case MOVE_EFFECT_AURORA_VEIL:
case MOVE_EFFECT_GRAVITY:
case MOVE_EFFECT_HEAL_TEAM:
case MOVE_EFFECT_AROMATHERAPY:
case MOVE_EFFECT_RECYCLE_BERRIES:
case MOVE_EFFECT_ION_DELUGE:
case MOVE_EFFECT_HAZE:
case MOVE_EFFECT_RAISE_TEAM_ATTACK:
case MOVE_EFFECT_RAISE_TEAM_DEFENSE:
case MOVE_EFFECT_RAISE_TEAM_SPEED:
case MOVE_EFFECT_RAISE_TEAM_SP_ATK:
case MOVE_EFFECT_RAISE_TEAM_SP_DEF:
case MOVE_EFFECT_CRIT_PLUS_SIDE:
case MOVE_EFFECT_LOWER_ATTACK_SIDE:
case MOVE_EFFECT_LOWER_DEFENSE_SIDE:
case MOVE_EFFECT_LOWER_SPEED_SIDE:
case MOVE_EFFECT_LOWER_SP_ATK_SIDE:
case MOVE_EFFECT_LOWER_SP_DEF_SIDE:
case MOVE_EFFECT_LOWER_SPEED_2_SIDE:
case MOVE_EFFECT_LOWER_EVASIVENESS_SIDE:
case MOVE_EFFECT_VINE_LASH:
case MOVE_EFFECT_WILDFIRE:
case MOVE_EFFECT_CANNONADE:
case MOVE_EFFECT_VOLCALITH:
case MOVE_EFFECT_PREVENT_ESCAPE_SIDE:
case MOVE_EFFECT_SANDBLAST_SIDE:
case MOVE_EFFECT_FIRE_SPIN_SIDE:
case MOVE_EFFECT_PARALYZE_SIDE:
case MOVE_EFFECT_POISON_SIDE:
case MOVE_EFFECT_CONFUSE_PAY_DAY_SIDE:
case MOVE_EFFECT_POISON_PARALYZE_SIDE:
case MOVE_EFFECT_EFFECT_SPORE_SIDE:
case MOVE_EFFECT_INFATUATE_SIDE:
case MOVE_EFFECT_CONFUSE_SIDE:
case MOVE_EFFECT_TORMENT_SIDE:
return TRUE;
default:
return FALSE;
}
}
void SetMoveEffect(enum BattlerId battlerAtk, enum BattlerId effectBattler, enum MoveEffect moveEffect, const u8 *battleScript, enum SetMoveEffectFlags effectFlags)
{
enum Ability abilities[MAX_BATTLERS_COUNT] = {ABILITY_NONE};
@ -2375,7 +2435,6 @@ void SetMoveEffect(enum BattlerId battlerAtk, enum BattlerId effectBattler, enum
bool32 affectsUser = (battlerAtk == effectBattler);
bool32 mirrorArmorReflected = (abilities[gBattlerTarget] == ABILITY_MIRROR_ARMOR);
union StatChangeFlags flags = {0};
bool32 activateAfterFaint = FALSE;
if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT
&& IsBattlerAlive(gBattlerTarget)
@ -2384,19 +2443,7 @@ void SetMoveEffect(enum BattlerId battlerAtk, enum BattlerId effectBattler, enum
gBattlescriptCurrInstr = battleScript;
return;
}
switch (moveEffect) // Set move effects which happen later on
{
case MOVE_EFFECT_STEALTH_ROCK:
case MOVE_EFFECT_PAYDAY:
case MOVE_EFFECT_BUG_BITE:
case MOVE_EFFECT_FLAME_BURST:
activateAfterFaint = TRUE;
break;
default:
break;
}
gBattleScripting.battler = battlerAtk;
gEffectBattler = effectBattler;
@ -2406,7 +2453,7 @@ void SetMoveEffect(enum BattlerId battlerAtk, enum BattlerId effectBattler, enum
&& IsSheerForceAffected(gCurrentMove, abilities[battlerAtk])
&& !(moveEffect == MOVE_EFFECT_ORDER_UP && gBattleStruct->battlerState[gBattlerAttacker].commanderSpecies != SPECIES_NONE))
moveEffect = MOVE_EFFECT_NONE;
else if (!IsBattlerAlive(gEffectBattler) && !activateAfterFaint)
else if (!IsBattlerAlive(gEffectBattler) && !IgnoreTargetingForMoveEffect(moveEffect))
moveEffect = MOVE_EFFECT_NONE;
else if (DoesSubstituteBlockMove(gBattlerAttacker, gEffectBattler, gCurrentMove) && !affectsUser)
moveEffect = MOVE_EFFECT_NONE;
@ -4990,6 +5037,7 @@ static void PlayAnimation(enum BattlerId battler, u8 animId, const u16 *argPtr,
|| animId == B_ANIM_FORM_CHANGE
|| animId == B_ANIM_SUBSTITUTE_FADE
|| animId == B_ANIM_PRIMAL_REVERSION
|| animId == B_ANIM_POWER_CONSTRUCT
|| animId == B_ANIM_ULTRA_BURST
|| animId == B_ANIM_TERA_CHARGE
|| animId == B_ANIM_TERA_ACTIVATE
@ -8525,6 +8573,7 @@ static void Cmd_transformdataexecution(void)
gBattleMons[gBattlerAttacker].volatiles.transformed = TRUE;
gBattleMons[gBattlerAttacker].volatiles.disabledMove = MOVE_NONE;
gBattleMons[gBattlerAttacker].volatiles.disableTimer = 0;
gBattleMons[gBattlerAttacker].volatiles.transformedMonSpecies = gBattleMons[gBattlerAttacker].species;
gBattleMons[gBattlerAttacker].volatiles.transformedMonPID = gBattleMons[gBattlerTarget].personality;
if (B_TRANSFORM_SHINY >= GEN_4)
@ -13275,6 +13324,12 @@ void BS_JumpIfAbilityCantBeReactivated(void)
enum BattlerId battler = GetBattlerForBattleScript(cmd->battler);
u32 ability = gBattleMons[battler].ability;
if (GetBattlerHoldEffectIgnoreAbility(battler) == HOLD_EFFECT_ABILITY_SHIELD)
{
gBattlescriptCurrInstr = cmd->jumpInstr;
return;
}
switch (ability)
{
case ABILITY_IMPOSTER:

View File

@ -163,15 +163,19 @@ uq4_12_t GetTeraMultiplier(struct BattleContext *ctx)
else
return UQ_4_12(2.0);
}
// Base or Tera type only.
else if ((ctx->moveType == teraType && !IS_BATTLER_OF_BASE_TYPE(ctx->battlerAtk, ctx->moveType))
|| (ctx->moveType != teraType && IS_BATTLER_OF_BASE_TYPE(ctx->battlerAtk, ctx->moveType)))
// Tera type only (Adaptability applies).
else if (ctx->moveType == teraType && !IS_BATTLER_OF_BASE_TYPE(ctx->battlerAtk, ctx->moveType))
{
if (ctx->abilityAtk == ABILITY_ADAPTABILITY)
return UQ_4_12(2.0);
else
return UQ_4_12(1.5);
}
// Base type only (Adaptability does not apply while Terastallized).
else if (ctx->moveType != teraType && IS_BATTLER_OF_BASE_TYPE(ctx->battlerAtk, ctx->moveType))
{
return UQ_4_12(1.5);
}
// Neither base or Tera type.
else
{

View File

@ -5176,6 +5176,7 @@ static u32 GetStatValueWithStages(enum BattlerId battler, enum Stat stat)
enum Stat GetParadoxHighestStatId(enum BattlerId battler)
{
enum Stat highestId = STAT_ATK;
bool32 wonderRoom = gFieldStatuses & STATUS_FIELD_WONDER_ROOM;
u32 highestStat = GetStatValueWithStages(battler, STAT_ATK);
for (u32 stat = STAT_DEF; stat < NUM_STATS; stat++)
@ -5183,7 +5184,23 @@ enum Stat GetParadoxHighestStatId(enum BattlerId battler)
if (stat == STAT_SPEED)
continue;
u32 statValue = GetStatValueWithStages(battler, stat);
u32 statValue;
switch (stat)
{
case STAT_DEF:
statValue = wonderRoom ? gBattleMons[battler].spDefense : gBattleMons[battler].defense;
statValue *= gStatStageRatios[gBattleMons[battler].statStages[STAT_DEF]][0];
statValue /= gStatStageRatios[gBattleMons[battler].statStages[STAT_DEF]][1];
break;
case STAT_SPDEF:
statValue = wonderRoom ? gBattleMons[battler].defense : gBattleMons[battler].spDefense;
statValue *= gStatStageRatios[gBattleMons[battler].statStages[STAT_SPDEF]][0];
statValue /= gStatStageRatios[gBattleMons[battler].statStages[STAT_SPDEF]][1];
break;
default:
statValue = GetStatValueWithStages(battler, stat);
break;
}
if (statValue > highestStat)
{
highestStat = statValue;
@ -7282,8 +7299,13 @@ static inline u32 CalcDefenseStat(struct BattleContext *ctx)
modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(2.0));
break;
case HOLD_EFFECT_EVIOLITE:
if (CanEvolve(gBattleMons[battlerDef].species))
modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5));
{
u16 species = gBattleMons[battlerDef].species;
if (gBattleMons[battlerDef].volatiles.transformed && gBattleMons[battlerDef].volatiles.transformedMonSpecies != SPECIES_NONE)
species = gBattleMons[battlerDef].volatiles.transformedMonSpecies;
if (CanEvolve(species))
modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5));
}
break;
case HOLD_EFFECT_ASSAULT_VEST:
if (!usesDefStat)

View File

@ -440,7 +440,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
[MOVE_RAZOR_WIND] =
{
.name = COMPOUND_STRING("Razor Wind"),
#if B_UPDATED_MOVE_DATA == GEN_3
#if B_UPDATED_MOVE_DATA == GEN_3 || B_UPDATED_MOVE_DATA == GEN_1
.description = COMPOUND_STRING(
"A 2-turn move that strikes\n"
"the foe on the 2nd turn."),
@ -455,10 +455,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
.accuracy = B_UPDATED_MOVE_DATA >= GEN_3 ? 100 : 75,
#if B_UPDATED_MOVE_DATA >= GEN_4
.criticalHitStage = 1,
#elif B_UPDATED_MOVE_DATA == GEN_3
.criticalHitStage = 0,
#else
#elif B_UPDATED_MOVE_DATA == GEN_2
.criticalHitStage = 2,
#else
.criticalHitStage = 0,
#endif
.pp = 10,
.target = TARGET_BOTH,
@ -490,6 +490,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
.priority = 0,
.category = DAMAGE_CATEGORY_STATUS,
.zMove = { .effect = Z_EFFECT_RESET_STATS },
.ignoresProtect = TRUE,
.mirrorMoveBanned = TRUE,
.danceMove = TRUE,
.snatchAffected = TRUE,
.contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS,
@ -3262,6 +3264,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
.priority = 0,
.category = DAMAGE_CATEGORY_STATUS,
.zMove = { .effect = Z_EFFECT_ATK_UP_2 },
.ignoresProtect = TRUE,
.mirrorMoveBanned = TRUE,
.mimicBanned = TRUE,
.metronomeBanned = B_UPDATED_MOVE_FLAGS >= GEN_4,
.copycatBanned = TRUE,
@ -4633,7 +4637,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
.priority = 0,
.category = DAMAGE_CATEGORY_STATUS,
.zMove = { .effect = Z_EFFECT_DEF_UP_1 },
.ignoresProtect = (B_UPDATED_MOVE_FLAGS >= GEN_6) || (B_UPDATED_MOVE_FLAGS < GEN_3),
.ignoresProtect = B_UPDATED_MOVE_FLAGS < GEN_3,
.magicCoatAffected = TRUE,
.contestEffect = CONTEST_EFFECT_MAKE_FOLLOWING_MONS_NERVOUS,
.contestCategory = CONTEST_CATEGORY_SMART,
@ -4810,7 +4814,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
.priority = 0,
.category = DAMAGE_CATEGORY_STATUS,
.zMove = { .effect = Z_EFFECT_RECOVER_HP },
.ignoresProtect = B_UPDATED_MOVE_FLAGS >= GEN_3,
.ignoresProtect = TRUE,
.ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_5,
.mirrorMoveBanned = TRUE,
.contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE,
@ -4975,6 +4979,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
.category = DAMAGE_CATEGORY_STATUS,
.argument = { .protectMethod = PROTECT_NORMAL },
.zMove = { .effect = Z_EFFECT_RESET_STATS },
.ignoresProtect = TRUE,
.mirrorMoveBanned = TRUE,
.metronomeBanned = TRUE,
.copycatBanned = TRUE,
.assistBanned = TRUE,
@ -7234,6 +7240,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
.target = B_UPDATED_MOVE_FLAGS >= GEN_6 ? TARGET_SELECTED : TARGET_DEPENDS,
.priority = 0,
.category = DAMAGE_CATEGORY_STATUS,
.ignoresProtect = TRUE,
.mirrorMoveBanned = TRUE,
.metronomeBanned = B_UPDATED_MOVE_FLAGS >= GEN_5,
.copycatBanned = TRUE,
.sleepTalkBanned = TRUE,
@ -7806,6 +7814,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
.priority = 4,
.category = DAMAGE_CATEGORY_STATUS,
.zMove = { .effect = Z_EFFECT_SPD_UP_2 },
.ignoresProtect = TRUE,
.mirrorMoveBanned = TRUE,
.ignoresSubstitute = TRUE,
.forcePressure = TRUE,
.metronomeBanned = TRUE,

View File

@ -1514,10 +1514,10 @@ static const struct FormChange sSilvallyFormChangeTable[] =
{FORM_CHANGE_TERMINATOR},
};
#endif //P_FAMILY_TYPE_NULL
#if P_FAMILY_MINIOR
static const struct FormChange sMiniorRedFormChangeTable[] =
{
{FORM_CHANGE_BEGIN_WILD_ENCOUNTER, SPECIES_MINIOR_METEOR_RED},
{FORM_CHANGE_BEGIN_BATTLE, SPECIES_MINIOR_CORE_RED},
{FORM_CHANGE_BATTLE_HP_PERCENT_SEND_OUT, SPECIES_MINIOR_METEOR_RED, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50},
{FORM_CHANGE_BATTLE_HP_PERCENT_SEND_OUT, SPECIES_MINIOR_CORE_RED, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50},
@ -1530,6 +1530,7 @@ static const struct FormChange sMiniorRedFormChangeTable[] =
};
static const struct FormChange sMiniorBlueFormChangeTable[] =
{
{FORM_CHANGE_BEGIN_WILD_ENCOUNTER, SPECIES_MINIOR_METEOR_BLUE},
{FORM_CHANGE_BEGIN_BATTLE, SPECIES_MINIOR_CORE_BLUE},
{FORM_CHANGE_BATTLE_HP_PERCENT_SEND_OUT, SPECIES_MINIOR_METEOR_BLUE, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50},
{FORM_CHANGE_BATTLE_HP_PERCENT_SEND_OUT, SPECIES_MINIOR_CORE_BLUE, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50},
@ -1542,6 +1543,7 @@ static const struct FormChange sMiniorBlueFormChangeTable[] =
};
static const struct FormChange sMiniorGreenFormChangeTable[] =
{
{FORM_CHANGE_BEGIN_WILD_ENCOUNTER, SPECIES_MINIOR_METEOR_GREEN},
{FORM_CHANGE_BEGIN_BATTLE, SPECIES_MINIOR_CORE_GREEN},
{FORM_CHANGE_BATTLE_HP_PERCENT_SEND_OUT, SPECIES_MINIOR_METEOR_GREEN, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50},
{FORM_CHANGE_BATTLE_HP_PERCENT_SEND_OUT, SPECIES_MINIOR_CORE_GREEN, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50},
@ -1554,6 +1556,7 @@ static const struct FormChange sMiniorGreenFormChangeTable[] =
};
static const struct FormChange sMiniorIndigoFormChangeTable[] =
{
{FORM_CHANGE_BEGIN_WILD_ENCOUNTER, SPECIES_MINIOR_METEOR_INDIGO},
{FORM_CHANGE_BEGIN_BATTLE, SPECIES_MINIOR_CORE_INDIGO},
{FORM_CHANGE_BATTLE_HP_PERCENT_SEND_OUT, SPECIES_MINIOR_METEOR_INDIGO, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50},
{FORM_CHANGE_BATTLE_HP_PERCENT_SEND_OUT, SPECIES_MINIOR_CORE_INDIGO, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50},
@ -1566,6 +1569,7 @@ static const struct FormChange sMiniorIndigoFormChangeTable[] =
};
static const struct FormChange sMiniorOrangeFormChangeTable[] =
{
{FORM_CHANGE_BEGIN_WILD_ENCOUNTER, SPECIES_MINIOR_METEOR_ORANGE},
{FORM_CHANGE_BEGIN_BATTLE, SPECIES_MINIOR_CORE_ORANGE},
{FORM_CHANGE_BATTLE_HP_PERCENT_SEND_OUT, SPECIES_MINIOR_METEOR_ORANGE, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50},
{FORM_CHANGE_BATTLE_HP_PERCENT_SEND_OUT, SPECIES_MINIOR_CORE_ORANGE, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50},
@ -1578,6 +1582,7 @@ static const struct FormChange sMiniorOrangeFormChangeTable[] =
};
static const struct FormChange sMiniorVioletFormChangeTable[] =
{
{FORM_CHANGE_BEGIN_WILD_ENCOUNTER, SPECIES_MINIOR_METEOR_VIOLET},
{FORM_CHANGE_BEGIN_BATTLE, SPECIES_MINIOR_CORE_VIOLET},
{FORM_CHANGE_BATTLE_HP_PERCENT_SEND_OUT, SPECIES_MINIOR_METEOR_VIOLET, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50},
{FORM_CHANGE_BATTLE_HP_PERCENT_SEND_OUT, SPECIES_MINIOR_CORE_VIOLET, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50},
@ -1590,6 +1595,7 @@ static const struct FormChange sMiniorVioletFormChangeTable[] =
};
static const struct FormChange sMiniorYellowFormChangeTable[] =
{
{FORM_CHANGE_BEGIN_WILD_ENCOUNTER, SPECIES_MINIOR_METEOR_YELLOW},
{FORM_CHANGE_BEGIN_BATTLE, SPECIES_MINIOR_CORE_YELLOW},
{FORM_CHANGE_BATTLE_HP_PERCENT_SEND_OUT, SPECIES_MINIOR_METEOR_YELLOW, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50},
{FORM_CHANGE_BATTLE_HP_PERCENT_SEND_OUT, SPECIES_MINIOR_CORE_YELLOW, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50},

View File

@ -1197,7 +1197,7 @@ static void WarpToInitialPosition(u8 taskId)
static u16 GetDecorationElevation(u8 decoration, u8 tileIndex)
{
u16 elevation = -1;
u16 elevation = ELEVATION_INVALID;
switch (decoration)
{
case DECOR_STAND:
@ -1242,7 +1242,7 @@ static void ShowDecorationOnMap_(u16 mapX, u16 mapY, u8 decWidth, u8 decHeight,
overlapsWall = 0;
elevation = GetDecorationElevation(gDecorations[decoration].id, j * decWidth + i);
if (elevation != 0xFFFF)
if (elevation != ELEVATION_INVALID)
MapGridSetMetatileEntryAt(x, y, (gDecorations[decoration].tiles[j * decWidth + i] + (NUM_TILES_IN_PRIMARY | overlapsWall)) | impassableFlag | elevation);
else
MapGridSetMetatileIdAt(x, y, (gDecorations[decoration].tiles[j * decWidth + i] + (NUM_TILES_IN_PRIMARY | overlapsWall)) | impassableFlag);

View File

@ -3519,7 +3519,7 @@ u8 GetObjectEventIdByPosition(u16 x, u16 y, u8 elevation)
static bool8 ObjectEventDoesElevationMatch(struct ObjectEvent *objectEvent, u8 elevation)
{
if (objectEvent->currentElevation != 0 && elevation != 0 && objectEvent->currentElevation != elevation)
if (objectEvent->currentElevation != ELEVATION_TRANSITION && elevation != ELEVATION_TRANSITION && objectEvent->currentElevation != elevation)
return FALSE;
return TRUE;
@ -9983,12 +9983,12 @@ bool8 IsElevationMismatchAt(u8 elevation, s16 x, s16 y)
{
u8 mapElevation;
if (elevation == 0)
if (elevation == ELEVATION_TRANSITION)
return FALSE;
mapElevation = MapGridGetElevationAt(x, y);
if (mapElevation == 0 || mapElevation == 15)
if (mapElevation == ELEVATION_TRANSITION || mapElevation == ELEVATION_MULTI_LEVEL)
return FALSE;
if (mapElevation != elevation)
@ -10047,7 +10047,7 @@ void ObjectEventUpdateElevation(struct ObjectEvent *objEvent, struct Sprite *spr
u8 curElevation = MapGridGetElevationAt(objEvent->currentCoords.x, objEvent->currentCoords.y);
u8 prevElevation = MapGridGetElevationAt(objEvent->previousCoords.x, objEvent->previousCoords.y);
if (curElevation == 15 || prevElevation == 15)
if (curElevation == ELEVATION_MULTI_LEVEL || prevElevation == ELEVATION_MULTI_LEVEL)
{
// Ignore subsprite priorities under bridges
// so all subsprites will display below it
@ -10058,7 +10058,7 @@ void ObjectEventUpdateElevation(struct ObjectEvent *objEvent, struct Sprite *spr
objEvent->currentElevation = curElevation;
if (curElevation != 0 && curElevation != 15)
if (curElevation != ELEVATION_TRANSITION && curElevation != ELEVATION_MULTI_LEVEL)
objEvent->previousElevation = curElevation;
}
@ -10086,7 +10086,7 @@ static void ObjectEventUpdateSubpriority(struct ObjectEvent *objEvent, struct Sp
static bool8 AreElevationsCompatible(u8 a, u8 b)
{
if (a == 0 || b == 0)
if (a == ELEVATION_TRANSITION || b == ELEVATION_TRANSITION)
return TRUE;
if (a != b)

View File

@ -50,6 +50,9 @@ void FakeRtc_TickTimeForward(void)
void FakeRtc_AdvanceTimeBy(u32 days, u32 hours, u32 minutes, u32 seconds)
{
if (!OW_USE_FAKE_RTC)
return;
struct DateTime dateTime;
struct SiiRtcInfo *rtc = FakeRtc_GetCurrentTime();
@ -63,6 +66,9 @@ void FakeRtc_AdvanceTimeBy(u32 days, u32 hours, u32 minutes, u32 seconds)
void FakeRtc_ForwardTimeTo(u32 hour, u32 minute, u32 second)
{
if (!OW_USE_FAKE_RTC)
return;
Script_PauseFakeRtc();
struct Time diff, target;
struct SiiRtcInfo *fakeRtc = FakeRtc_GetCurrentTime();

View File

@ -268,10 +268,10 @@ static void GetInFrontOfPlayerPosition(struct MapPosition *position)
GetXYCoordsOneStepInFrontOfPlayer(&position->x, &position->y);
PlayerGetDestCoords(&x, &y);
if (MapGridGetElevationAt(x, y) != 0)
if (MapGridGetElevationAt(x, y) != ELEVATION_TRANSITION)
position->elevation = PlayerGetElevation();
else
position->elevation = 0;
position->elevation = ELEVATION_TRANSITION;
}
static u16 GetPlayerCurMetatileBehavior(int runningState)
@ -1114,7 +1114,7 @@ static s8 GetWarpEventAtPosition(struct MapHeader *mapHeader, u16 x, u16 y, u8 e
{
if ((u16)warpEvent->x == x && (u16)warpEvent->y == y)
{
if (warpEvent->elevation == elevation || warpEvent->elevation == 0)
if (warpEvent->elevation == elevation || warpEvent->elevation == ELEVATION_TRANSITION)
return i;
}
}
@ -1161,7 +1161,7 @@ static const u8 *GetCoordEventScriptAtPosition(struct MapHeader *mapHeader, u16
{
if ((u16)coordEvents[i].x == x && (u16)coordEvents[i].y == y)
{
if (coordEvents[i].elevation == elevation || coordEvents[i].elevation == 0)
if (coordEvents[i].elevation == elevation || coordEvents[i].elevation == ELEVATION_TRANSITION)
{
const u8 *script = TryRunCoordEventScript(&coordEvents[i]);
if (script != NULL)
@ -1187,7 +1187,7 @@ static const struct BgEvent *GetBackgroundEventAtPosition(struct MapHeader *mapH
{
if ((u16)bgEvents[i].x == x && (u16)bgEvents[i].y == y)
{
if (bgEvents[i].elevation == elevation || bgEvents[i].elevation == 0)
if (bgEvents[i].elevation == elevation || bgEvents[i].elevation == ELEVATION_TRANSITION)
return &bgEvents[i];
}
}

View File

@ -1289,7 +1289,7 @@ void SynchronizeSurfPosition(struct ObjectEvent *playerObj, struct Sprite *sprit
for (i = DIR_SOUTH; i <= DIR_EAST; i++, x = sprite->sPrevX, y = sprite->sPrevY)
{
MoveCoords(i, &x, &y);
if (MapGridGetElevationAt(x, y) == 3)
if (MapGridGetElevationAt(x, y) == ELEVATION_DEFAULT)
{
// While dismounting the surf blob bobs at a slower rate
sprite->sIntervalIdx++;

View File

@ -1013,9 +1013,9 @@ static enum Collision CheckForObjectEventStaticCollision(struct ObjectEvent *obj
static bool8 CanStopSurfing(s16 x, s16 y, enum Direction direction)
{
if ((gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING)
&& MapGridGetElevationAt(x, y) == 3
&& (GetObjectEventIdByPosition(x, y, 3) == OBJECT_EVENTS_COUNT
|| GetObjectEventIdByPosition(x, y, 3) == GetFollowerNPCObjectId()
&& MapGridGetElevationAt(x, y) == ELEVATION_DEFAULT
&& (GetObjectEventIdByPosition(x, y, ELEVATION_DEFAULT) == OBJECT_EVENTS_COUNT
|| GetObjectEventIdByPosition(x, y, ELEVATION_DEFAULT) == GetFollowerNPCObjectId()
))
{
CreateStopSurfingTask(direction);
@ -1663,7 +1663,7 @@ bool8 IsPlayerFacingSurfableFishableWater(void)
MoveCoords(playerObjEvent->facingDirection, &x, &y);
if (GetCollisionAtCoords(playerObjEvent, x, y, playerObjEvent->facingDirection) == COLLISION_ELEVATION_MISMATCH
&& PlayerGetElevation() == 3
&& PlayerGetElevation() == ELEVATION_DEFAULT
&& MetatileBehavior_IsSurfableFishableWater(MapGridGetMetatileBehaviorAt(x, y)))
return TRUE;
else
@ -1724,7 +1724,7 @@ void InitPlayerAvatar(s16 x, s16 y, enum Direction direction, enum Gender gender
playerObjEventTemplate.graphicsId = GetPlayerAvatarGraphicsIdByStateIdAndGender(PLAYER_AVATAR_STATE_NORMAL, gender);
playerObjEventTemplate.x = x - MAP_OFFSET;
playerObjEventTemplate.y = y - MAP_OFFSET;
playerObjEventTemplate.elevation = 0;
playerObjEventTemplate.elevation = ELEVATION_TRANSITION;
playerObjEventTemplate.movementType = MOVEMENT_TYPE_PLAYER;
playerObjEventTemplate.movementRangeX = 0;
playerObjEventTemplate.movementRangeY = 0;

View File

@ -1360,7 +1360,7 @@ void SpawnCameraObject(void)
LOCALID_CAMERA,
gSaveBlock1Ptr->pos.x + MAP_OFFSET,
gSaveBlock1Ptr->pos.y + MAP_OFFSET,
3); // elevation
ELEVATION_DEFAULT);
gObjectEvents[obj].invisible = TRUE;
CameraObjectSetFollowedSpriteId(gObjectEvents[obj].spriteId);
}

View File

@ -3149,7 +3149,7 @@ static const u8 *TryInteractWithPlayer(struct CableClubPlayer *player)
otherPlayerPos = player->pos;
otherPlayerPos.x += gDirectionToVectors[player->facing].x;
otherPlayerPos.y += gDirectionToVectors[player->facing].y;
otherPlayerPos.elevation = 0;
otherPlayerPos.elevation = ELEVATION_TRANSITION;
linkPlayerId = GetLinkPlayerIdAt(otherPlayerPos.x, otherPlayerPos.y);
if (linkPlayerId != MAX_LINK_PLAYERS)

View File

@ -6692,6 +6692,7 @@ u32 GetFormChangeTargetSpecies_Internal(struct FormChangeContext ctx)
case FORM_CHANGE_DEPOSIT:
case FORM_CHANGE_FAINT:
case FORM_CHANGE_DAYS_PASSED:
case FORM_CHANGE_BEGIN_WILD_ENCOUNTER:
targetSpecies = formChanges[i].targetSpecies;
break;
case FORM_CHANGE_STATUS:

View File

@ -28,8 +28,8 @@ enum
typedef struct MatchCallTextDataStruct {
const u8 *text;
u16 flag;
u16 flag2;
u16 availabilityFlag;
u16 flagToSetOnCompletion;
} match_call_text_data_t;
struct MatchCallStructCommon {
@ -157,21 +157,25 @@ static void MatchCall_BufferCallMessageText(const match_call_text_data_t *, u8 *
static void MatchCall_BufferCallMessageTextByRematchTeam(const match_call_text_data_t *, u16, u8 *);
static void MatchCall_GetNameAndDescByRematchIdx(u32, const u8 **, const u8 **);
#define ALWAYS_AVAILABLE 0xFFFF
#define NO_FLAG_TO_SET 0xFFFF
#define MATCH_CALL_TEXT_END {NULL, ALWAYS_AVAILABLE, NO_FLAG_TO_SET}
// .rodata
static const match_call_text_data_t sMrStoneTextScripts[] = {
{ MatchCall_Text_MrStone1, 0xFFFF, FLAG_ENABLE_MR_STONE_POKENAV },
{ MatchCall_Text_MrStone2, FLAG_ENABLE_MR_STONE_POKENAV, 0xFFFF },
{ MatchCall_Text_MrStone3, FLAG_DELIVERED_STEVEN_LETTER, 0xFFFF },
{ MatchCall_Text_MrStone4, FLAG_RECEIVED_EXP_SHARE, 0xFFFF },
{ MatchCall_Text_MrStone5, FLAG_RECEIVED_HM_STRENGTH, 0xFFFF },
{ MatchCall_Text_MrStone6, FLAG_DEFEATED_PETALBURG_GYM, 0xFFFF },
{ MatchCall_Text_MrStone7, FLAG_RECEIVED_CASTFORM, 0xFFFF },
{ MatchCall_Text_MrStone8, FLAG_GROUDON_AWAKENED_MAGMA_HIDEOUT, 0xFFFF },
{ MatchCall_Text_MrStone9, FLAG_TEAM_AQUA_ESCAPED_IN_SUBMARINE, 0xFFFF },
{ MatchCall_Text_MrStone10, FLAG_DEFEATED_SOOTOPOLIS_GYM, 0xFFFF },
{ MatchCall_Text_MrStone11, FLAG_SYS_GAME_CLEAR, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_MrStone1, ALWAYS_AVAILABLE, FLAG_ENABLE_MR_STONE_POKENAV },
{ MatchCall_Text_MrStone2, FLAG_ENABLE_MR_STONE_POKENAV, NO_FLAG_TO_SET },
{ MatchCall_Text_MrStone3, FLAG_DELIVERED_STEVEN_LETTER, NO_FLAG_TO_SET },
{ MatchCall_Text_MrStone4, FLAG_RECEIVED_EXP_SHARE, NO_FLAG_TO_SET },
{ MatchCall_Text_MrStone5, FLAG_RECEIVED_HM_STRENGTH, NO_FLAG_TO_SET },
{ MatchCall_Text_MrStone6, FLAG_DEFEATED_PETALBURG_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_MrStone7, FLAG_RECEIVED_CASTFORM, NO_FLAG_TO_SET },
{ MatchCall_Text_MrStone8, FLAG_GROUDON_AWAKENED_MAGMA_HIDEOUT, NO_FLAG_TO_SET },
{ MatchCall_Text_MrStone9, FLAG_TEAM_AQUA_ESCAPED_IN_SUBMARINE, NO_FLAG_TO_SET },
{ MatchCall_Text_MrStone10, FLAG_DEFEATED_SOOTOPOLIS_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_MrStone11, FLAG_SYS_GAME_CLEAR, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallStructNPC sMrStoneMatchCallHeader =
@ -185,16 +189,16 @@ static const struct MatchCallStructNPC sMrStoneMatchCallHeader =
};
static const match_call_text_data_t sNormanTextScripts[] = {
{ MatchCall_Text_Norman1, FLAG_ENABLE_NORMAN_MATCH_CALL, 0xFFFF },
{ MatchCall_Text_Norman2, FLAG_DEFEATED_DEWFORD_GYM, 0xFFFF },
{ MatchCall_Text_Norman3, FLAG_DEFEATED_LAVARIDGE_GYM, 0xFFFF },
{ MatchCall_Text_Norman4, FLAG_DEFEATED_PETALBURG_GYM, 0xFFFF },
{ MatchCall_Text_Norman5, FLAG_RECEIVED_RED_OR_BLUE_ORB, 0xFFFF },
{ MatchCall_Text_Norman6, 0xFFFE, 0xFFFF },
{ MatchCall_Text_Norman7, FLAG_SYS_GAME_CLEAR, 0xFFFF },
{ MatchCall_Text_Norman8, FLAG_SYS_GAME_CLEAR, 0xFFFF },
{ MatchCall_Text_Norman9, FLAG_SYS_GAME_CLEAR, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_Norman1, FLAG_ENABLE_NORMAN_MATCH_CALL, NO_FLAG_TO_SET },
{ MatchCall_Text_Norman2, FLAG_DEFEATED_DEWFORD_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_Norman3, FLAG_DEFEATED_LAVARIDGE_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_Norman4, FLAG_DEFEATED_PETALBURG_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_Norman5, FLAG_RECEIVED_RED_OR_BLUE_ORB, NO_FLAG_TO_SET },
{ MatchCall_Text_Norman6, 0xFFFE, NO_FLAG_TO_SET },
{ MatchCall_Text_Norman7, FLAG_SYS_GAME_CLEAR, NO_FLAG_TO_SET },
{ MatchCall_Text_Norman8, FLAG_SYS_GAME_CLEAR, NO_FLAG_TO_SET },
{ MatchCall_Text_Norman9, FLAG_SYS_GAME_CLEAR, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallStructTrainer sNormanMatchCallHeader =
@ -218,10 +222,10 @@ static const struct MatchCallBirch sProfBirchMatchCallHeader =
};
static const match_call_text_data_t sMomTextScripts[] = {
{ MatchCall_Text_Mom1, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Mom2, FLAG_DEFEATED_PETALBURG_GYM, 0xFFFF },
{ MatchCall_Text_Mom3, FLAG_SYS_GAME_CLEAR, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_Mom1, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Mom2, FLAG_DEFEATED_PETALBURG_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_Mom3, FLAG_SYS_GAME_CLEAR, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallStructNPC sMomMatchCallHeader =
@ -235,14 +239,14 @@ static const struct MatchCallStructNPC sMomMatchCallHeader =
};
static const match_call_text_data_t sStevenTextScripts[] = {
{ MatchCall_Text_Steven1, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Steven2, FLAG_RUSTURF_TUNNEL_OPENED, 0xFFFF },
{ MatchCall_Text_Steven3, FLAG_RECEIVED_RED_OR_BLUE_ORB, 0xFFFF },
{ MatchCall_Text_Steven4, FLAG_TEAM_AQUA_ESCAPED_IN_SUBMARINE, 0xFFFF },
{ MatchCall_Text_Steven5, FLAG_DEFEATED_MOSSDEEP_GYM, 0xFFFF },
{ MatchCall_Text_Steven6, FLAG_KYOGRE_ESCAPED_SEAFLOOR_CAVERN, 0xFFFF },
{ MatchCall_Text_Steven7, FLAG_SYS_GAME_CLEAR, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Steven1, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Steven2, FLAG_RUSTURF_TUNNEL_OPENED, NO_FLAG_TO_SET },
{ MatchCall_Text_Steven3, FLAG_RECEIVED_RED_OR_BLUE_ORB, NO_FLAG_TO_SET },
{ MatchCall_Text_Steven4, FLAG_TEAM_AQUA_ESCAPED_IN_SUBMARINE, NO_FLAG_TO_SET },
{ MatchCall_Text_Steven5, FLAG_DEFEATED_MOSSDEEP_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_Steven6, FLAG_KYOGRE_ESCAPED_SEAFLOOR_CAVERN, NO_FLAG_TO_SET },
{ MatchCall_Text_Steven7, FLAG_SYS_GAME_CLEAR, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END,
};
static const struct MatchCallStructNPC sStevenMatchCallHeader =
@ -258,22 +262,22 @@ static const struct MatchCallStructNPC sStevenMatchCallHeader =
static const u8 gText_MayBrendanMatchCallDesc[] = _("RAD NEIGHBOR");
static const match_call_text_data_t sMayTextScripts[] = {
{ MatchCall_Text_May1, 0xFFFF, 0xFFFF },
{ MatchCall_Text_May2, FLAG_DEFEATED_DEWFORD_GYM, 0xFFFF },
{ MatchCall_Text_May3, FLAG_DELIVERED_DEVON_GOODS, 0xFFFF },
{ MatchCall_Text_May4, FLAG_HIDE_MAUVILLE_CITY_WALLY, 0xFFFF },
{ MatchCall_Text_May5, FLAG_RECEIVED_HM_STRENGTH, 0xFFFF },
{ MatchCall_Text_May6, FLAG_DEFEATED_LAVARIDGE_GYM, 0xFFFF },
{ MatchCall_Text_May7, FLAG_DEFEATED_PETALBURG_GYM, 0xFFFF },
{ MatchCall_Text_May8, FLAG_RECEIVED_CASTFORM, 0xFFFF },
{ MatchCall_Text_May9, FLAG_RECEIVED_RED_OR_BLUE_ORB, 0xFFFF },
{ MatchCall_Text_May10, FLAG_GROUDON_AWAKENED_MAGMA_HIDEOUT, 0xFFFF },
{ MatchCall_Text_May11, FLAG_MET_TEAM_AQUA_HARBOR, 0xFFFF },
{ MatchCall_Text_May12, FLAG_TEAM_AQUA_ESCAPED_IN_SUBMARINE, 0xFFFF },
{ MatchCall_Text_May13, FLAG_KYOGRE_ESCAPED_SEAFLOOR_CAVERN, 0xFFFF },
{ MatchCall_Text_May14, FLAG_DEFEATED_SOOTOPOLIS_GYM, 0xFFFF },
{ MatchCall_Text_May15, FLAG_SYS_GAME_CLEAR, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_May1, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_May2, FLAG_DEFEATED_DEWFORD_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_May3, FLAG_DELIVERED_DEVON_GOODS, NO_FLAG_TO_SET },
{ MatchCall_Text_May4, FLAG_HIDE_MAUVILLE_CITY_WALLY, NO_FLAG_TO_SET },
{ MatchCall_Text_May5, FLAG_RECEIVED_HM_STRENGTH, NO_FLAG_TO_SET },
{ MatchCall_Text_May6, FLAG_DEFEATED_LAVARIDGE_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_May7, FLAG_DEFEATED_PETALBURG_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_May8, FLAG_RECEIVED_CASTFORM, NO_FLAG_TO_SET },
{ MatchCall_Text_May9, FLAG_RECEIVED_RED_OR_BLUE_ORB, NO_FLAG_TO_SET },
{ MatchCall_Text_May10, FLAG_GROUDON_AWAKENED_MAGMA_HIDEOUT, NO_FLAG_TO_SET },
{ MatchCall_Text_May11, FLAG_MET_TEAM_AQUA_HARBOR, NO_FLAG_TO_SET },
{ MatchCall_Text_May12, FLAG_TEAM_AQUA_ESCAPED_IN_SUBMARINE, NO_FLAG_TO_SET },
{ MatchCall_Text_May13, FLAG_KYOGRE_ESCAPED_SEAFLOOR_CAVERN, NO_FLAG_TO_SET },
{ MatchCall_Text_May14, FLAG_DEFEATED_SOOTOPOLIS_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_May15, FLAG_SYS_GAME_CLEAR, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallRival sMayMatchCallHeader =
@ -287,22 +291,22 @@ static const struct MatchCallRival sMayMatchCallHeader =
};
static const match_call_text_data_t sBrendanTextScripts[] = {
{ MatchCall_Text_Brendan1, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Brendan2, FLAG_DEFEATED_DEWFORD_GYM, 0xFFFF },
{ MatchCall_Text_Brendan3, FLAG_DELIVERED_DEVON_GOODS, 0xFFFF },
{ MatchCall_Text_Brendan4, FLAG_HIDE_MAUVILLE_CITY_WALLY, 0xFFFF },
{ MatchCall_Text_Brendan5, FLAG_RECEIVED_HM_STRENGTH, 0xFFFF },
{ MatchCall_Text_Brendan6, FLAG_DEFEATED_LAVARIDGE_GYM, 0xFFFF },
{ MatchCall_Text_Brendan7, FLAG_DEFEATED_PETALBURG_GYM, 0xFFFF },
{ MatchCall_Text_Brendan8, FLAG_RECEIVED_CASTFORM, 0xFFFF },
{ MatchCall_Text_Brendan9, FLAG_RECEIVED_RED_OR_BLUE_ORB, 0xFFFF },
{ MatchCall_Text_Brendan10, FLAG_GROUDON_AWAKENED_MAGMA_HIDEOUT, 0xFFFF },
{ MatchCall_Text_Brendan11, FLAG_MET_TEAM_AQUA_HARBOR, 0xFFFF },
{ MatchCall_Text_Brendan12, FLAG_TEAM_AQUA_ESCAPED_IN_SUBMARINE, 0xFFFF },
{ MatchCall_Text_Brendan13, FLAG_KYOGRE_ESCAPED_SEAFLOOR_CAVERN, 0xFFFF },
{ MatchCall_Text_Brendan14, FLAG_DEFEATED_SOOTOPOLIS_GYM, 0xFFFF },
{ MatchCall_Text_Brendan15, FLAG_SYS_GAME_CLEAR, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_Brendan1, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Brendan2, FLAG_DEFEATED_DEWFORD_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_Brendan3, FLAG_DELIVERED_DEVON_GOODS, NO_FLAG_TO_SET },
{ MatchCall_Text_Brendan4, FLAG_HIDE_MAUVILLE_CITY_WALLY, NO_FLAG_TO_SET },
{ MatchCall_Text_Brendan5, FLAG_RECEIVED_HM_STRENGTH, NO_FLAG_TO_SET },
{ MatchCall_Text_Brendan6, FLAG_DEFEATED_LAVARIDGE_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_Brendan7, FLAG_DEFEATED_PETALBURG_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_Brendan8, FLAG_RECEIVED_CASTFORM, NO_FLAG_TO_SET },
{ MatchCall_Text_Brendan9, FLAG_RECEIVED_RED_OR_BLUE_ORB, NO_FLAG_TO_SET },
{ MatchCall_Text_Brendan10, FLAG_GROUDON_AWAKENED_MAGMA_HIDEOUT, NO_FLAG_TO_SET },
{ MatchCall_Text_Brendan11, FLAG_MET_TEAM_AQUA_HARBOR, NO_FLAG_TO_SET },
{ MatchCall_Text_Brendan12, FLAG_TEAM_AQUA_ESCAPED_IN_SUBMARINE, NO_FLAG_TO_SET },
{ MatchCall_Text_Brendan13, FLAG_KYOGRE_ESCAPED_SEAFLOOR_CAVERN, NO_FLAG_TO_SET },
{ MatchCall_Text_Brendan14, FLAG_DEFEATED_SOOTOPOLIS_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_Brendan15, FLAG_SYS_GAME_CLEAR, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallRival sBrendanMatchCallHeader =
@ -316,14 +320,14 @@ static const struct MatchCallRival sBrendanMatchCallHeader =
};
static const match_call_text_data_t sWallyTextScripts[] = {
{ MatchCall_Text_Wally1, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Wally2, FLAG_RUSTURF_TUNNEL_OPENED, 0xFFFF },
{ MatchCall_Text_Wally3, FLAG_DEFEATED_LAVARIDGE_GYM, 0xFFFF },
{ MatchCall_Text_Wally4, FLAG_RECEIVED_CASTFORM, 0xFFFF },
{ MatchCall_Text_Wally5, FLAG_GROUDON_AWAKENED_MAGMA_HIDEOUT, 0xFFFF },
{ MatchCall_Text_Wally6, FLAG_KYOGRE_ESCAPED_SEAFLOOR_CAVERN, 0xFFFF },
{ MatchCall_Text_Wally7, FLAG_DEFEATED_WALLY_VICTORY_ROAD, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_Wally1, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Wally2, FLAG_RUSTURF_TUNNEL_OPENED, NO_FLAG_TO_SET },
{ MatchCall_Text_Wally3, FLAG_DEFEATED_LAVARIDGE_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_Wally4, FLAG_RECEIVED_CASTFORM, NO_FLAG_TO_SET },
{ MatchCall_Text_Wally5, FLAG_GROUDON_AWAKENED_MAGMA_HIDEOUT, NO_FLAG_TO_SET },
{ MatchCall_Text_Wally6, FLAG_KYOGRE_ESCAPED_SEAFLOOR_CAVERN, NO_FLAG_TO_SET },
{ MatchCall_Text_Wally7, FLAG_DEFEATED_WALLY_VICTORY_ROAD, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallLocationOverride sWallyLocationData[] = {
@ -345,14 +349,14 @@ static const struct MatchCallWally sWallyMatchCallHeader =
};
static const match_call_text_data_t sScottTextScripts[] = {
{ MatchCall_Text_Scott1, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Scott2, FLAG_DEFEATED_EVIL_TEAM_MT_CHIMNEY, 0xFFFF },
{ MatchCall_Text_Scott3, FLAG_RECEIVED_CASTFORM, 0xFFFF },
{ MatchCall_Text_Scott4, FLAG_RECEIVED_RED_OR_BLUE_ORB, 0xFFFF },
{ MatchCall_Text_Scott5, FLAG_TEAM_AQUA_ESCAPED_IN_SUBMARINE, 0xFFFF },
{ MatchCall_Text_Scott6, FLAG_DEFEATED_SOOTOPOLIS_GYM, 0xFFFF },
{ MatchCall_Text_Scott7, FLAG_SYS_GAME_CLEAR, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_Scott1, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Scott2, FLAG_DEFEATED_EVIL_TEAM_MT_CHIMNEY, NO_FLAG_TO_SET },
{ MatchCall_Text_Scott3, FLAG_RECEIVED_CASTFORM, NO_FLAG_TO_SET },
{ MatchCall_Text_Scott4, FLAG_RECEIVED_RED_OR_BLUE_ORB, NO_FLAG_TO_SET },
{ MatchCall_Text_Scott5, FLAG_TEAM_AQUA_ESCAPED_IN_SUBMARINE, NO_FLAG_TO_SET },
{ MatchCall_Text_Scott6, FLAG_DEFEATED_SOOTOPOLIS_GYM, NO_FLAG_TO_SET },
{ MatchCall_Text_Scott7, FLAG_SYS_GAME_CLEAR, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
@ -367,11 +371,11 @@ static const struct MatchCallStructNPC sScottMatchCallHeader =
};
static const match_call_text_data_t sRoxanneTextScripts[] = {
{ MatchCall_Text_Roxanne1, 0xFFFE, 0xFFFF },
{ MatchCall_Text_Roxanne2, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Roxanne3, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Roxanne4, FLAG_SYS_GAME_CLEAR, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_Roxanne1, 0xFFFE, NO_FLAG_TO_SET },
{ MatchCall_Text_Roxanne2, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Roxanne3, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Roxanne4, FLAG_SYS_GAME_CLEAR, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallStructTrainer sRoxanneMatchCallHeader =
@ -386,11 +390,11 @@ static const struct MatchCallStructTrainer sRoxanneMatchCallHeader =
};
static const match_call_text_data_t sBrawlyTextScripts[] = {
{ MatchCall_Text_Brawly1, 0xFFFE, 0xFFFF },
{ MatchCall_Text_Brawly2, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Brawly3, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Brawly4, FLAG_SYS_GAME_CLEAR, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_Brawly1, 0xFFFE, NO_FLAG_TO_SET },
{ MatchCall_Text_Brawly2, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Brawly3, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Brawly4, FLAG_SYS_GAME_CLEAR, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallStructTrainer sBrawlyMatchCallHeader =
@ -405,11 +409,11 @@ static const struct MatchCallStructTrainer sBrawlyMatchCallHeader =
};
static const match_call_text_data_t sWattsonTextScripts[] = {
{ MatchCall_Text_Wattson1, 0xFFFE, 0xFFFF },
{ MatchCall_Text_Wattson2, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Wattson3, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Wattson4, FLAG_SYS_GAME_CLEAR, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_Wattson1, 0xFFFE, NO_FLAG_TO_SET },
{ MatchCall_Text_Wattson2, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Wattson3, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Wattson4, FLAG_SYS_GAME_CLEAR, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallStructTrainer sWattsonMatchCallHeader =
@ -424,11 +428,11 @@ static const struct MatchCallStructTrainer sWattsonMatchCallHeader =
};
static const match_call_text_data_t sFlanneryTextScripts[] = {
{ MatchCall_Text_Flannery1, 0xFFFE, 0xFFFF },
{ MatchCall_Text_Flannery2, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Flannery3, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Flannery4, FLAG_SYS_GAME_CLEAR, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_Flannery1, 0xFFFE, NO_FLAG_TO_SET },
{ MatchCall_Text_Flannery2, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Flannery3, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Flannery4, FLAG_SYS_GAME_CLEAR, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallStructTrainer sFlanneryMatchCallHeader =
@ -443,11 +447,11 @@ static const struct MatchCallStructTrainer sFlanneryMatchCallHeader =
};
static const match_call_text_data_t sWinonaTextScripts[] = {
{ MatchCall_Text_Winona1, 0xFFFE, 0xFFFF },
{ MatchCall_Text_Winona2, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Winona3, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Winona4, FLAG_SYS_GAME_CLEAR, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_Winona1, 0xFFFE, NO_FLAG_TO_SET },
{ MatchCall_Text_Winona2, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Winona3, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Winona4, FLAG_SYS_GAME_CLEAR, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallStructTrainer sWinonaMatchCallHeader =
@ -462,11 +466,11 @@ static const struct MatchCallStructTrainer sWinonaMatchCallHeader =
};
static const match_call_text_data_t sTateLizaTextScripts[] = {
{ MatchCall_Text_TateLiza1, 0xFFFE, 0xFFFF },
{ MatchCall_Text_TateLiza2, 0xFFFF, 0xFFFF },
{ MatchCall_Text_TateLiza3, 0xFFFF, 0xFFFF },
{ MatchCall_Text_TateLiza4, FLAG_SYS_GAME_CLEAR, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_TateLiza1, 0xFFFE, NO_FLAG_TO_SET },
{ MatchCall_Text_TateLiza2, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_TateLiza3, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_TateLiza4, FLAG_SYS_GAME_CLEAR, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallStructTrainer sTateLizaMatchCallHeader =
@ -481,11 +485,11 @@ static const struct MatchCallStructTrainer sTateLizaMatchCallHeader =
};
static const match_call_text_data_t sJuanTextScripts[] = {
{ MatchCall_Text_Juan1, 0xFFFE, 0xFFFF },
{ MatchCall_Text_Juan2, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Juan3, 0xFFFF, 0xFFFF },
{ MatchCall_Text_Juan4, FLAG_SYS_GAME_CLEAR, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_Juan1, 0xFFFE, NO_FLAG_TO_SET },
{ MatchCall_Text_Juan2, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Juan3, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
{ MatchCall_Text_Juan4, FLAG_SYS_GAME_CLEAR, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallStructTrainer sJuanMatchCallHeader =
@ -502,8 +506,8 @@ static const struct MatchCallStructTrainer sJuanMatchCallHeader =
static const u8 gText_EliteFourMatchCallDesc[] = _("ELITE FOUR");
static const match_call_text_data_t sSidneyTextScripts[] = {
{ MatchCall_Text_Sidney, 0xFFFF, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_Sidney, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallStructTrainer sSidneyMatchCallHeader =
@ -518,8 +522,8 @@ static const struct MatchCallStructTrainer sSidneyMatchCallHeader =
};
static const match_call_text_data_t sPhoebeTextScripts[] = {
{ MatchCall_Text_Phoebe, 0xFFFF, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_Phoebe, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallStructTrainer sPhoebeMatchCallHeader =
@ -534,8 +538,8 @@ static const struct MatchCallStructTrainer sPhoebeMatchCallHeader =
};
static const match_call_text_data_t sGlaciaTextScripts[] = {
{ MatchCall_Text_Glacia, 0xFFFF, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_Glacia, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallStructTrainer sGlaciaMatchCallHeader =
@ -550,8 +554,8 @@ static const struct MatchCallStructTrainer sGlaciaMatchCallHeader =
};
static const match_call_text_data_t sDrakeTextScripts[] = {
{ MatchCall_Text_Drake, 0xFFFF, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_Drake, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallStructTrainer sDrakeMatchCallHeader =
@ -566,8 +570,8 @@ static const struct MatchCallStructTrainer sDrakeMatchCallHeader =
};
static const match_call_text_data_t sWallaceTextScripts[] = {
{ MatchCall_Text_Wallace, 0xFFFF, 0xFFFF },
{ NULL, 0xFFFF, 0xFFFF }
{ MatchCall_Text_Wallace, ALWAYS_AVAILABLE, NO_FLAG_TO_SET },
MATCH_CALL_TEXT_END
};
static const struct MatchCallStructTrainer sWallaceMatchCallHeader =
@ -1018,12 +1022,12 @@ static void MatchCall_BufferCallMessageText(const match_call_text_data_t *textDa
i--;
while (i)
{
if (textData[i].flag != 0xFFFF && FlagGet(textData[i].flag) == TRUE)
if (textData[i].availabilityFlag != ALWAYS_AVAILABLE && FlagGet(textData[i].availabilityFlag) == TRUE)
break;
i--;
}
if (textData[i].flag2 != 0xFFFF)
FlagSet(textData[i].flag2);
if (textData[i].flagToSetOnCompletion != NO_FLAG_TO_SET)
FlagSet(textData[i].flagToSetOnCompletion);
StringExpandPlaceholders(dest, textData[i].text);
}
@ -1033,17 +1037,17 @@ static void MatchCall_BufferCallMessageTextByRematchTeam(const match_call_text_d
u32 i;
for (i = 0; textData[i].text != NULL; i++)
{
if (textData[i].flag == 0xFFFE)
if (textData[i].availabilityFlag == 0xFFFE)
break;
if (textData[i].flag != 0xFFFF && !FlagGet(textData[i].flag))
if (textData[i].availabilityFlag != ALWAYS_AVAILABLE && !FlagGet(textData[i].availabilityFlag))
break;
}
if (textData[i].flag != 0xFFFE)
if (textData[i].availabilityFlag != 0xFFFE)
{
if (i)
i--;
if (textData[i].flag2 != 0xFFFF)
FlagSet(textData[i].flag2);
if (textData[i].flagToSetOnCompletion != NO_FLAG_TO_SET)
FlagSet(textData[i].flagToSetOnCompletion);
StringExpandPlaceholders(dest, textData[i].text);
}
else

View File

@ -351,7 +351,8 @@ void RtcCalcLocalTimeOffset(s32 days, s32 hours, s32 minutes, s32 seconds)
gLocalTime.hours = hours;
gLocalTime.minutes = minutes;
gLocalTime.seconds = seconds;
FakeRtc_ManuallySetTime(gLocalTime.days, gLocalTime.hours, gLocalTime.minutes, seconds);
if (!OW_USE_FAKE_RTC)
FakeRtc_ManuallySetTime(gLocalTime.days, gLocalTime.hours, gLocalTime.minutes, seconds);
RtcGetInfo(&sRtc);
RtcCalcTimeDifference(&sRtc, &gSaveBlock2Ptr->localTimeOffset, &gLocalTime);
}

View File

@ -3257,6 +3257,9 @@ bool8 ScrCmd_fwdtime(struct ScriptContext *ctx)
bool8 ScrCmd_fwdweekday(struct ScriptContext *ctx)
{
if (!OW_USE_FAKE_RTC)
return FALSE;
struct SiiRtcInfo *rtc = FakeRtc_GetCurrentTime();
u32 weekdayTarget = ScriptReadWord(ctx);

View File

@ -263,7 +263,7 @@ static const u8 *const sModeStrings[NUM_TRAINER_HILL_MODES] =
static const struct ObjectEventTemplate sTrainerObjectEventTemplate =
{
.graphicsId = OBJ_EVENT_GFX_RIVAL_BRENDAN_NORMAL,
.elevation = 3,
.elevation = ELEVATION_DEFAULT,
.movementType = MOVEMENT_TYPE_LOOK_AROUND,
.movementRangeX = 1,
.movementRangeY = 1,
@ -716,7 +716,7 @@ static u16 GetMapDataForFloor(u8 floorId, u32 x, u32 y, u32 floorWidth) // floor
impassable = (sHillData->floors[floorId].map.collisionData[y] >> (15 - x) & 1);
metatileId = sHillData->floors[floorId].map.metatileData[floorWidth * y + x] + NUM_METATILES_IN_PRIMARY;
elevation = PACK_ELEVATION(3);
elevation = PACK_ELEVATION(ELEVATION_DEFAULT);
return PACK_COLLISION(impassable) | elevation | PACK_METATILE(metatileId);
}

View File

@ -61,4 +61,39 @@ SINGLE_BATTLE_TEST("(TERA) Terastallizing into the same type with Adaptability g
}
}
TO_DO_BATTLE_TEST("Adaptability does not affect Stellar-type moves");
SINGLE_BATTLE_TEST("(TERA) Adaptability does not increase non-Tera base STAB beyond 1.5x", s16 damage)
{
u32 move;
PARAMETRIZE { move = MOVE_GUST; }
PARAMETRIZE { move = MOVE_WATER_GUN; }
GIVEN {
PLAYER(SPECIES_CRAWDAUNT) { Ability(ABILITY_ADAPTABILITY); TeraType(TYPE_NORMAL); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, move, gimmick: GIMMICK_TERA); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
// With Adaptability, non-Tera base type should still be 1.5x STAB (not 2.0x).
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
}
}
SINGLE_BATTLE_TEST("(TERA) Adaptability does not affect Stellar-type moves", s16 damage)
{
u32 ability;
PARAMETRIZE { ability = ABILITY_HYPER_CUTTER; }
PARAMETRIZE { ability = ABILITY_ADAPTABILITY; }
GIVEN {
PLAYER(SPECIES_CRAWDAUNT) { Ability(ability); TeraType(TYPE_STELLAR); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_TERA_BLAST, gimmick: GIMMICK_TERA); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TERA_BLAST, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_EQ(results[0].damage, results[1].damage);
}
}

View File

@ -1,4 +1,45 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("TODO: Write Hadron Engine (Ability) test titles")
SINGLE_BATTLE_TEST("Hadron Engine creates Electric Terrain when entering the battle")
{
GIVEN {
PLAYER(SPECIES_MIRAIDON) { Ability(ABILITY_HADRON_ENGINE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {}
} SCENE {
ABILITY_POPUP(player, ABILITY_HADRON_ENGINE);
MESSAGE("An electric current ran across the battlefield!");
}
}
SINGLE_BATTLE_TEST("Hadron Engine boosts the Pokemon's Special Attack on Electric Terrain even if not grounded", s16 damage)
{
bool32 overrideTerrain, airBalloon;
PARAMETRIZE { airBalloon = FALSE; overrideTerrain = TRUE; }
PARAMETRIZE { airBalloon = FALSE; overrideTerrain = FALSE; }
PARAMETRIZE { airBalloon = TRUE; overrideTerrain = TRUE; }
PARAMETRIZE { airBalloon = TRUE; overrideTerrain = FALSE; }
GIVEN {
ASSUME(gItemsInfo[ITEM_AIR_BALLOON].holdEffect == HOLD_EFFECT_AIR_BALLOON);
ASSUME(GetMoveEffect(MOVE_GRASSY_TERRAIN) == EFFECT_GRASSY_TERRAIN);
ASSUME(GetMoveCategory(MOVE_POWER_GEM) == DAMAGE_CATEGORY_SPECIAL);
PLAYER(SPECIES_MIRAIDON) { Ability(ABILITY_HADRON_ENGINE); Moves(MOVE_POWER_GEM, MOVE_CELEBRATE); Item(airBalloon ? ITEM_AIR_BALLOON : ITEM_NONE); Speed(1); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_GRASSY_TERRAIN, MOVE_CELEBRATE); Speed(2); }
} WHEN {
if (overrideTerrain)
TURN { MOVE(opponent, MOVE_GRASSY_TERRAIN); }
TURN { MOVE(player, MOVE_POWER_GEM); }
} SCENE {
if (overrideTerrain)
ANIMATION(ANIM_TYPE_MOVE, MOVE_GRASSY_TERRAIN, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWER_GEM, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.3333), results[1].damage);
EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.3333), results[3].damage);
}
}

View File

@ -134,6 +134,23 @@ SINGLE_BATTLE_TEST("Protosynthesis prioritizes stats in the case of a tie in the
}
}
SINGLE_BATTLE_TEST("Protosynthesis uses Wonder Room swapped defenses when choosing boosted stat")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_WONDER_ROOM) == EFFECT_WONDER_ROOM);
PLAYER(SPECIES_ROARING_MOON) { Ability(ABILITY_PROTOSYNTHESIS); Attack(50); Defense(200); SpAttack(40); SpDefense(60); Speed(70); Moves(MOVE_WONDER_ROOM); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SUNNY_DAY); Speed(60); }
} WHEN {
TURN { MOVE(player, MOVE_WONDER_ROOM); MOVE(opponent, MOVE_SUNNY_DAY); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_WONDER_ROOM, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, opponent);
ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS);
MESSAGE("The harsh sunlight activated Roaring Moon's Protosynthesis!");
MESSAGE("Roaring Moon's Sp. Def was heightened!");
}
}
SINGLE_BATTLE_TEST("Protosynthesis activates in Sun before Booster Energy")
{
GIVEN {

View File

@ -201,6 +201,23 @@ SINGLE_BATTLE_TEST("Quark Drive prioritizes stats in the case of a tie in the fo
}
}
SINGLE_BATTLE_TEST("Quark Drive uses Wonder Room swapped defenses when choosing boosted stat")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_WONDER_ROOM) == EFFECT_WONDER_ROOM);
PLAYER(SPECIES_IRON_LEAVES) { Ability(ABILITY_QUARK_DRIVE); Attack(50); Defense(200); SpAttack(40); SpDefense(60); Speed(70); Moves(MOVE_WONDER_ROOM); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_ELECTRIC_TERRAIN); Speed(60); }
} WHEN {
TURN { MOVE(player, MOVE_WONDER_ROOM); MOVE(opponent, MOVE_ELECTRIC_TERRAIN); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_WONDER_ROOM, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, opponent);
ABILITY_POPUP(player, ABILITY_QUARK_DRIVE);
MESSAGE("The Electric Terrain activated Iron Leaves's Quark Drive!");
MESSAGE("Iron Leaves's Sp. Def was heightened!");
}
}
SINGLE_BATTLE_TEST("Quark Drive activates in Electric Terrain before Booster Energy")
{
GIVEN {

View File

@ -75,3 +75,39 @@ SINGLE_BATTLE_TEST("Shields Down protects Minior Meteor from status conditions")
EXPECT(opponent->status1 & STATUS1_BURN);
}
}
WILD_BATTLE_TEST("Wild Minior appear in Meteor form without transforming")// To be replaced with WILD_DOUBLE_BATTLE_TEST when that is made possible.
{
GIVEN {
PLAYER(SPECIES_MINIOR_CORE) { Ability(ABILITY_SHIELDS_DOWN); }
OPPONENT(SPECIES_MINIOR_CORE) { Ability(ABILITY_SHIELDS_DOWN); }
} WHEN {
TURN {}
} SCENE {
ABILITY_POPUP(player, ABILITY_SHIELDS_DOWN);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player);
NONE_OF {
ABILITY_POPUP(opponent, ABILITY_SHIELDS_DOWN);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, opponent);
}
} THEN {
EXPECT_EQ(opponent->species, SPECIES_MINIOR_METEOR);
EXPECT_EQ(player->species, SPECIES_MINIOR_METEOR);
}
}
SINGLE_BATTLE_TEST("Trainers' Minior appear in Core form")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET)
OPPONENT(SPECIES_MINIOR_METEOR) { Ability(ABILITY_SHIELDS_DOWN); }
} WHEN {
TURN {}
} SCENE {
ABILITY_POPUP(opponent, ABILITY_SHIELDS_DOWN);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, opponent);
} THEN {
EXPECT_EQ(opponent->species, SPECIES_MINIOR_METEOR);
}
}

View File

@ -997,6 +997,7 @@ DOUBLE_BATTLE_TEST("Dynamax: G-Max Volt Crash paralyzes both opponents")
TURN { MOVE(playerLeft, MOVE_THUNDERBOLT, target: opponentLeft, gimmick: GIMMICK_DYNAMAX); }
} SCENE {
MESSAGE("Pikachu used G-Max Volt Crash!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_G_MAX_VOLT_CRASH, playerLeft);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponentLeft);
MESSAGE("The opposing Wobbuffet is paralyzed, so it may be unable to move!");
STATUS_ICON(opponentLeft, paralysis: TRUE);
@ -1309,6 +1310,7 @@ DOUBLE_BATTLE_TEST("Dynamax: G-Max Replenish recycles allies' berries 50\% of th
PASSES_RANDOMLY(1, 2, RNG_G_MAX_REPLENISH);
GIVEN {
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_REPLENISH, MOVE_EFFECT_RECYCLE_BERRIES));
ASSUME(GetItemHoldEffect(ITEM_APICOT_BERRY) == HOLD_EFFECT_SP_DEFENSE_UP);
PLAYER(SPECIES_SNORLAX) { Item(ITEM_APICOT_BERRY); GigantamaxFactor(TRUE); }
PLAYER(SPECIES_MUNCHLAX) { Item(ITEM_APICOT_BERRY); Ability(ABILITY_THICK_FAT); }
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_APICOT_BERRY); }
@ -1321,12 +1323,14 @@ DOUBLE_BATTLE_TEST("Dynamax: G-Max Replenish recycles allies' berries 50\% of th
TURN { MOVE(playerLeft, MOVE_SCRATCH, target: opponentLeft, gimmick: GIMMICK_DYNAMAX); }
} SCENE {
// turn 1
MESSAGE("Using Apicot Berry, the Sp. Def of Snorlax rose!");
MESSAGE("Using Apicot Berry, the Sp. Def of Munchlax rose!");
MESSAGE("Using Apicot Berry, the Sp. Def of the opposing Wobbuffet rose!");
MESSAGE("Using Apicot Berry, the Sp. Def of the opposing Wobbuffet rose!");
// turn 2
MESSAGE("Snorlax used G-Max Replenish!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_G_MAX_REPLENISH, playerLeft);
MESSAGE("Snorlax found one Apicot Berry!");
MESSAGE("Munchlax found one Apicot Berry!");
}
@ -1369,6 +1373,7 @@ DOUBLE_BATTLE_TEST("Dynamax: G-Max Finale heals allies by 1/6 of their health")
TURN { MOVE(playerLeft, MOVE_MOONBLAST, target: opponentLeft, gimmick: GIMMICK_DYNAMAX); }
} SCENE {
MESSAGE("Alcremie used G-Max Finale!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_G_MAX_FINALE, playerLeft);
HP_BAR(playerLeft, captureDamage: &damage1);
HP_BAR(playerRight, captureDamage: &damage2);
} THEN {
@ -1713,5 +1718,81 @@ DOUBLE_BATTLE_TEST("Dynamax stat raising moves don't make stat-changing abilitie
}
}
DOUBLE_BATTLE_TEST("Dynamax: G-Max Finale heals allies by 1/6 of their health, even if it faints the foe")
{
s16 damage1, damage2;
GIVEN {
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_FINALE, MOVE_EFFECT_HEAL_TEAM));
PLAYER(SPECIES_ALCREMIE) { HP(1); GigantamaxFactor(TRUE); }
PLAYER(SPECIES_MILCERY) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_MOONBLAST, target: opponentLeft, gimmick: GIMMICK_DYNAMAX); SEND_OUT(opponentLeft, 2); }
} SCENE {
MESSAGE("Alcremie used G-Max Finale!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_G_MAX_FINALE, playerLeft);
HP_BAR(playerLeft, captureDamage: &damage1);
HP_BAR(playerRight, captureDamage: &damage2);
} THEN {
EXPECT_MUL_EQ(-damage1, Q_4_12(6), playerLeft->maxHP); // heals based on Dynamax HP. Appears to have a problem with milcery in this case!?
}
}
DOUBLE_BATTLE_TEST("Dynamax: G-Max Replenish recycles allies' berries 50\% of the time, even if it faints the foe")
{
PASSES_RANDOMLY(1, 2, RNG_G_MAX_REPLENISH);
GIVEN {
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_REPLENISH, MOVE_EFFECT_RECYCLE_BERRIES));
ASSUME(GetItemHoldEffect(ITEM_APICOT_BERRY) == HOLD_EFFECT_SP_DEFENSE_UP);
PLAYER(SPECIES_SNORLAX) { Item(ITEM_APICOT_BERRY); GigantamaxFactor(TRUE); }
PLAYER(SPECIES_MUNCHLAX) { Item(ITEM_APICOT_BERRY); Ability(ABILITY_THICK_FAT); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_STUFF_CHEEKS); \
MOVE(playerRight, MOVE_STUFF_CHEEKS); \
MOVE(opponentLeft, MOVE_CELEBRATE); \
MOVE(opponentRight, MOVE_CELEBRATE); }
TURN { MOVE(playerLeft, MOVE_SCRATCH, target: opponentLeft, gimmick: GIMMICK_DYNAMAX); SEND_OUT(opponentLeft, 2);}
} SCENE {
// turn 1
MESSAGE("Using Apicot Berry, the Sp. Def of Snorlax rose!");
MESSAGE("Using Apicot Berry, the Sp. Def of Munchlax rose!");
// turn 2
MESSAGE("Snorlax used G-Max Replenish!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_G_MAX_REPLENISH, playerLeft);
MESSAGE("Snorlax found one Apicot Berry!");
MESSAGE("Munchlax found one Apicot Berry!");
}
}
DOUBLE_BATTLE_TEST("Dynamax: G-Max Volt Crash paralyzes other opponent even if its target faints")
{
GIVEN {
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_VOLT_CRASH, MOVE_EFFECT_PARALYZE_SIDE));
PLAYER(SPECIES_PIKACHU) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_PICHU);
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_WYNAUT);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(playerLeft, MOVE_THUNDERBOLT, target: opponentLeft, gimmick: GIMMICK_DYNAMAX); SEND_OUT(opponentLeft, 2); }
} SCENE {
MESSAGE("Pikachu used G-Max Volt Crash!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_G_MAX_VOLT_CRASH, playerLeft);
NONE_OF {
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponentLeft);
STATUS_ICON(opponentLeft, paralysis: TRUE);
}
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponentRight);
MESSAGE("The opposing Wynaut is paralyzed, so it may be unable to move!");
STATUS_ICON(opponentRight, paralysis: TRUE);
}
}
TO_DO_BATTLE_TEST("Dynamax: Contrary inverts stat-lowering Max Moves, without showing a message")
TO_DO_BATTLE_TEST("Dynamax: Contrary inverts stat-increasing Max Moves, without showing a message")

View File

@ -35,6 +35,38 @@ SINGLE_BATTLE_TEST("Ability Shield protects against Neutralizing Gas")
}
}
DOUBLE_BATTLE_TEST("Ability Shield prevents Intimidate from reactivating after Neutralizing Gas ends")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(5); }
PLAYER(SPECIES_WYNAUT) { Speed(4); }
OPPONENT(SPECIES_KOFFING) { Ability(ABILITY_NEUTRALIZING_GAS); HP(1); Speed(1); }
OPPONENT(SPECIES_GYARADOS) { Ability(ABILITY_INTIMIDATE); Item(ITEM_ABILITY_SHIELD); Speed(3); }
} WHEN {
TURN { MOVE(playerLeft, MOVE_SCRATCH, target: opponentLeft); }
} SCENE {
ABILITY_POPUP(opponentLeft, ABILITY_NEUTRALIZING_GAS);
MESSAGE("Neutralizing gas filled the area!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentRight);
MESSAGE("The opposing Gyarados's Ability is protected by the effects of its Ability Shield!");
ABILITY_POPUP(opponentRight, ABILITY_INTIMIDATE);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, playerLeft);
HP_BAR(opponentLeft);
MESSAGE("The effects of the neutralizing gas wore off!");
NONE_OF {
ABILITY_POPUP(opponentRight, ABILITY_INTIMIDATE);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
}
MESSAGE("The opposing Koffing fainted!");
} THEN {
EXPECT_EQ(playerLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1);
EXPECT_EQ(playerRight->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1);
}
}
SINGLE_BATTLE_TEST("Ability Shield protects against Mold Breaker (no message)")
{
enum Item item;

View File

@ -1,4 +1,82 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("TODO: Write Eviolite (Hold Effect) test titles")
ASSUMPTIONS
{
ASSUME(gItemsInfo[ITEM_EVIOLITE].holdEffect == HOLD_EFFECT_EVIOLITE);
}
SINGLE_BATTLE_TEST("Eviolite boosts Defense and Sp. Def for unevolved Pokemon", s16 damage)
{
u16 move;
u32 item;
PARAMETRIZE { move = MOVE_SCRATCH; item = ITEM_EVIOLITE; }
PARAMETRIZE { move = MOVE_SCRATCH; item = ITEM_NONE; }
PARAMETRIZE { move = MOVE_WATER_GUN; item = ITEM_EVIOLITE; }
PARAMETRIZE { move = MOVE_WATER_GUN; item = ITEM_NONE; }
GIVEN {
ASSUME(GetMoveCategory(MOVE_SCRATCH) == DAMAGE_CATEGORY_PHYSICAL);
ASSUME(GetMoveCategory(MOVE_WATER_GUN) == DAMAGE_CATEGORY_SPECIAL);
PLAYER(SPECIES_PIKACHU) { Item(item); }
OPPONENT(SPECIES_MAGIKARP) { Moves(MOVE_SCRATCH, MOVE_WATER_GUN); }
} WHEN {
TURN { MOVE(opponent, move); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[3].damage);
}
}
SINGLE_BATTLE_TEST("Eviolite does not boost Defense or Sp. Def for evolved Pokemon", s16 damage)
{
u16 move;
u32 item;
PARAMETRIZE { move = MOVE_SCRATCH; item = ITEM_EVIOLITE; }
PARAMETRIZE { move = MOVE_SCRATCH; item = ITEM_NONE; }
PARAMETRIZE { move = MOVE_WATER_GUN; item = ITEM_EVIOLITE; }
PARAMETRIZE { move = MOVE_WATER_GUN; item = ITEM_NONE; }
GIVEN {
ASSUME(GetMoveCategory(MOVE_SCRATCH) == DAMAGE_CATEGORY_PHYSICAL);
ASSUME(GetMoveCategory(MOVE_WATER_GUN) == DAMAGE_CATEGORY_SPECIAL);
PLAYER(SPECIES_RAICHU) { Item(item); }
OPPONENT(SPECIES_MAGIKARP) { Moves(MOVE_SCRATCH, MOVE_WATER_GUN); }
} WHEN {
TURN { MOVE(opponent, move); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.0), results[1].damage);
EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.0), results[3].damage);
}
}
SINGLE_BATTLE_TEST("Eviolite uses original species after Transform", s16 damage)
{
u32 item;
PARAMETRIZE { item = ITEM_EVIOLITE; }
PARAMETRIZE { item = ITEM_NONE; }
GIVEN {
ASSUME(GetMoveEffect(MOVE_TRANSFORM) == EFFECT_TRANSFORM);
PLAYER(SPECIES_PIKACHU) { Item(item); Moves(MOVE_TRANSFORM, MOVE_CELEBRATE); }
OPPONENT(SPECIES_GYARADOS) { Moves(MOVE_SCRATCH, MOVE_CELEBRATE); }
} WHEN {
TURN { MOVE(player, MOVE_TRANSFORM); MOVE(opponent, MOVE_CELEBRATE); }
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SCRATCH); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TRANSFORM, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent);
HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
}
}

View File

@ -92,24 +92,24 @@ DOUBLE_BATTLE_TEST("Ally Switch does not redirect the target of Snipe Shot")
DOUBLE_BATTLE_TEST("Ally Switch does not redirect moves done by Pokémon with Stalwart and Propeller Tail")
{
u16 species;
enum Ability ability;
PARAMETRIZE { ability = ABILITY_STALWART; }
PARAMETRIZE { ability = ABILITY_PROPELLER_TAIL; }
PARAMETRIZE { ability = ABILITY_TELEPATHY; }
PARAMETRIZE { species = SPECIES_DURALUDON; ability = ABILITY_STALWART; }
PARAMETRIZE { species = SPECIES_ARROKUDA; ability = ABILITY_PROPELLER_TAIL; }
PARAMETRIZE { species = SPECIES_RALTS; ability = ABILITY_TELEPATHY; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET); // Wobb is playerLeft, but it'll be Wynaut after Ally Switch
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_KADABRA) { Ability(ability); }
OPPONENT(species) { Ability(ability); }
OPPONENT(SPECIES_ABRA);
} WHEN {
TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); MOVE(opponentLeft, MOVE_SCRATCH, target:playerRight); } // Kadabra targets playerRight Wynaut.
TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); MOVE(opponentLeft, MOVE_SCRATCH, target:playerRight); } // Opponent targets playerRight Wynaut.
} SCENE {
MESSAGE("Wobbuffet used Ally Switch!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, playerLeft);
MESSAGE("Wobbuffet and Wynaut switched places!");
MESSAGE("The opposing Kadabra used Scratch!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft);
HP_BAR((ability == ABILITY_STALWART || ability == ABILITY_PROPELLER_TAIL) ? playerLeft : playerRight);
}
@ -218,6 +218,7 @@ DOUBLE_BATTLE_TEST("Ally Switch increases the Protect-like moves counter (Gen9+)
DOUBLE_BATTLE_TEST("Ally Switch works if ally used two-turn move like Dig")
{
GIVEN {
ASSUME(gBattleMoveEffects[GetMoveEffect(MOVE_DIG)].twoTurnEffect);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET);
@ -313,9 +314,8 @@ DOUBLE_BATTLE_TEST("Ally switch swaps opposing sky drop targets if partner is be
DOUBLE_BATTLE_TEST("Ally Switch swaps Illusion data")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_ALLY_SWITCH) == EFFECT_ALLY_SWITCH);
PLAYER(SPECIES_HOOPA);
PLAYER(SPECIES_ZOROARK);
PLAYER(SPECIES_ZOROARK) {Ability(ABILITY_ILLUSION); }
PLAYER(SPECIES_MAMOSWINE); // the third member here is required for zoroark
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
@ -329,6 +329,7 @@ DOUBLE_BATTLE_TEST("Ally Switch swaps Illusion data")
DOUBLE_BATTLE_TEST("Ally switch updates last used moves for Mimic")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_MIMIC) == EFFECT_MIMIC);
PLAYER(SPECIES_XATU) { Speed(100); }
PLAYER(SPECIES_RIOLU) { Speed(150); }
OPPONENT(SPECIES_FEAROW) { Speed(20); }
@ -348,9 +349,10 @@ DOUBLE_BATTLE_TEST("Ally switch updates last used moves for Mimic")
}
}
DOUBLE_BATTLE_TEST("Ally Switch does not update leech seed battler")
DOUBLE_BATTLE_TEST("Ally Switch does not update leech seed position")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_LEECH_SEED) == EFFECT_LEECH_SEED);
PLAYER(SPECIES_WYNAUT);
PLAYER(SPECIES_SOLOSIS);
OPPONENT(SPECIES_BULBASAUR) { HP(50); MaxHP(100); }
@ -379,6 +381,114 @@ DOUBLE_BATTLE_TEST("Ally Switch does not update leech seed battler")
}
}
DOUBLE_BATTLE_TEST("Ally Switch does not update Future Sight target position")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_FUTURE_SIGHT) == EFFECT_FUTURE_SIGHT);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_ABRA);
OPPONENT(SPECIES_RALTS);
} WHEN {
TURN { MOVE(opponentLeft, MOVE_FUTURE_SIGHT, target: playerLeft); }
TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); }
TURN { }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, opponentLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, playerLeft);
MESSAGE("Wynaut took the Future Sight attack!");
HP_BAR(playerLeft);
NOT HP_BAR(playerRight);
}
}
DOUBLE_BATTLE_TEST("Ally Switch does not update Future Sight target position when attacker side switches")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_FUTURE_SIGHT) == EFFECT_FUTURE_SIGHT);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_ABRA);
OPPONENT(SPECIES_RALTS);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponentLeft, MOVE_FUTURE_SIGHT, target: playerLeft); }
TURN { SWITCH(opponentLeft, 2); MOVE(opponentRight, MOVE_ALLY_SWITCH); }
TURN { }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, opponentLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, opponentRight);
MESSAGE("Wobbuffet took the Future Sight attack!");
HP_BAR(playerLeft);
NOT HP_BAR(playerRight);
}
}
DOUBLE_BATTLE_TEST("Ally Switch does not update Wish recovery position")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_WISH) == EFFECT_WISH);
PLAYER(SPECIES_WOBBUFFET) { HP(50); MaxHP(100); }
PLAYER(SPECIES_WYNAUT) { HP(20); MaxHP(100); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_WISH); }
TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_WISH, playerLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, playerLeft);
HP_BAR(playerLeft);
NOT HP_BAR(playerRight);
} THEN {
EXPECT_EQ(playerLeft->hp, 70);
EXPECT_EQ(playerRight->hp, 50);
}
}
DOUBLE_BATTLE_TEST("Ally Switch does not update Healing Wish/Lunar Dance recovery position")
{
u16 move = MOVE_NONE;
struct BattlePokemon *switchTarget = NULL;
PARAMETRIZE { move = MOVE_HEALING_WISH; switchTarget = playerLeft; }
PARAMETRIZE { move = MOVE_HEALING_WISH; switchTarget = playerRight; }
PARAMETRIZE { move = MOVE_LUNAR_DANCE; switchTarget = playerLeft; }
PARAMETRIZE { move = MOVE_LUNAR_DANCE; switchTarget = playerRight; }
GIVEN {
WITH_CONFIG(B_HEALING_WISH_SWITCH, GEN_8);
ASSUME(GetMoveEffect(MOVE_HEALING_WISH) == EFFECT_HEALING_WISH);
ASSUME(GetMoveEffect(MOVE_LUNAR_DANCE) == EFFECT_LUNAR_DANCE);
PLAYER(SPECIES_GARDEVOIR);
PLAYER(SPECIES_ABRA);
PLAYER(SPECIES_WOBBUFFET) { HP(100); MaxHP(100); }
PLAYER(SPECIES_WYNAUT) { HP(50); MaxHP(80); Status1(STATUS1_PARALYSIS); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, move); SEND_OUT(playerLeft, 2); }
TURN { MOVE(playerRight, MOVE_ALLY_SWITCH); }
TURN { SWITCH(switchTarget, 3); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, playerLeft);
if (switchTarget == playerLeft) {
HP_BAR(playerLeft, hp: 80);
STATUS_ICON(playerLeft, none: TRUE);
} else {
NOT HP_BAR(playerRight);
}
} THEN {
if (switchTarget == playerLeft) {
EXPECT_EQ(playerLeft->hp, 80);
EXPECT_EQ(playerLeft->status1, STATUS1_NONE);
} else {
EXPECT_EQ(playerRight->hp, 50);
EXPECT_EQ(playerRight->status1, STATUS1_PARALYSIS);
}
}
}
DOUBLE_BATTLE_TEST("Ally Switch updates attract battler")
{
GIVEN {

View File

@ -12,7 +12,6 @@ TO_DO_BATTLE_TEST("Assist can call moves with no PP left");
TO_DO_BATTLE_TEST("Assist can call moves from a fainted party member");
TO_DO_BATTLE_TEST("Assist can call moves that are blocked to its partners"); // Eg. double battle parter blocked by Disable
TO_DO_BATTLE_TEST("Assist can only call the original moves of a Transformed partner (Gen4 only)");
TO_DO_BATTLE_TEST("Assist can only call the current moves of a Transformed partner (Gen5+)");
TO_DO_BATTLE_TEST("Assist cannot call a Mimicked move (Gen4 only)");
TO_DO_BATTLE_TEST("Assist can call a Mimicked move but not the original Mimic (Gen5+)");
TO_DO_BATTLE_TEST("Assist can call moves in unhatched Eggs (Gen5 only)");
@ -57,3 +56,25 @@ SINGLE_BATTLE_TEST("Assisted move triggers correct weakness berry")
ANIMATION(ANIM_TYPE_MOVE, MOVE_SURF, player);
}
}
DOUBLE_BATTLE_TEST("Assist can only call the current moves of a Transformed partner (Gen5+)")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_TRANSFORM) == EFFECT_TRANSFORM);
PLAYER(SPECIES_WOBBUFFET) { Speed(3); Moves(MOVE_ASSIST); }
PLAYER(SPECIES_DITTO) { Speed(4); Moves(MOVE_TRANSFORM); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(2); Moves(MOVE_SCRATCH); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(1); }
} WHEN {
TURN {
MOVE(playerRight, MOVE_TRANSFORM, target: opponentLeft);
MOVE(playerLeft, MOVE_ASSIST);
MOVE(opponentLeft, MOVE_SCRATCH, target: playerRight);
}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TRANSFORM, playerRight);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ASSIST, playerLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, playerLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft);
}
}

View File

@ -0,0 +1,38 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(GetMoveEffect(MOVE_PSYBLADE) == EFFECT_TERRAIN_BOOST);
}
SINGLE_BATTLE_TEST("Psyblade's power increases by 50% on Electric Terrain even if the user is not grounded", s16 damage)
{
bool32 terrain, airBalloon;
PARAMETRIZE { terrain = FALSE; airBalloon = FALSE; }
PARAMETRIZE { terrain = TRUE; airBalloon = FALSE; }
PARAMETRIZE { terrain = FALSE; airBalloon = TRUE; }
PARAMETRIZE { terrain = TRUE; airBalloon = TRUE; }
GIVEN {
ASSUME(gItemsInfo[ITEM_AIR_BALLOON].holdEffect == HOLD_EFFECT_AIR_BALLOON);
ASSUME(GetMoveEffect(MOVE_ELECTRIC_TERRAIN) == EFFECT_ELECTRIC_TERRAIN);
ASSUME(GetMoveTerrainBoost_Terrain(MOVE_PSYBLADE) == STATUS_FIELD_ELECTRIC_TERRAIN);
ASSUME(GetMoveTerrainBoost_GroundCheck(MOVE_PSYBLADE) == GROUND_CHECK_NONE);
PLAYER(SPECIES_SLOWKING) { Moves(MOVE_ELECTRIC_TERRAIN, MOVE_PSYBLADE); Item(airBalloon ? ITEM_AIR_BALLOON : ITEM_NONE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
if (terrain)
TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); }
TURN { MOVE(player, MOVE_PSYBLADE); }
} SCENE {
if (terrain)
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYBLADE, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[3].damage);
}
}

View File

@ -1,6 +1,11 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(GetMoveEffect(MOVE_SUCKER_PUNCH) == EFFECT_SUCKER_PUNCH);
}
SINGLE_BATTLE_TEST("Sucker Punch hits targets that are about to attack")
{
GIVEN {
@ -34,6 +39,25 @@ SINGLE_BATTLE_TEST("Sucker Punch doesn't hit targets using status moves")
}
}
SINGLE_BATTLE_TEST("Sucker Punch hits targets using Me First")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_ME_FIRST) == EFFECT_ME_FIRST);
ASSUME(GetMovePriority(MOVE_SUCKER_PUNCH) > GetMovePriority(MOVE_ME_FIRST));
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SUCKER_PUNCH); MOVE(opponent, MOVE_ME_FIRST); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUCKER_PUNCH, player);
HP_BAR(opponent);
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ME_FIRST, opponent);
HP_BAR(player);
}
}
}
SINGLE_BATTLE_TEST("Sucker Punch doesn't hit targets that has already moved")
{
GIVEN {

View File

@ -21,3 +21,20 @@ SINGLE_BATTLE_TEST("Tickle reduces the target's Attack and Defense by 1 stage ea
EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE - 1);
}
}
SINGLE_BATTLE_TEST("Tickle is blocked by Substitute (Gen4+)")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_TICKLE, MOVE_CELEBRATE); Speed(5); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SUBSTITUTE, MOVE_CELEBRATE); Speed(10); }
} WHEN {
TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_CELEBRATE); }
TURN { MOVE(player, MOVE_TICKLE); MOVE(opponent, MOVE_CELEBRATE); }
} SCENE {
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TICKLE, player);
MESSAGE("But it failed!");
} THEN {
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE);
}
}

View File

@ -1,4 +1,42 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("TODO: Write Venom Drench (Move Effect) test titles")
ASSUMPTIONS
{
ASSUME(GetMoveEffect(MOVE_VENOM_DRENCH) == EFFECT_VENOM_DRENCH);
}
SINGLE_BATTLE_TEST("Venom Drench lowers stats of a poisoned target")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_VENOM_DRENCH); }
OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); }
} WHEN {
TURN { MOVE(player, MOVE_VENOM_DRENCH); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_VENOM_DRENCH, player);
} THEN {
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1);
EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE - 1);
EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 1);
}
}
SINGLE_BATTLE_TEST("Venom Drench is blocked by Substitute")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_SUBSTITUTE) == EFFECT_SUBSTITUTE);
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_VENOM_DRENCH, MOVE_CELEBRATE); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SUBSTITUTE, MOVE_CELEBRATE); Status1(STATUS1_POISON); }
} WHEN {
TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_CELEBRATE); }
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_VENOM_DRENCH); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, opponent);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_VENOM_DRENCH, player);
} THEN {
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE);
EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE);
}
}