Merge branch '_RHH/master' into _RHH/upcoming

This commit is contained in:
Eduardo Quezada 2025-01-23 23:01:25 -03:00
commit cd84e07341
8 changed files with 142 additions and 131 deletions

View File

@ -427,7 +427,9 @@ $(OBJ_DIR)/sym_common.ld: sym_common.txt $(C_OBJS) $(wildcard common_syms/*.txt)
$(OBJ_DIR)/sym_ewram.ld: sym_ewram.txt
$(RAMSCRGEN) ewram_data $< ENGLISH > $@
TEACHABLE_DEPS := $(shell find data/ -type f -name '*.inc') $(INCLUDE_DIRS)/constants/tms_hms.h $(C_SUBDIR)/pokemon.c
MOVES_JSON_DIR := $(TOOLS_DIR)/learnset_helpers/porymoves_files
TEACHABLE_DEPS := $(shell find data/ -type f -name '*.inc') $(INCLUDE_DIRS)/constants/tms_hms.h $(C_SUBDIR)/pokemon.c $(wildcard $(MOVES_JSON_DIR)/*.json)
$(DATA_SRC_SUBDIR)/pokemon/teachable_learnsets.h: $(TEACHABLE_DEPS)
python3 $(TOOLS_DIR)/learnset_helpers/teachable.py

View File

@ -834,6 +834,7 @@ struct BattleStruct
u8 numSpreadTargets:2;
u8 padding3:2;
struct MessageStatus slideMessageStatus;
u8 trainerSlideSpriteIds[MAX_BATTLERS_COUNT];
};
// The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider,

View File

@ -67,7 +67,7 @@ enum {
#define ABILITYEFFECT_WATER_SPORT 253 // Only used if B_SPORT_TURNS >= GEN_6
// For the first argument of ItemBattleEffects, to deteremine which block of item effects to try
enum ItemEffect
enum ItemCaseId
{
ITEMEFFECT_NONE,
ITEMEFFECT_ON_SWITCH_IN,
@ -82,6 +82,16 @@ enum ItemEffect
ITEMEFFECT_STATS_CHANGED, // For White Herb and Eject Pack
};
enum ItemEffect
{
ITEM_NO_EFFECT,
ITEM_STATUS_CHANGE,
ITEM_EFFECT_OTHER,
ITEM_PP_CHANGE,
ITEM_HP_CHANGE,
ITEM_STATS_CHANGE,
};
#define IS_WHOLE_SIDE_ALIVE(battler) ((IsBattlerAlive(battler) && IsBattlerAlive(BATTLE_PARTNER(battler))))
#define IS_ALIVE_AND_PRESENT(battler) (IsBattlerAlive(battler) && IsBattlerSpritePresent(battler))
@ -223,7 +233,7 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move);
bool32 CanBattlerEscape(u32 battler); // no ability check
void BattleScriptExecute(const u8 *BS_ptr);
void BattleScriptPushCursorAndCallback(const u8 *BS_ptr);
u32 ItemBattleEffects(enum ItemEffect, u32 battler, bool32 moveTurn);
u32 ItemBattleEffects(enum ItemCaseId, u32 battler, bool32 moveTurn);
void ClearVariousBattlerFlags(u32 battler);
void HandleAction_RunBattleScript(void);
u32 SetRandomTarget(u32 battler);
@ -281,7 +291,7 @@ void TryRestoreHeldItems(void);
bool32 CanStealItem(u32 battlerStealing, u32 battlerItem, u16 item);
void TrySaveExchangedItem(u32 battler, u16 stolenItem);
bool32 IsPartnerMonFromSameTrainer(u32 battler);
u32 TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum ItemEffect caseID);
enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum ItemCaseId caseID);
bool32 IsBattlerAffectedByHazards(u32 battler, bool32 toxicSpikes);
void SortBattlersBySpeed(u8 *battlers, bool32 slowToFast);
bool32 CompareStat(u32 battler, u8 statId, u8 cmpTo, u8 cmpKind);

View File

@ -297,8 +297,7 @@
#define B_SHOW_TYPES SHOW_TYPES_NEVER // When defined as SHOW_TYPES_ALWAYS, after selecting "Fight" in battle, the types of all Pokemon are revealed. Whe defined as SHOW_TYPES_OWN, types are only revealed if the player owns the mon in question.
// Pokémon battle sprite settings
#define B_ENEMY_MON_SHADOW_STYLE GEN_3 // In Gen4+, all enemy Pokemon will have a shadow drawn beneath them.
// Currently Gen4+ shadows don't properly work with Trainerslides
#define B_ENEMY_MON_SHADOW_STYLE GEN_LATEST // In Gen4+, all enemy Pokemon will have a shadow drawn beneath them.
// Battle UI settings
#define B_MOVE_REARRANGEMENT_IN_BATTLE GEN_LATEST // In Gen 4+ move slots cannot be rearranged in battle

View File

@ -2223,12 +2223,12 @@ static void Controller_DoMoveAnimation(u32 battler)
static void Controller_HandleTrainerSlideBack(u32 battler)
{
if (gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy)
if (gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].callback == SpriteCallbackDummy)
{
if (GetBattlerSide(battler) == B_SIDE_OPPONENT)
FreeTrainerFrontPicPalette(gSprites[gBattlerSpriteIds[battler]].oam.affineParam);
FreeSpriteOamMatrix(&gSprites[gBattlerSpriteIds[battler]]);
DestroySprite(&gSprites[gBattlerSpriteIds[battler]]);
FreeTrainerFrontPicPalette(gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.affineParam);
FreeSpriteOamMatrix(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]]);
DestroySprite(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]]);
BattleControllerComplete(battler);
}
}
@ -2270,7 +2270,7 @@ static void Controller_WaitForStatusAnimation(u32 battler)
static void Controller_WaitForTrainerPic(u32 battler)
{
if (gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy)
if (gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].callback == SpriteCallbackDummy)
BattleControllerComplete(battler);
}
@ -2460,18 +2460,18 @@ void BtlController_HandleDrawTrainerPic(u32 battler, u32 trainerPicId, bool32 is
if (GetBattlerSide(battler) == B_SIDE_OPPONENT) // Always the front sprite for the opponent.
{
DecompressTrainerFrontPic(trainerPicId, battler);
SetMultiuseSpriteTemplateToTrainerBack(trainerPicId, GetBattlerPosition(battler));
SetMultiuseSpriteTemplateToTrainerFront(trainerPicId, GetBattlerPosition(battler));
if (subpriority == -1)
subpriority = GetBattlerSpriteSubpriority(battler);
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
gBattleStruct->trainerSlideSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
xPos,
yPos,
subpriority);
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerSprites[trainerPicId].palette.tag);
gSprites[gBattlerSpriteIds[battler]].x2 = -DISPLAY_WIDTH;
gSprites[gBattlerSpriteIds[battler]].sSpeedX = 2;
gSprites[gBattlerSpriteIds[battler]].oam.affineParam = trainerPicId;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerSprites[trainerPicId].palette.tag);
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].x2 = -DISPLAY_WIDTH;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].sSpeedX = 2;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.affineParam = trainerPicId;
}
else // Player's side
{
@ -2481,15 +2481,15 @@ void BtlController_HandleDrawTrainerPic(u32 battler, u32 trainerPicId, bool32 is
SetMultiuseSpriteTemplateToTrainerFront(trainerPicId, GetBattlerPosition(battler));
if (subpriority == -1)
subpriority = GetBattlerSpriteSubpriority(battler);
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
gBattleStruct->trainerSlideSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
xPos,
yPos,
subpriority);
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerSprites[trainerPicId].palette.tag);
gSprites[gBattlerSpriteIds[battler]].oam.affineMode = ST_OAM_AFFINE_OFF;
gSprites[gBattlerSpriteIds[battler]].hFlip = 1;
gSprites[gBattlerSpriteIds[battler]].y2 = 48;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerSprites[trainerPicId].palette.tag);
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.affineMode = ST_OAM_AFFINE_OFF;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].hFlip = 1;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].y2 = 48;
}
else
{
@ -2497,20 +2497,20 @@ void BtlController_HandleDrawTrainerPic(u32 battler, u32 trainerPicId, bool32 is
SetMultiuseSpriteTemplateToTrainerBack(trainerPicId, GetBattlerPosition(battler));
if (subpriority == -1)
subpriority = GetBattlerSpriteSubpriority(battler);
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
gBattleStruct->trainerSlideSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
xPos,
yPos,
subpriority);
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = battler;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = battler;
}
gSprites[gBattlerSpriteIds[battler]].x2 = DISPLAY_WIDTH;
gSprites[gBattlerSpriteIds[battler]].sSpeedX = -2;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].x2 = DISPLAY_WIDTH;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].sSpeedX = -2;
}
if (B_FAST_INTRO_NO_SLIDE || gTestRunnerHeadless)
gSprites[gBattlerSpriteIds[battler]].callback = SpriteCB_TrainerSpawn;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].callback = SpriteCB_TrainerSpawn;
else
gSprites[gBattlerSpriteIds[battler]].callback = SpriteCB_TrainerSlideIn;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].callback = SpriteCB_TrainerSlideIn;
gBattlerControllerFuncs[battler] = Controller_WaitForTrainerPic;
}
@ -2521,26 +2521,26 @@ void BtlController_HandleTrainerSlide(u32 battler, u32 trainerPicId)
{
DecompressTrainerBackPic(trainerPicId, battler);
SetMultiuseSpriteTemplateToTrainerBack(trainerPicId, GetBattlerPosition(battler));
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
gBattleStruct->trainerSlideSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate,
80,
(8 - gTrainerBacksprites[trainerPicId].coordinates.size) * 4 + 80,
30);
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = battler;
gSprites[gBattlerSpriteIds[battler]].x2 = -96;
gSprites[gBattlerSpriteIds[battler]].sSpeedX = 2;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = battler;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].x2 = -96;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].sSpeedX = 2;
}
else
{
DecompressTrainerFrontPic(trainerPicId, battler);
SetMultiuseSpriteTemplateToTrainerBack(trainerPicId, GetBattlerPosition(battler));
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate, 176, 40, 30);
gSprites[gBattlerSpriteIds[battler]].oam.affineParam = trainerPicId;
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerSprites[trainerPicId].palette.tag);
gSprites[gBattlerSpriteIds[battler]].x2 = 96;
gSprites[gBattlerSpriteIds[battler]].x += 32;
gSprites[gBattlerSpriteIds[battler]].sSpeedX = -2;
SetMultiuseSpriteTemplateToTrainerFront(trainerPicId, GetBattlerPosition(battler));
gBattleStruct->trainerSlideSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate, 176, 40, 0);
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.affineParam = trainerPicId;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerSprites[trainerPicId].palette.tag);
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].x2 = 96;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].x += 32;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].sSpeedX = -2;
}
gSprites[gBattlerSpriteIds[battler]].callback = SpriteCB_TrainerSlideIn;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].callback = SpriteCB_TrainerSlideIn;
gBattlerControllerFuncs[battler] = Controller_WaitForTrainerPic;
}
@ -2551,14 +2551,14 @@ void BtlController_HandleTrainerSlideBack(u32 battler, s16 data0, bool32 startAn
{
u32 side = GetBattlerSide(battler);
SetSpritePrimaryCoordsFromSecondaryCoords(&gSprites[gBattlerSpriteIds[battler]]);
gSprites[gBattlerSpriteIds[battler]].data[0] = data0;
gSprites[gBattlerSpriteIds[battler]].data[2] = (side == B_SIDE_PLAYER) ? -40 : 280;
gSprites[gBattlerSpriteIds[battler]].data[4] = gSprites[gBattlerSpriteIds[battler]].y;
gSprites[gBattlerSpriteIds[battler]].callback = StartAnimLinearTranslation;
StoreSpriteCallbackInData6(&gSprites[gBattlerSpriteIds[battler]], SpriteCallbackDummy);
SetSpritePrimaryCoordsFromSecondaryCoords(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]]);
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].data[0] = data0;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].data[2] = (side == B_SIDE_PLAYER) ? -40 : 280;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].data[4] = gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].y;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].callback = StartAnimLinearTranslation;
StoreSpriteCallbackInData6(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]], SpriteCallbackDummy);
if (startAnim)
StartSpriteAnim(&gSprites[gBattlerSpriteIds[battler]], 1);
StartSpriteAnim(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]], 1);
gBattlerControllerFuncs[battler] = Controller_HandleTrainerSlideBack;
}
@ -2828,34 +2828,34 @@ void BtlController_HandleIntroTrainerBallThrow(u32 battler, u16 tagTrainerPal, c
u8 paletteNum, taskId;
u32 side = GetBattlerSide(battler);
SetSpritePrimaryCoordsFromSecondaryCoords(&gSprites[gBattlerSpriteIds[battler]]);
SetSpritePrimaryCoordsFromSecondaryCoords(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]]);
if (side == B_SIDE_PLAYER)
{
gSprites[gBattlerSpriteIds[battler]].data[0] = 50;
gSprites[gBattlerSpriteIds[battler]].data[2] = -40;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].data[0] = 50;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].data[2] = -40;
}
else
{
gSprites[gBattlerSpriteIds[battler]].data[0] = 35;
gSprites[gBattlerSpriteIds[battler]].data[2] = 280;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].data[0] = 35;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].data[2] = 280;
}
gSprites[gBattlerSpriteIds[battler]].data[4] = gSprites[gBattlerSpriteIds[battler]].y;
gSprites[gBattlerSpriteIds[battler]].callback = StartAnimLinearTranslation;
gSprites[gBattlerSpriteIds[battler]].sBattlerId = battler;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].data[4] = gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].y;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].callback = StartAnimLinearTranslation;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].sBattlerId = battler;
if (side == B_SIDE_PLAYER)
{
StoreSpriteCallbackInData6(&gSprites[gBattlerSpriteIds[battler]], SpriteCB_FreePlayerSpriteLoadMonSprite);
StartSpriteAnim(&gSprites[gBattlerSpriteIds[battler]], ShouldDoSlideInAnim() ? 2 : 1);
StoreSpriteCallbackInData6(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]], SpriteCB_FreePlayerSpriteLoadMonSprite);
StartSpriteAnim(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]], ShouldDoSlideInAnim() ? 2 : 1);
paletteNum = AllocSpritePalette(tagTrainerPal);
LoadCompressedPalette(trainerPal, OBJ_PLTT_ID(paletteNum), PLTT_SIZE_4BPP);
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = paletteNum;
gSprites[gBattleStruct->trainerSlideSpriteIds[battler]].oam.paletteNum = paletteNum;
}
else
{
StoreSpriteCallbackInData6(&gSprites[gBattlerSpriteIds[battler]], SpriteCB_FreeOpponentSprite);
StoreSpriteCallbackInData6(&gSprites[gBattleStruct->trainerSlideSpriteIds[battler]], SpriteCB_FreeOpponentSprite);
}
taskId = CreateTask(Task_StartSendOutAnim, 5);

View File

@ -10827,25 +10827,25 @@ static void Cmd_various(void)
VARIOUS_ARGS(const u8 *failInstr);
if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_SEEDS)
{
u8 effect = 0;
enum ItemEffect effect = ITEM_NO_EFFECT;
u16 item = gBattleMons[battler].item;
switch (GetBattlerHoldEffectParam(battler))
{
case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE);
effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, item, ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN);
break;
case HOLD_EFFECT_PARAM_GRASSY_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE);
effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, item, ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN);
break;
case HOLD_EFFECT_PARAM_MISTY_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE);
effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN);
break;
case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE);
effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN);
break;
}
if (effect)
if (effect != ITEM_NO_EFFECT)
return;
}
gBattlescriptCurrInstr = cmd->failInstr;

View File

@ -6785,16 +6785,6 @@ void BattleScriptPushCursorAndCallback(const u8 *BS_ptr)
gBattleMainFunc = RunBattleScriptCommands;
}
enum
{
ITEM_NO_EFFECT,
ITEM_STATUS_CHANGE,
ITEM_EFFECT_OTHER,
ITEM_PP_CHANGE,
ITEM_HP_CHANGE,
ITEM_STATS_CHANGE,
};
bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag)
{
if (!(gFieldStatuses & terrainFlag))
@ -6933,7 +6923,7 @@ bool32 HasEnoughHpToEatBerry(u32 battler, u32 hpFraction, u32 itemId)
return FALSE;
}
static u32 HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, enum ItemEffect caseID)
static enum ItemEffect HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, enum ItemCaseId caseID)
{
if (HasEnoughHpToEatBerry(battler, (B_CONFUSE_BERRIES_HEAL >= GEN_7 ? 4 : 2), itemId)
&& (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)))
@ -6969,10 +6959,10 @@ static u32 HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, enum ItemEffe
return ITEM_HP_CHANGE;
}
return 0;
return ITEM_NO_EFFECT;
}
static u32 StatRaiseBerry(u32 battler, u32 itemId, u32 statId, enum ItemEffect caseID)
static enum ItemEffect StatRaiseBerry(u32 battler, u32 itemId, u32 statId, enum ItemCaseId caseID)
{
if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN) && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, itemId), itemId))
{
@ -7000,7 +6990,7 @@ static u32 StatRaiseBerry(u32 battler, u32 itemId, u32 statId, enum ItemEffect c
return ITEM_NO_EFFECT;
}
static u32 RandomStatRaiseBerry(u32 battler, u32 itemId, enum ItemEffect caseID)
static enum ItemEffect RandomStatRaiseBerry(u32 battler, u32 itemId, enum ItemCaseId caseID)
{
s32 i;
u16 stringId;
@ -7048,10 +7038,10 @@ static u32 RandomStatRaiseBerry(u32 battler, u32 itemId, enum ItemEffect caseID)
return ITEM_STATS_CHANGE;
}
return 0;
return ITEM_NO_EFFECT;
}
static u32 TrySetMicleBerry(u32 battler, u32 itemId, enum ItemEffect caseID)
static enum ItemEffect TrySetMicleBerry(u32 battler, u32 itemId, enum ItemCaseId caseID)
{
if (HasEnoughHpToEatBerry(battler, 4, itemId))
{
@ -7067,10 +7057,10 @@ static u32 TrySetMicleBerry(u32 battler, u32 itemId, enum ItemEffect caseID)
}
return ITEM_EFFECT_OTHER;
}
return 0;
return ITEM_NO_EFFECT;
}
static u8 TrySetEnigmaBerry(u32 battler)
static enum ItemEffect TrySetEnigmaBerry(u32 battler)
{
if (IsBattlerAlive(battler)
&& !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)
@ -7087,10 +7077,10 @@ static u8 TrySetEnigmaBerry(u32 battler)
gBattlescriptCurrInstr = BattleScript_ItemHealHP_RemoveItemRet;
return ITEM_HP_CHANGE;
}
return 0;
return ITEM_NO_EFFECT;
}
static u8 DamagedStatBoostBerryEffect(u32 battler, u8 statId, u8 category)
static enum ItemEffect DamagedStatBoostBerryEffect(u32 battler, u8 statId, u8 category)
{
if (IsBattlerAlive(battler)
&& CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)
@ -7116,10 +7106,10 @@ static u8 DamagedStatBoostBerryEffect(u32 battler, u8 statId, u8 category)
gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet;
return ITEM_STATS_CHANGE;
}
return 0;
return ITEM_NO_EFFECT;
}
u32 TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum ItemEffect caseID)
enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum ItemCaseId caseID)
{
if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
{
@ -7129,7 +7119,7 @@ u32 TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum Ite
SET_STATCHANGER(statId, 1, FALSE);
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId;
gBattleScripting.animArg2 = 0;
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL)
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN)
{
BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
}
@ -7140,10 +7130,33 @@ u32 TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum Ite
}
return ITEM_STATS_CHANGE;
}
return 0;
return ITEM_NO_EFFECT;
}
static u32 ItemRestorePp(u32 battler, u32 itemId, enum ItemEffect caseID)
static enum ItemEffect TryEjectPack(u32 battler, enum ItemCaseId caseID)
{
if (gProtectStructs[battler].statFell
&& !gProtectStructs[battler].disableEjectPack
&& CountUsablePartyMons(battler) > 0
&& !(gCurrentMove == MOVE_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker))) // Does not activate if attacker used Parting Shot and can switch out
{
gProtectStructs[battler].statFell = FALSE;
gBattleScripting.battler = battler;
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN)
{
BattleScriptExecute(BattleScript_EjectPackActivate_End2);
}
else
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_EjectPackActivate_Ret;
}
return ITEM_STATS_CHANGE;
}
return ITEM_NO_EFFECT;
}
static u32 ItemRestorePp(u32 battler, u32 itemId, enum ItemCaseId caseID)
{
struct Pokemon *party = GetBattlerParty(battler);
struct Pokemon *mon = &party[gBattlerPartyIndexes[battler]];
@ -7190,7 +7203,7 @@ static u32 ItemRestorePp(u32 battler, u32 itemId, enum ItemEffect caseID)
return 0;
}
static u32 ItemHealHp(u32 battler, u32 itemId, enum ItemEffect caseID, bool32 percentHeal)
static u32 ItemHealHp(u32 battler, u32 itemId, enum ItemCaseId caseID, bool32 percentHeal)
{
if (!(gBattleScripting.overrideBerryRequirements && gBattleMons[battler].hp == gBattleMons[battler].maxHP)
&& (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))
@ -7286,7 +7299,7 @@ static bool32 GetMentalHerbEffect(u32 battler)
return ret;
}
static u32 TryConsumeMirrorHerb(u32 battler, enum ItemEffect caseID)
static u32 TryConsumeMirrorHerb(u32 battler, enum ItemCaseId caseID)
{
u32 effect = 0;
@ -7311,7 +7324,7 @@ static u32 TryConsumeMirrorHerb(u32 battler, enum ItemEffect caseID)
return effect;
}
static inline u32 TryBoosterEnergy(u32 battler, enum ItemEffect caseID)
static inline u32 TryBoosterEnergy(u32 battler, enum ItemCaseId caseID)
{
if (gDisableStructs[battler].boosterEnergyActivates || gBattleMons[battler].status2 & STATUS2_TRANSFORMED)
return ITEM_NO_EFFECT;
@ -7577,7 +7590,7 @@ static u8 ItemEffectMoveEnd(u32 battler, u16 holdEffect)
return effect;
}
static inline bool32 TryCureStatus(u32 battler, enum ItemEffect caseId)
static inline bool32 TryCureStatus(u32 battler, enum ItemCaseId caseId)
{
u32 effect = ITEM_NO_EFFECT;
u32 string = 0;
@ -7637,10 +7650,10 @@ static inline bool32 TryCureStatus(u32 battler, enum ItemEffect caseId)
return effect;
}
u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn)
{
u32 moveType = 0;
u32 effect = ITEM_NO_EFFECT;
enum ItemEffect effect = ITEM_NO_EFFECT;
u32 battlerHoldEffect = 0, atkHoldEffect = 0;
u32 atkHoldEffectParam = 0;
u32 atkItem = 0;
@ -7838,24 +7851,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
}
break;
case HOLD_EFFECT_EJECT_PACK:
if (gProtectStructs[battler].statFell
&& gProtectStructs[battler].disableEjectPack == 0
&& CountUsablePartyMons(battler) > 0
&& !(gCurrentMove == MOVE_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker))) // Does not activate if attacker used Parting Shot and can switch out
{
gProtectStructs[battler].statFell = FALSE;
gBattleScripting.battler = battler;
effect = ITEM_STATS_CHANGE;
if (moveTurn)
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_EjectPackActivate_Ret;
}
else
{
BattleScriptExecute(BattleScript_EjectPackActivate_End2);
}
}
effect = TryEjectPack(battler, caseID);
break;
case HOLD_EFFECT_BERSERK_GENE:
BufferStatChange(battler, STAT_ATK, STRINGID_STATROSE);
@ -7883,12 +7879,10 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
{
gSpecialStatuses[battler].switchInItemDone = TRUE;
gBattlerAttacker = gPotentialItemEffectBattler = gBattleScripting.battler = battler;
switch (effect)
if (effect == ITEM_STATUS_CHANGE)
{
case ITEM_STATUS_CHANGE:
BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1);
MarkBattlerForControllerExec(battler);
break;
}
}
}
@ -8100,12 +8094,10 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
if (effect != 0)
{
gBattlerAttacker = gPotentialItemEffectBattler = gBattleScripting.battler = battler;
switch (effect)
if (effect == ITEM_STATUS_CHANGE)
{
case ITEM_STATUS_CHANGE:
BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1);
MarkBattlerForControllerExec(battler);
break;
}
}
}
@ -8464,16 +8456,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
}
break;
case HOLD_EFFECT_EJECT_PACK:
if (gProtectStructs[battler].statFell
&& gProtectStructs[battler].disableEjectPack == 0
&& CountUsablePartyMons(battler) > 0)
{
gBattleScripting.battler = battler;
gPotentialItemEffectBattler = battler;
effect = ITEM_STATS_CHANGE;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_EjectPackActivates;
}
effect = TryEjectPack(battler, ITEMEFFECT_ON_SWITCH_IN);
break;
}
break;

View File

@ -105,7 +105,6 @@ SINGLE_BATTLE_TEST("Eject Pack activates once intimidate mon switches in")
SINGLE_BATTLE_TEST("Eject Pack will not activate if Parting Shot user can switch out")
{
ASSUME(gItemsInfo[ITEM_EJECT_PACK].holdEffect == HOLD_EFFECT_EJECT_PACK);
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); }
PLAYER(SPECIES_WOBBUFFET);
@ -121,3 +120,20 @@ SINGLE_BATTLE_TEST("Eject Pack will not activate if Parting Shot user can switch
}
}
}
DOUBLE_BATTLE_TEST("Eject Pack will not trigger if the conditions are not met")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); }
PLAYER(SPECIES_BELDUM) { Ability(ABILITY_CLEAR_BODY); };
PLAYER(SPECIES_RALTS) { Ability(ABILITY_TRACE); Item(ITEM_EJECT_PACK); }
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
} WHEN {
TURN { SWITCH(opponentLeft, 2); SEND_OUT(playerLeft, 2); }
} SCENE {
}
}