From fcf13aab2b462ecafdd670e833a7bc02cc597e43 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sun, 19 Feb 2023 06:40:55 -0300 Subject: [PATCH 1/4] Fixed evolutions that use held items to evolve not working when using Rare Candies. (#2565) --- src/party_menu.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/party_menu.c b/src/party_menu.c index 4cecc825775f..8debf9f3c75c 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -5165,7 +5165,6 @@ void ItemUseCB_RareCandy(u8 taskId, TaskFunc task) u16 *itemPtr = &gSpecialVar_ItemId; bool8 cannotUseEffect; u8 holdEffectParam = ItemId_GetHoldEffectParam(*itemPtr); - u16 targetSpecies = GetEvolutionTargetSpecies(mon, EVO_MODE_NORMAL, ITEM_NONE, NULL); sInitialLevel = GetMonData(mon, MON_DATA_LEVEL); if (sInitialLevel != MAX_LEVEL) @@ -5181,10 +5180,22 @@ void ItemUseCB_RareCandy(u8 taskId, TaskFunc task) PlaySE(SE_SELECT); if (cannotUseEffect) { - if (targetSpecies != SPECIES_NONE && holdEffectParam == 0) + u16 targetSpecies = SPECIES_NONE; + + // Resets values to 0 so other means of teaching moves doesn't overwrite levels + sInitialLevel = 0; + sFinalLevel = 0; + + if (holdEffectParam == 0) + targetSpecies = GetEvolutionTargetSpecies(mon, EVO_MODE_NORMAL, ITEM_NONE, NULL); + + if (targetSpecies != SPECIES_NONE) { - PartyMenuTryEvolution(taskId); RemoveBagItem(gSpecialVar_ItemId, 1); + FreePartyPointers(); + gCB2_AfterEvolution = gPartyMenu.exitCallback; + BeginEvolutionScene(mon, targetSpecies, TRUE, gPartyMenu.slotId); + DestroyTask(taskId); } else { From ec343cef02438173223b3f5d3e71d89443649015 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sun, 19 Feb 2023 06:45:59 -0300 Subject: [PATCH 2/4] Config to have Shuckle make Berry Juice from Oran Berries (#2331) * Removed unused ifdefs and made actually check for Z Power Ring * Config to have Shuckle make Berry Juice from Oran Berries * Ordered species-specific configs --- include/config/pokemon.h | 7 +++++-- src/battle_script_commands.c | 24 ++++++++++++++++++------ src/battle_z_move.c | 4 ---- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/include/config/pokemon.h b/include/config/pokemon.h index 4cb2271d5a5e..ce5faf2a6ec9 100644 --- a/include/config/pokemon.h +++ b/include/config/pokemon.h @@ -13,11 +13,14 @@ #define P_EGG_HATCH_LEVEL GEN_LATEST // Since Gen 4, Pokémon will hatch from eggs at level 1 instead of 5. #define P_BALL_INHERITING GEN_LATEST // Since Gen 6, Eggs from the Daycare will inherit the Poké Ball from their mother. From Gen7 onwards, the father can pass it down as well, as long as it's of the same species as the mother. -// Other settings +// Species-specific settings #define P_SHEDINJA_BALL GEN_LATEST // Since Gen 4, Shedinja requires a Poké Ball for its evolution. In Gen 3, Shedinja inherits Nincada's Ball. -#define P_LEGENDARY_PERFECT_IVS GEN_LATEST // Since Gen 6, Legendaries, Mythicals and Ultra Beasts found in the wild or given through gifts have at least 3 perfect IVs. #define P_KADABRA_EVERSTONE GEN_LATEST // Since Gen 4, Kadabra can evolve even when holding an Everstone. #define P_HIPPO_GENDER_DIFF_ICONS TRUE // If TRUE, will give Hippopotas and Hippowdon custom icons for their female forms. +#define P_SHUCKLE_BERRY_JUICE TRUE // In Gen 2, Shuckle had a 1/16 chance of converting Berry that it's holding into Berry Juice. Setting this to TRUE will allow to do this with an Oran Berry, which is the spiritual succesor of the Berry item. + +// Other settings +#define P_LEGENDARY_PERFECT_IVS GEN_LATEST // Since Gen 6, Legendaries, Mythicals and Ultra Beasts found in the wild or given through gifts have at least 3 perfect IVs. // Flag settings // To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 87feb5627103..8b8d4f1e9485 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -14922,7 +14922,6 @@ static void Cmd_pickup(void) heldItem = GetBattlePyramidPickupItemId(); SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &heldItem); } - #if (defined ITEM_HONEY) else if (ability == ABILITY_HONEY_GATHER && species != 0 && species != SPECIES_EGG @@ -14934,7 +14933,15 @@ static void Cmd_pickup(void) SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &heldItem); } } - #endif + #if P_SHUCKLE_BERRY_JUICE == TRUE + else if (species == SPECIES_SHUCKLE + && heldItem == ITEM_ORAN_BERRY + && (Random() % 16) == 0) + { + heldItem = ITEM_BERRY_JUICE; + SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &heldItem); + } + #endif } } else @@ -14972,7 +14979,6 @@ static void Cmd_pickup(void) } } } - #if (defined ITEM_HONEY) else if (ability == ABILITY_HONEY_GATHER && species != 0 && species != SPECIES_EGG @@ -14984,7 +14990,15 @@ static void Cmd_pickup(void) SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &heldItem); } } - #endif + #if P_SHUCKLE_BERRY_JUICE == TRUE + else if (species == SPECIES_SHUCKLE + && heldItem == ITEM_ORAN_BERRY + && (Random() % 16) == 0) + { + heldItem = ITEM_BERRY_JUICE; + SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &heldItem); + } + #endif } } @@ -16073,10 +16087,8 @@ static bool32 CriticalCapture(u32 odds) else odds = (odds * 250) / 100; - #ifdef ITEM_CATCHING_CHARM if (CheckBagHasItem(ITEM_CATCHING_CHARM, 1)) odds = (odds * (100 + B_CATCHING_CHARM_BOOST)) / 100; - #endif odds /= 6; if ((Random() % 255) < odds) diff --git a/src/battle_z_move.c b/src/battle_z_move.c index bdbf5674c830..536080aa96c5 100644 --- a/src/battle_z_move.c +++ b/src/battle_z_move.c @@ -204,11 +204,7 @@ bool32 IsViableZMove(u8 battlerId, u16 move) else holdEffect = ItemId_GetHoldEffect(item); - #ifdef ITEM_ULTRANECROZIUM_Z - if (holdEffect == HOLD_EFFECT_Z_CRYSTAL || item == ITEM_ULTRANECROZIUM_Z) - #else if (holdEffect == HOLD_EFFECT_Z_CRYSTAL) - #endif { u16 zMove = GetSignatureZMove(move, gBattleMons[battlerId].species, item); if (zMove != MOVE_NONE) From 4b64433816d0a2c6c29aa12dfcaabe1b03a18299 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Sun, 19 Feb 2023 05:48:12 -0500 Subject: [PATCH 3/4] Add Battle Anim cmds for dynamic Task, Sprite creation + Misc. Anim Fixes (#2649) * add createvisualtaskontargets, createspriteontargets to fix electroweb, fiery wrath anims * add missing semicolon * add Cmd_createspriteontargets_onpos for heal block, fix heal block targeting * remove duplicate func * improve origin pulse anim * fix IsDoubleBattle call * venom drench acid uses average battler positions * add GetSubpriorityForMoveAnim * add GetBattleAnimMoveTargets for CreateSpriteOnTargets and Cmd_createvisualtaskontargets --------- Co-authored-by: ghoulslash --- asm/macros/battle_anim_script.inc | 44 +++++++ data/battle_anim_scripts.s | 90 +++++++------ src/battle_anim.c | 212 +++++++++++++++++++++++++++--- src/battle_anim_effects_1.c | 26 +++- src/data/battle_moves.h | 2 +- 5 files changed, 310 insertions(+), 64 deletions(-) diff --git a/asm/macros/battle_anim_script.inc b/asm/macros/battle_anim_script.inc index a98a344fa1bf..6ff38769068c 100644 --- a/asm/macros/battle_anim_script.inc +++ b/asm/macros/battle_anim_script.inc @@ -270,6 +270,50 @@ .macro stopsound .byte 0x2f .endm + + @ same as createvisualtask except takes in battlerargindex, which is the battle anim arg index of the battler to loop through + .macro createvisualtaskontargets addr:req, priority:req, battlerargindex:req, argv:vararg + .byte 0x30 + .4byte \addr + .byte \priority + .byte \battlerargindex + .byte (.Lcreatetask_\@_2 - .Lcreatetask_\@_1) / 2 @ num_args +.Lcreatetask_\@_1: + .2byte \argv +.Lcreatetask_\@_2: + .endm + + @ same as createsprite except takes in battlerargindex, which is the battle anim arg index of the battler to loop through + .macro createspriteontargets template:req, anim_battler:req, subpriority_offset:req, battlerargindex:req, argv:vararg + .byte 0x31 + .4byte \template + .if \anim_battler == ANIM_TARGET + .byte 0x80 | (\subpriority_offset & 0x7F) + .else + .byte (\subpriority_offset & 0x7F) + .endif + .byte \battlerargindex + .byte (.Lsprite_\@_2 - .Lsprite_\@_1) / 2 +.Lsprite_\@_1: + .2byte \argv +.Lsprite_\@_2: + .endm + + @ does not overwrite gBattleAnimArgs[battlerargindex], some sprite templates are too dependent on the value (e.g. heal block) + .macro createspriteontargets_onpos template:req, anim_battler:req, subpriority_offset:req, battlerargindex:req, argv:vararg + .byte 0x32 + .4byte \template + .if \anim_battler == ANIM_TARGET + .byte 0x80 | (\subpriority_offset & 0x7F) + .else + .byte (\subpriority_offset & 0x7F) + .endif + .byte \battlerargindex + .byte (.Lsprite_\@_2 - .Lsprite_\@_1) / 2 +.Lsprite_\@_1: + .2byte \argv +.Lsprite_\@_2: + .endm @ useful macros .macro jumpreteq value:req, ptr:req diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 0ad58c49e106..71bd93d70a11 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -1492,22 +1492,22 @@ Move_HEAL_BLOCK: loadspritegfx ANIM_TAG_BLUE_STAR monbg ANIM_TARGET createsoundtask SoundTask_PlaySeChangingVolume, SE_M_ABSORB_2, SOUND_PAN_TARGET, 256, -16, 0, 2 - createsprite gHealingBlueStarSpriteTemplate, ANIM_TARGET, 2, 0, -5, 1, 0 + createspriteontargets_onpos gHealingBlueStarSpriteTemplate, ANIM_TARGET, 2, 2, 0, -5, ANIM_TARGET, 0 delay 7 - createsprite gHealingBlueStarSpriteTemplate, ANIM_TARGET, 2, -15, 10, 1, 0 + createspriteontargets_onpos gHealingBlueStarSpriteTemplate, ANIM_TARGET, 2, 2, -15, 10, ANIM_TARGET, 0 delay 7 - createvisualtask AnimTask_BlendBattleAnimPal, 10, 1 | 4, 4, 2, 12, 0, RGB_BLACK - createsprite gHealingBlueStarSpriteTemplate, ANIM_TARGET, 2, 0, -5, 1, 0 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_DEF_SIDE, 4, 2, 12, 0, RGB_BLACK + createspriteontargets_onpos gHealingBlueStarSpriteTemplate, ANIM_TARGET, 2, 2, 0, -5, ANIM_TARGET, 0 delay 7 - createsprite gHealingBlueStarSpriteTemplate, ANIM_TARGET, 2, -15, 10, 1, 0 + createspriteontargets_onpos gHealingBlueStarSpriteTemplate, ANIM_TARGET, 2, 2, -15, 10, ANIM_TARGET, 0 delay 7 - createsprite gHealingBlueStarSpriteTemplate, ANIM_TARGET, 2, -15, -15, 1, 0 + createspriteontargets_onpos gHealingBlueStarSpriteTemplate, ANIM_TARGET, 2, 2, -15, -15, ANIM_TARGET, 0 delay 7 - createsprite gHealingBlueStarSpriteTemplate, ANIM_TARGET, 2, 10, -5, 1, 0 + createspriteontargets_onpos gHealingBlueStarSpriteTemplate, ANIM_TARGET, 2, 2, 10, -5, ANIM_TARGET, 0 delay 7 waitforvisualfinish delay 11 - createvisualtask AnimTask_BlendBattleAnimPal, 10, 1 | 4, 4, 2, 0, 12, RGB_BLACK + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_DEF_SIDE, 4, 2, 0, 12, RGB_BLACK waitforvisualfinish clearmonbg ANIM_TARGET end @@ -6405,11 +6405,7 @@ Move_ELECTROWEB: clearmonbg ANIM_DEF_PARTNER delay 1 createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 5, 1, 2, 9, 0, RGB_BLACK - - @ ElectricityEffect looks ugly against both opponents, to do later - jumpifdoublebattle Move_ELECTROWEB_Wait - - call ElectricityEffect + call ElectricityEffect_OnTargets Move_ELECTROWEB_Wait: waitforvisualfinish end @@ -9278,16 +9274,16 @@ Move_EERIE_IMPULSE:: Move_VENOM_DRENCH:: loadspritegfx ANIM_TAG_POISON_BUBBLE monbg ANIM_DEF_PARTNER - launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0xfffb 0x1 0xfffb 0x0 + launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0xfffb 0x1 0xfffb 1 playsewithpan SE_M_BUBBLE3, SOUND_PAN_TARGET delay 0x2 - launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0x5 0x0 0x6 0x0 + launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0x5 0x0 0x6 1 playsewithpan SE_M_BUBBLE3, SOUND_PAN_TARGET delay 0x2 - launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0x13 0x1 0xa 0x0 + launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0x13 0x1 0xa 1 playsewithpan SE_M_BUBBLE3, SOUND_PAN_TARGET delay 0x2 - launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0xffe9 0x2 0xfff6 0x0 + launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0xffe9 0x2 0xfff6 1 playsewithpan SE_M_BUBBLE3, SOUND_PAN_TARGET delay 0x2 call AcidDrench @@ -9296,28 +9292,28 @@ Move_VENOM_DRENCH:: clearmonbg ANIM_DEF_PARTNER end AcidDrench: - launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0xffec 0x0 0xfff6 0x0 + launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0xffec 0x0 0xfff6 1 playsewithpan SE_M_BUBBLE3, SOUND_PAN_TARGET delay 0x2 - launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0x1c 0x1 0xa 0x0 + launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0x1c 0x1 0xa 1 playsewithpan SE_M_BUBBLE3, SOUND_PAN_TARGET delay 0x2 - launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0xfff6 0x1 0xfffb 0x0 + launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0xfff6 0x1 0xfffb 1 playsewithpan SE_M_BUBBLE3, SOUND_PAN_TARGET delay 0x2 - launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0xa 0x0 0x6 0x0 + launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0xa 0x0 0x6 1 playsewithpan SE_M_BUBBLE3, SOUND_PAN_TARGET delay 0x2 - launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0x18 0x1 0xa 0x0 + launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0x18 0x1 0xa 1 playsewithpan SE_M_BUBBLE3, SOUND_PAN_TARGET delay 0x2 - launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0xffe0 0x2 0xfff6 0x0 + launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0xffe0 0x2 0xfff6 1 playsewithpan SE_M_BUBBLE3, SOUND_PAN_TARGET delay 0x2 - launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0xffec 0x0 0xfff6 0x0 + launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0xffec 0x0 0xfff6 1 playsewithpan SE_M_BUBBLE3, SOUND_PAN_TARGET delay 0x2 - launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0x1e 0x2 0xa 0x0 + launchtemplate gVenomDrenchAcidTemplate 0x82, 0x4, 0x1e 0x2 0xa 1 playsewithpan SE_M_BUBBLE3, SOUND_PAN_TARGET delay 0x2 return @@ -10175,6 +10171,7 @@ Move_ORIGIN_PULSE:: launchtemplate gOriginPulseOrbInwardTemplate 0x82 0x5 0x1 0x0 0xFF2A 0xFFAA 0x10 @between left and upper left launchtemplate gOriginPulseOrbInwardTemplate 0x82 0x5 0x1 0x0 0xFFDA 0xFF94 0x10 @between up and upper left waitforvisualfinish + createvisualtaskontargets AnimTask_ShakeMon2, 5, 0, ANIM_TARGET, 2, 0, 18, 1 monbg ANIM_DEF_PARTNER launchtemplate gOriginPulseBasicSplatTemplate 0x83 0x4 0xffb0 0xfff0 0x1 0x1 stopsound @@ -23375,15 +23372,15 @@ Move_OVERHEAT: waitforvisualfinish createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 3, -5, 3, ANIM_TARGET, 0 playsewithpan SE_M_FLAMETHROWER, SOUND_PAN_TARGET - createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 10, 0, 25, 1 + createvisualtaskontargets AnimTask_ShakeMon, 2, 0, ANIM_TARGET, 10, 0, 25, 1 delay 6 - createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 3, 8, -5, ANIM_TARGET, 0 + createspriteontargets gBasicHitSplatSpriteTemplate, ANIM_TARGET, 3, 2, 8, -5, ANIM_TARGET, 0 playsewithpan SE_M_FLAMETHROWER, SOUND_PAN_TARGET delay 8 - createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 3, 10, 10, ANIM_TARGET, 0 + createspriteontargets gBasicHitSplatSpriteTemplate, ANIM_TARGET, 3, 2, 10, 10, ANIM_TARGET, 0 playsewithpan SE_M_FLAMETHROWER, SOUND_PAN_TARGET delay 8 - createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 3, 0, 0, ANIM_TARGET, 0 + createspriteontargets gBasicHitSplatSpriteTemplate, ANIM_TARGET, 3, 2, 0, 0, ANIM_TARGET, 0 playsewithpan SE_M_FLAMETHROWER, SOUND_PAN_TARGET createvisualtask AnimTask_CopyPalFadedToUnfaded, 5, 1 delay 1 @@ -24209,21 +24206,40 @@ WaterBubblesEffectLong: ElectricityEffect: playsewithpan SE_M_THUNDERBOLT2, SOUND_PAN_TARGET ElectricityEffectNoSound: - createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, 5, 0, 5, 0, ANIM_TARGET + createspriteontargets gElectricitySpriteTemplate, ANIM_TARGET, 2, 5, 0, 5, 0, ANIM_TARGET delay 2 - createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, -5, 10, 5, 1, ANIM_TARGET + createspriteontargets gElectricitySpriteTemplate, ANIM_TARGET, 2, -5, 10, 5, 1, ANIM_TARGET delay 2 - createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, 15, 20, 5, 2, ANIM_TARGET + createspriteontargets gElectricitySpriteTemplate, ANIM_TARGET, 2, 15, 20, 5, 2, ANIM_TARGET delay 2 - createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, -15, -10, 5, 0, ANIM_TARGET + createspriteontargets gElectricitySpriteTemplate, ANIM_TARGET, 2, -15, -10, 5, 0, ANIM_TARGET delay 2 - createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, 25, 0, 5, 1, ANIM_TARGET + createspriteontargets gElectricitySpriteTemplate, ANIM_TARGET, 2, 25, 0, 5, 1, ANIM_TARGET delay 2 - createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, -8, 8, 5, 2, ANIM_TARGET + createspriteontargets gElectricitySpriteTemplate, ANIM_TARGET, 2, -8, 8, 5, 2, ANIM_TARGET delay 2 - createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, 2, -8, 5, 0, ANIM_TARGET + createspriteontargets gElectricitySpriteTemplate, ANIM_TARGET, 2, 2, -8, 5, 0, ANIM_TARGET delay 2 - createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, -20, 15, 5, 1, ANIM_TARGET + createspriteontargets gElectricitySpriteTemplate, ANIM_TARGET, 2, -20, 15, 5, 1, ANIM_TARGET + return + +ElectricityEffect_OnTargets: + playsewithpan SE_M_THUNDERBOLT2, SOUND_PAN_TARGET + createspriteontargets gElectricitySpriteTemplate, ANIM_TARGET, 2, 4, 5, 0, 5, 0, ANIM_TARGET + delay 2 + createspriteontargets gElectricitySpriteTemplate, ANIM_TARGET, 2, 4, -5, 10, 5, 1, ANIM_TARGET + delay 2 + createspriteontargets gElectricitySpriteTemplate, ANIM_TARGET, 2, 4, 15, 20, 5, 2, ANIM_TARGET + delay 2 + createspriteontargets gElectricitySpriteTemplate, ANIM_TARGET, 2, 4, -15, -10, 5, 0, ANIM_TARGET + delay 2 + createspriteontargets gElectricitySpriteTemplate, ANIM_TARGET, 2, 4, 25, 0, 5, 1, ANIM_TARGET + delay 2 + createspriteontargets gElectricitySpriteTemplate, ANIM_TARGET, 2, 4, -8, 8, 5, 2, ANIM_TARGET + delay 2 + createspriteontargets gElectricitySpriteTemplate, ANIM_TARGET, 2, 4, 2, -8, 5, 0, ANIM_TARGET + delay 2 + createspriteontargets gElectricitySpriteTemplate, ANIM_TARGET, 2, 4, -20, 15, 5, 1, ANIM_TARGET return ConfusionEffect: diff --git a/src/battle_anim.c b/src/battle_anim.c index 610c24321695..a7faec1fda43 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -3,6 +3,7 @@ #include "battle_anim.h" #include "battle_controllers.h" #include "battle_interface.h" +#include "battle_util.h" #include "bg.h" #include "contest.h" #include "decompress.h" @@ -81,7 +82,9 @@ static void Cmd_visible(void); static void Cmd_teamattack_moveback(void); static void Cmd_teamattack_movefwd(void); static void Cmd_stopsound(void); - +static void Cmd_createvisualtaskontargets(void); +static void Cmd_createspriteontargets(void); +static void Cmd_createspriteontargets_onpos(void); static void RunAnimScriptCommand(void); static void Task_UpdateMonBg(u8 taskId); static void FlipBattlerBgTiles(void); @@ -169,6 +172,9 @@ static void (* const sScriptCmdTable[])(void) = Cmd_teamattack_moveback, // 0x2D Cmd_teamattack_movefwd, // 0x2E Cmd_stopsound, // 0x2F + Cmd_createvisualtaskontargets, // 0x30 + Cmd_createspriteontargets, // 0x31 + Cmd_createspriteontargets_onpos, // 0x32 }; void ClearBattleAnimationVars(void) @@ -425,29 +431,46 @@ static void Cmd_unloadspritegfx(void) ClearSpriteIndex(GET_TRUE_SPRITE_INDEX(index)); } -static void Cmd_createsprite(void) +static u8 GetBattleAnimMoveTargets(u8 battlerArgIndex, u8 *targets) { - s32 i; - const struct SpriteTemplate *template; - u8 argVar; - u8 argsCount; - s16 subpriority; - - sBattleAnimScriptPtr++; - template = (const struct SpriteTemplate *)(T2_READ_32(sBattleAnimScriptPtr)); - sBattleAnimScriptPtr += 4; - - argVar = sBattleAnimScriptPtr[0]; - sBattleAnimScriptPtr++; - - argsCount = sBattleAnimScriptPtr[0]; - sBattleAnimScriptPtr++; - for (i = 0; i < argsCount; i++) + u8 numTargets = 1; + switch (GetBattlerMoveTargetType(gBattleAnimAttacker, gAnimMoveIndex)) { - gBattleAnimArgs[i] = T1_READ_16(sBattleAnimScriptPtr); - sBattleAnimScriptPtr += 2; + case MOVE_TARGET_BOTH: + targets[0] = gBattleAnimArgs[battlerArgIndex]; + numTargets = 1; + if (IsBattlerAlive(targets[0] ^ BIT_FLANK)) { + targets[1] = targets[0] ^ BIT_FLANK; + numTargets++; + } + break; + case MOVE_TARGET_FOES_AND_ALLY: + targets[0] = gBattleAnimArgs[battlerArgIndex]; + numTargets = 1; + + if (IsBattlerAlive(targets[0] ^ BIT_FLANK)) { + targets[1] = targets[0] ^ BIT_FLANK; + numTargets++; + } + + if (IsBattlerAlive(gBattleAnimAttacker ^ BIT_FLANK)) { + targets[2] = gBattleAnimAttacker ^ BIT_FLANK; + numTargets++; + } + break; + default: + targets[0] = gBattleAnimArgs[battlerArgIndex]; // original + numTargets = 1; + break; } + + return numTargets; +} +static s16 GetSubpriorityForMoveAnim(u8 argVar) +{ + s16 subpriority; + if (argVar & ANIMSPRITE_IS_TARGET) { argVar ^= ANIMSPRITE_IS_TARGET; @@ -470,6 +493,34 @@ static void Cmd_createsprite(void) if (subpriority < 3) subpriority = 3; + + return subpriority; +} + +static void Cmd_createsprite(void) +{ + s32 i; + const struct SpriteTemplate *template; + u8 argVar; + u8 argsCount; + s16 subpriority; + + sBattleAnimScriptPtr++; + template = (const struct SpriteTemplate *)(T2_READ_32(sBattleAnimScriptPtr)); + sBattleAnimScriptPtr += 4; + + argVar = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + + argsCount = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + for (i = 0; i < argsCount; i++) + { + gBattleAnimArgs[i] = T1_READ_16(sBattleAnimScriptPtr); + sBattleAnimScriptPtr += 2; + } + + subpriority = GetSubpriorityForMoveAnim(argVar); CreateSpriteAndAnimate( template, @@ -479,6 +530,85 @@ static void Cmd_createsprite(void) gAnimVisualTaskCount++; } +static void CreateSpriteOnTargets(const struct SpriteTemplate *template, u8 argVar, u8 battlerArgIndex, u8 argsCount, bool32 overwriteAnimTgt) +{ + u32 i; + u8 targets[MAX_BATTLERS_COUNT]; + int ntargets; + s16 subpriority; + + for (i = 0; i < argsCount; i++) + { + gBattleAnimArgs[i] = T1_READ_16(sBattleAnimScriptPtr); + sBattleAnimScriptPtr += 2; + } + + subpriority = GetSubpriorityForMoveAnim(argVar); + + ntargets = GetBattleAnimMoveTargets(battlerArgIndex, targets); + + for (i = 0; i < ntargets; i++) { + + if (overwriteAnimTgt) + gBattleAnimArgs[battlerArgIndex] = targets[i]; + + CreateSpriteAndAnimate( + template, + GetBattlerSpriteCoord(targets[i], BATTLER_COORD_X_2), + GetBattlerSpriteCoord(targets[i], BATTLER_COORD_Y_PIC_OFFSET), + subpriority); + gAnimVisualTaskCount++; + } +} + +// will NOT overwrite gBattleAnimArgs +static void Cmd_createspriteontargets_onpos(void) +{ + const struct SpriteTemplate *template; + u8 argVar; + u8 argsCount; + u8 battlerArgIndex; + + sBattleAnimScriptPtr++; + template = (const struct SpriteTemplate *)(T2_READ_32(sBattleAnimScriptPtr)); + sBattleAnimScriptPtr += 4; + + argVar = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + + battlerArgIndex = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + + argsCount = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + + CreateSpriteOnTargets(template, argVar, battlerArgIndex, argsCount, FALSE); +} + +// DOES overwrite gBattleAnimArgs +static void Cmd_createspriteontargets(void) +{ + const struct SpriteTemplate *template; + u8 argVar; + u8 argsCount; + u8 battlerArgIndex; + + sBattleAnimScriptPtr++; + template = (const struct SpriteTemplate *)(T2_READ_32(sBattleAnimScriptPtr)); + sBattleAnimScriptPtr += 4; + + argVar = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + + battlerArgIndex = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + + argsCount = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + + CreateSpriteOnTargets(template, argVar, battlerArgIndex, argsCount, TRUE); +} + static void Cmd_createvisualtask(void) { TaskFunc taskFunc; @@ -509,6 +639,48 @@ static void Cmd_createvisualtask(void) gAnimVisualTaskCount++; } +static void Cmd_createvisualtaskontargets(void) +{ + TaskFunc taskFunc; + u8 taskPriority; + u8 taskId; + u8 numArgs; + u8 battlerArgIndex; // index in gBattleAnimArgs that has the battlerId + s32 i; + u8 targets[MAX_BATTLERS_COUNT] = {0}; + + sBattleAnimScriptPtr++; + + taskFunc = (TaskFunc)T2_READ_32(sBattleAnimScriptPtr); + sBattleAnimScriptPtr += 4; + + taskPriority = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + + battlerArgIndex = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + + numArgs = sBattleAnimScriptPtr[0]; + sBattleAnimScriptPtr++; + + // copy task arguments + for (i = 0; i < numArgs; i++) { + gBattleAnimArgs[i] = T1_READ_16(sBattleAnimScriptPtr); + sBattleAnimScriptPtr += 2; + } + + numArgs = GetBattleAnimMoveTargets(battlerArgIndex, targets); + + for (i = 0; i < numArgs; i++) + { + gBattleAnimArgs[battlerArgIndex] = targets[i]; + taskId = CreateTask(taskFunc, taskPriority); + taskFunc(taskId); + gAnimVisualTaskCount++; + } +} + + static void Cmd_delay(void) { sBattleAnimScriptPtr++; diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index 761a1886c4bd..8dae62029324 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -4806,8 +4806,8 @@ void AnimTask_CycleMagicalLeafPal(u8 taskId) void AnimNeedleArmSpike(struct Sprite *sprite) { - u8 a; - u8 b; + s16 a; + s16 b; u16 c; u16 x; u16 y; @@ -4820,13 +4820,27 @@ void AnimNeedleArmSpike(struct Sprite *sprite) { if (gBattleAnimArgs[0] == 0) { - a = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - b = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + if (IsDoubleBattle()) + { + SetAverageBattlerPositions(gBattleAnimAttacker, TRUE, &a, &b); + } + else + { + a = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + b = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + } } else { - a = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - b = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + if (IsDoubleBattle()) + { + SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &a, &b); + } + else + { + a = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + b = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + } } sprite->data[0] = gBattleAnimArgs[4]; diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 997e7f4b3482..415ef234ceaa 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -6833,7 +6833,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = .accuracy = 100, .pp = 15, .secondaryEffectChance = 0, - .target = MOVE_TARGET_SELECTED, + .target = MOVE_TARGET_BOTH, .priority = 0, .split = SPLIT_STATUS, .zMovePower = 0, From 380af442c39bf2af87a0e31b23d12e12b251f6ec Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Sun, 19 Feb 2023 12:05:56 +0100 Subject: [PATCH 4/4] Fix buggy pokemon anims with Illusion (#2639) * try illusion fix * fix --- include/battle_util.h | 1 + src/battle_controller_link_opponent.c | 4 +++- src/battle_controller_opponent.c | 4 +++- src/battle_util.c | 8 ++++++++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index bf3943a9d85d..0661081e43b8 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -181,6 +181,7 @@ void UndoMegaEvolution(u32 monId); void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut); bool32 DoBattlersShareType(u32 battler1, u32 battler2); bool32 CanBattlerGetOrLoseItem(u8 battlerId, u16 itemId); +u32 GetIllusionMonSpecies(u32 battlerId); struct Pokemon *GetIllusionMonPtr(u32 battlerId); void ClearIllusionMon(u32 battlerId); bool32 SetIllusionMon(struct Pokemon *mon, u32 battlerId); diff --git a/src/battle_controller_link_opponent.c b/src/battle_controller_link_opponent.c index 97fc21df9e3f..908363907b3c 100644 --- a/src/battle_controller_link_opponent.c +++ b/src/battle_controller_link_opponent.c @@ -1149,7 +1149,9 @@ static void StartSendOutAnim(u8 battlerId, bool8 dontClearSubstituteBit) ClearTemporarySpeciesSpriteData(battlerId, dontClearSubstituteBit); gBattlerPartyIndexes[battlerId] = gBattleResources->bufferA[battlerId][1]; - species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + species = GetIllusionMonSpecies(battlerId); + if (species == SPECIES_NONE) + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); gBattleControllerData[battlerId] = CreateInvisibleSpriteWithCallback(SpriteCB_WaitForBattlerBallReleaseAnim); BattleLoadOpponentMonSpriteGfx(&gEnemyParty[gBattlerPartyIndexes[battlerId]], battlerId); SetMultiuseSpriteTemplateToPokemon(species, GetBattlerPosition(battlerId)); diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 0a9626a13cbb..79283b0674e9 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -1177,7 +1177,9 @@ static void StartSendOutAnim(u8 battlerId, bool8 dontClearSubstituteBit) ClearTemporarySpeciesSpriteData(battlerId, dontClearSubstituteBit); gBattlerPartyIndexes[battlerId] = gBattleResources->bufferA[battlerId][1]; - species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + species = GetIllusionMonSpecies(battlerId); + if (species == SPECIES_NONE) + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); gBattleControllerData[battlerId] = CreateInvisibleSpriteWithCallback(SpriteCB_WaitForBattlerBallReleaseAnim); BattleLoadOpponentMonSpriteGfx(&gEnemyParty[gBattlerPartyIndexes[battlerId]], battlerId); SetMultiuseSpriteTemplateToPokemon(species, GetBattlerPosition(battlerId)); diff --git a/src/battle_util.c b/src/battle_util.c index 46f8d3a3d3be..25ba83093c48 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10266,6 +10266,14 @@ void ClearIllusionMon(u32 battlerId) memset(&gBattleStruct->illusion[battlerId], 0, sizeof(gBattleStruct->illusion[battlerId])); } +u32 GetIllusionMonSpecies(u32 battlerId) +{ + struct Pokemon *illusionMon = GetIllusionMonPtr(battlerId); + if (illusionMon != NULL) + return GetMonData(illusionMon, MON_DATA_SPECIES); + return SPECIES_NONE; +} + bool32 SetIllusionMon(struct Pokemon *mon, u32 battlerId) { struct Pokemon *party, *partnerMon;