From f2840cb04767894ef1a7667ed719786a72b1dfbd Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:58:52 +0100 Subject: [PATCH 1/3] Fixes Eject Pack triggering twice on Intimidate (#6072) --- include/battle_util.h | 16 +++- src/battle_script_commands.c | 12 +-- src/battle_util.c | 113 ++++++++++++--------------- test/battle/hold_effect/eject_pack.c | 18 ++++- 4 files changed, 84 insertions(+), 75 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index dba6299dee..463d6609db 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -65,7 +65,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, @@ -80,6 +80,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 WEATHER_HAS_EFFECT ((!IsAbilityOnField(ABILITY_CLOUD_NINE) && !IsAbilityOnField(ABILITY_AIR_LOCK))) #define IS_WHOLE_SIDE_ALIVE(battler) ((IsBattlerAlive(battler) && IsBattlerAlive(BATTLE_PARTNER(battler)))) @@ -215,7 +225,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); @@ -272,7 +282,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); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 01b97938ef..55a192958c 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -10536,25 +10536,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; diff --git a/src/battle_util.c b/src/battle_util.c index d4debdd0de..f1457eacb3 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -6699,16 +6699,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)) @@ -6844,7 +6834,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))) @@ -6880,10 +6870,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)) { @@ -6911,7 +6901,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; @@ -6959,10 +6949,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)) { @@ -6978,10 +6968,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) @@ -6998,10 +6988,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) @@ -7027,10 +7017,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)) { @@ -7040,7 +7030,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); } @@ -7051,10 +7041,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]]; @@ -7101,7 +7114,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)) @@ -7198,7 +7211,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; @@ -7223,7 +7236,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 (gBattleStruct->boosterEnergyActivates & (1u << battler) || gBattleMons[battler].status2 & STATUS2_TRANSFORMED) return ITEM_NO_EFFECT; @@ -7487,7 +7500,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; @@ -7546,10 +7559,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; @@ -7746,24 +7759,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); @@ -7791,12 +7787,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; } } } @@ -8007,12 +8001,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; } } } @@ -8369,16 +8361,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; diff --git a/test/battle/hold_effect/eject_pack.c b/test/battle/hold_effect/eject_pack.c index bba874e1b3..3d674fe9e8 100644 --- a/test/battle/hold_effect/eject_pack.c +++ b/test/battle/hold_effect/eject_pack.c @@ -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 { + + } +} From e8d3b4163f4b312d846ed58a2e6f72e225efc82a Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Wed, 22 Jan 2025 14:50:23 +0100 Subject: [PATCH 2/3] Trainerslide animation fix (#6040) Co-authored-by: Hedara --- include/battle.h | 1 + include/config/battle.h | 3 +- src/battle_controllers.c | 106 +++++++++++++++++++-------------------- 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/include/battle.h b/include/battle.h index c762e7f766..10724041ca 100644 --- a/include/battle.h +++ b/include/battle.h @@ -832,6 +832,7 @@ struct BattleStruct u8 padding:7; u8 usedEjectItem; u8 usedMicleBerry; + u8 trainerSlideSpriteIds[MAX_BATTLERS_COUNT]; }; // The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider, diff --git a/include/config/battle.h b/include/config/battle.h index e3bde0d30c..226f649a33 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -291,7 +291,6 @@ #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. #endif // GUARD_CONFIG_BATTLE_H diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 727bc8e27f..cb794abacf 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -2258,12 +2258,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); } } @@ -2305,7 +2305,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); } @@ -2495,18 +2495,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 { @@ -2516,15 +2516,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 { @@ -2532,20 +2532,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; } @@ -2556,26 +2556,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; } @@ -2586,14 +2586,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; } @@ -2887,34 +2887,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); From 2aa0ee3de8915294986faed7f4abbebadd19d032 Mon Sep 17 00:00:00 2001 From: RavePossum <145081120+ravepossum@users.noreply.github.com> Date: Wed, 22 Jan 2025 18:20:07 -0500 Subject: [PATCH 3/3] Add dependency on json files to learnset helper (#6083) --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a1b6068156..a71c7bc755 100644 --- a/Makefile +++ b/Makefile @@ -426,7 +426,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