Implemented Primal Reversion

This commit is contained in:
LOuroboros 2021-08-25 03:35:21 -03:00
parent fbc4d7584e
commit 91a68cd5db
25 changed files with 455 additions and 49 deletions

View File

@ -1543,6 +1543,11 @@
.byte \case
.endm
.macro handleprimalreversion battler:req, case:req
various \battler, VARIOUS_HANDLE_PRIMAL_REVERSION
.byte \case
.endm
.macro handleformchange battler:req, case:req
various \battler, VARIOUS_HANDLE_FORM_CHANGE
.byte \case
@ -1825,6 +1830,11 @@
various BS_ATTACKER, VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER
.endm
.macro jumpifcantreverttoprimal ptr:req
various BS_ATTACKER, VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL
.4byte \ptr
.endm
@ helpful macros
.macro setstatchanger stat:req, stages:req, down:req
setbyte sSTATCHANGER \stat | \stages << 3 | \down << 7

View File

@ -4,6 +4,7 @@
#include "constants/songs.h"
#include "constants/moves.h"
#include "constants/pokemon.h"
#include "constants/items.h"
.include "asm/macros.inc"
.include "asm/macros/battle_anim_script.inc"
.include "constants/constants.inc"
@ -824,6 +825,7 @@ gBattleAnims_General::
.4byte General_TotemFlare @ B_ANIM_TOTEM_FLARE
.4byte General_GulpMissile @ B_ANIM_GULP_MISSILE
.4byte General_StrongWinds @ B_ANIM_STRONG_WINDS
.4byte General_PrimalReversion @ B_ANIM_PRIMAL_REVERSION
.align 2
gBattleAnims_Special::
@ -24399,6 +24401,17 @@ General_TotemFlare::
clearmonbg ANIM_ATTACKER
end
RainbowEndureEffect:
launchtemplate gBlueEndureEnergySpriteTemplate 0x2 0x4 0x0 0xffe8 0x1a 0x2
delay 0x3
launchtemplate gEndureEnergySpriteTemplate 0x2 0x4 0x0 0xe 0x1c 0x1 @Red Buff
delay 0x3
launchtemplate gGreenEndureEnergySpriteTemplate 0x2 0x4 0x0 0xfffb 0xa 0x2
delay 0x3
launchtemplate gYellowEndureEnergySpriteTemplate 0x2 0x4 0x0 0x1c 0x1a 0x3
delay 0x3
return
General_GulpMissile: @ Tackle anim (placeholder)
loadspritegfx ANIM_TAG_IMPACT
monbg ANIM_ATTACKER
@ -24424,15 +24437,77 @@ General_StrongWinds::
stopsound
end
RainbowEndureEffect:
launchtemplate gBlueEndureEnergySpriteTemplate 0x2 0x4 0x0 0xffe8 0x1a 0x2
delay 0x3
launchtemplate gEndureEnergySpriteTemplate 0x2 0x4 0x0 0xe 0x1c 0x1 @Red Buff
delay 0x3
launchtemplate gGreenEndureEnergySpriteTemplate 0x2 0x4 0x0 0xfffb 0xa 0x2
delay 0x3
launchtemplate gYellowEndureEnergySpriteTemplate 0x2 0x4 0x0 0x1c 0x1a 0x3
delay 0x3
General_PrimalReversion::
launchtask AnimTask_PrimalReversion 0x5 0x0
jumpargeq 0x0, ITEM_RED_ORB, General_PrimalReversion_Omega
jumpargeq 0x1, ITEM_BLUE_ORB, General_PrimalReversion_Alpha
General_PrimalReversion_Alpha:
loadspritegfx ANIM_TAG_ALPHA_STONE
loadspritegfx ANIM_TAG_PRIMAL_PARTICLES
loadspritegfx ANIM_TAG_ALPHA_SYMBOL
monbg ANIM_ATTACKER
setalpha 12, 8
loopsewithpan SE_M_MEGA_KICK, SOUND_PAN_ATTACKER, 13, 3
createvisualtask AnimTask_BlendColorCycle, 2, 2, 0, 6, 0, 11, RGB(31, 31, 11)
call PrimalReversionParticles
call PrimalReversionParticles
call PrimalReversionParticles
waitforvisualfinish
playsewithpan SE_M_SOLAR_BEAM, SOUND_PAN_ATTACKER
createsprite gAlphaStoneSpriteTemplate, ANIM_ATTACKER, 41, 0, 0, 0, 0
delay 20
createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA
waitforvisualfinish
createvisualtask AnimTask_TransformMon, 2, 0, 1
createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA
createvisualtask AnimTask_HorizontalShake, 5, 1, 5, 14
waitforvisualfinish
createsprite gAlphaSymbolSpriteTemplate ANIM_ATTACKER, 2
waitforvisualfinish
clearmonbg ANIM_ATK_PARTNER
blendoff
end
General_PrimalReversion_Omega:
loadspritegfx ANIM_TAG_OMEGA_STONE
loadspritegfx ANIM_TAG_PRIMAL_PARTICLES
loadspritegfx ANIM_TAG_OMEGA_SYMBOL
monbg ANIM_ATTACKER
setalpha 12, 8
loopsewithpan SE_M_MEGA_KICK, SOUND_PAN_ATTACKER, 13, 3
createvisualtask AnimTask_BlendColorCycle, 2, 2, 0, 6, 0, 11, RGB(31, 31, 11)
call PrimalReversionParticles
call PrimalReversionParticles
call PrimalReversionParticles
waitforvisualfinish
playsewithpan SE_M_SOLAR_BEAM, SOUND_PAN_ATTACKER
createsprite gOmegaStoneSpriteTemplate, ANIM_ATTACKER, 41, 0, 0, 0, 0
delay 20
createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA
waitforvisualfinish
createvisualtask AnimTask_TransformMon, 2, 0, 1
createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA
createvisualtask AnimTask_HorizontalShake, 5, 1, 5, 14
waitforvisualfinish
createsprite gOmegaSymbolSpriteTemplate ANIM_ATTACKER, 2
waitforvisualfinish
clearmonbg ANIM_ATK_PARTNER
blendoff
end
PrimalReversionParticles:
createsprite gPrimalParticlesSpriteTemplate, ANIM_ATTACKER, 2, 40, -10, 13
delay 3
createsprite gPrimalParticlesSpriteTemplate, ANIM_ATTACKER, 2, -35, -10, 13
delay 3
createsprite gPrimalParticlesSpriteTemplate, ANIM_ATTACKER, 2, 15, -40, 13
delay 3
createsprite gPrimalParticlesSpriteTemplate, ANIM_ATTACKER, 2, -10, -32, 13
delay 3
createsprite gPrimalParticlesSpriteTemplate, ANIM_ATTACKER, 2, 25, -20, 13
delay 3
createsprite gPrimalParticlesSpriteTemplate, ANIM_ATTACKER, 2, -40, -20, 13
delay 3
createsprite gPrimalParticlesSpriteTemplate, ANIM_ATTACKER, 2, 5, -40, 13
delay 3
return
SnatchMoveTrySwapFromSubstitute:

View File

@ -5599,6 +5599,9 @@ BattleScript_DoSwitchOut::
hidepartystatussummary BS_ATTACKER
switchinanim BS_ATTACKER, FALSE
waitstate
jumpifcantreverttoprimal BattleScript_DoSwitchOut2
call BattleScript_PrimalReversionRet
BattleScript_DoSwitchOut2:
switchineffects BS_ATTACKER
moveendcase MOVEEND_STATUS_IMMUNITY_ABILITIES
moveendcase MOVEEND_MIRROR_MOVE
@ -6625,6 +6628,33 @@ BattleScript_WishMegaEvolution::
switchinabilities BS_ATTACKER
end2
BattleScript_PrimalReversion::
printstring STRINGID_EMPTYSTRING3
waitmessage 1
setbyte gIsCriticalHit, 0
handleprimalreversion BS_ATTACKER, 0
handleprimalreversion BS_ATTACKER, 1
playanimation BS_ATTACKER, B_ANIM_PRIMAL_REVERSION, NULL
waitanimation
handleprimalreversion BS_ATTACKER, 2
printstring STRINGID_PKMNREVERTEDTOPRIMAL
waitmessage B_WAIT_TIME_LONG
switchinabilities BS_ATTACKER
end2
BattleScript_PrimalReversionRet::
printstring STRINGID_EMPTYSTRING3
waitmessage 1
setbyte gIsCriticalHit, 0
handleprimalreversion BS_ATTACKER, 0
handleprimalreversion BS_ATTACKER, 1
playanimation BS_ATTACKER, B_ANIM_PRIMAL_REVERSION, NULL
waitanimation
handleprimalreversion BS_ATTACKER, 2
printstring STRINGID_PKMNREVERTEDTOPRIMAL
waitmessage B_WAIT_TIME_LONG
return
BattleScript_AttackerFormChange::
pause 5
copybyte gBattlerAbility, gBattlerAttacker

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

View File

@ -461,10 +461,14 @@ struct MegaEvolutionData
bool8 alreadyEvolved[4]; // Array id is used for mon position.
u16 evolvedSpecies[MAX_BATTLERS_COUNT];
u16 playerEvolvedSpecies;
u8 primalRevertedPartyIds[2]; // As flags using gBitTable;
u16 primalRevertedSpecies[MAX_BATTLERS_COUNT];
u16 playerPrimalRevertedSpecies;
u8 battlerId;
bool8 playerSelect;
u8 triggerSpriteId;
bool8 isWishMegaEvo;
bool8 isPrimalReversion;
};
struct Illusion

View File

@ -39,16 +39,20 @@ enum
#define TAG_STATUS_SUMMARY_BAR_TILE 0xD70C
#define TAG_STATUS_SUMMARY_BALLS_TILE 0xD714
#define TAG_MEGA_TRIGGER_TILE 0xD777
#define TAG_MEGA_TRIGGER_TILE 0xD777
#define TAG_MEGA_INDICATOR_TILE 0xD778
#define TAG_ALPHA_INDICATOR_TILE 0xD779
#define TAG_OMEGA_INDICATOR_TILE 0xD77A
#define TAG_HEALTHBOX_PAL 0xD6FF
#define TAG_HEALTHBAR_PAL 0xD704
#define TAG_STATUS_SUMMARY_BAR_PAL 0xD710
#define TAG_STATUS_SUMMARY_BALLS_PAL 0xD712
#define TAG_MEGA_TRIGGER_PAL 0xD777
#define TAG_MEGA_INDICATOR_PAL 0xD778
#define TAG_MEGA_TRIGGER_PAL 0xD777
#define TAG_MEGA_INDICATOR_PAL 0xD778
#define TAG_ALPHA_INDICATOR_PAL 0xD779
#define TAG_OMEGA_INDICATOR_PAL 0xD77A
enum
{

View File

@ -398,5 +398,6 @@ extern const u8 BattleScript_MysteriousAirCurrentBlowsOn[];
extern const u8 BattleScript_AttackWeakenedByStrongWinds[];
extern const u8 BattleScript_BlockedByPrimalWeatherEnd3[];
extern const u8 BattleScript_BlockedByPrimalWeatherRet[];
extern const u8 BattleScript_PrimalReversion[];
#endif // GUARD_BATTLE_SCRIPTS_H

View File

@ -391,6 +391,9 @@
#define ANIM_TAG_DREEPY (ANIM_SPRITES_START + 379)
#define ANIM_TAG_ICE_ROCK_SINGLE (ANIM_SPRITES_START + 380)
#define ANIM_TAG_STONE_PILLAR_MULTI (ANIM_SPRITES_START + 381)
#define ANIM_TAG_ALPHA_SYMBOL (ANIM_SPRITES_START + 382)
#define ANIM_TAG_OMEGA_SYMBOL (ANIM_SPRITES_START + 383)
#define ANIM_TAG_PRIMAL_PARTICLES (ANIM_SPRITES_START + 384)
// battlers
#define ANIM_ATTACKER 0
@ -525,6 +528,7 @@
#define B_ANIM_TOTEM_FLARE 28 // Totem boosts aura flare
#define B_ANIM_GULP_MISSILE 29
#define B_ANIM_STRONG_WINDS 30
#define B_ANIM_PRIMAL_REVERSION 31
// special animations table (gBattleAnims_Special)
#define B_ANIM_LVL_UP 0

View File

@ -185,6 +185,8 @@
#define VARIOUS_REMOVE_TERRAIN 113
#define VARIOUS_JUMP_IF_PRANKSTER_BLOCKED 114
#define VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER 115
#define VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL 116
#define VARIOUS_HANDLE_PRIMAL_REVERSION 117
// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0

View File

@ -592,8 +592,9 @@
#define STRINGID_STRONGWINDSDISSIPATED 588
#define STRINGID_MYSTERIOUSAIRCURRENTBLOWSON 589
#define STRINGID_ATTACKWEAKENEDBSTRONGWINDS 590
#define STRINGID_PKMNREVERTEDTOPRIMAL 591
#define BATTLESTRINGS_COUNT 591
#define BATTLESTRINGS_COUNT 592
// The below IDs are all indexes into battle message tables,
// used to determine which of a set of messages to print.

View File

@ -336,25 +336,43 @@
#define F_SUMMARY_SCREEN_FLIP_SPRITE 0x80
// Evolution types
#define EVO_MEGA_EVOLUTION 0xffff // Not an actual evolution, used to temporarily mega evolve in battle.
#define EVO_MOVE_MEGA_EVOLUTION 0xfffe // Mega Evolution that checks for a move instead of held item.
#define EVO_FRIENDSHIP 1 // Pokémon levels up with friendship ≥ 220
#define EVO_FRIENDSHIP_DAY 2 // Pokémon levels up during the day with friendship ≥ 220
#define EVO_FRIENDSHIP_NIGHT 3 // Pokémon levels up at night with friendship ≥ 220
#define EVO_LEVEL 4 // Pokémon reaches the specified level
#define EVO_TRADE 5 // Pokémon is traded
#define EVO_TRADE_ITEM 6 // Pokémon is traded while it's holding the specified item
#define EVO_ITEM 7 // specified item is used on Pokémon
#define EVO_LEVEL_ATK_GT_DEF 8 // Pokémon reaches the specified level with attack > defense
#define EVO_LEVEL_ATK_EQ_DEF 9 // Pokémon reaches the specified level with attack = defense
#define EVO_LEVEL_ATK_LT_DEF 10 // Pokémon reaches the specified level with attack < defense
#define EVO_LEVEL_SILCOON 11 // Pokémon reaches the specified level with a Silcoon personality value
#define EVO_LEVEL_CASCOON 12 // Pokémon reaches the specified level with a Cascoon personality value
#define EVO_LEVEL_NINJASK 13 // Pokémon reaches the specified level (special value for Ninjask)
#define EVO_LEVEL_SHEDINJA 14 // Pokémon reaches the specified level (special value for Shedinja)
#define EVO_BEAUTY 15 // Pokémon levels up with beauty ≥ specified value
#define EVO_MEGA_EVOLUTION 0xffff // Not an actual evolution, used to temporarily mega evolve in battle.
#define EVO_MOVE_MEGA_EVOLUTION 0xfffe // Mega Evolution that checks for a move instead of held item.
#define EVO_PRIMAL_REVERSION 0xfffd // Not an actual evolution, used to undergo primal reversion in battle.
#define EVO_FRIENDSHIP 1 // Pokémon levels up with friendship ≥ 220
#define EVO_FRIENDSHIP_DAY 2 // Pokémon levels up during the day with friendship ≥ 220
#define EVO_FRIENDSHIP_NIGHT 3 // Pokémon levels up at night with friendship ≥ 220
#define EVO_LEVEL 4 // Pokémon reaches the specified level
#define EVO_TRADE 5 // Pokémon is traded
#define EVO_TRADE_ITEM 6 // Pokémon is traded while it's holding the specified item
#define EVO_ITEM 7 // specified item is used on Pokémon
#define EVO_LEVEL_ATK_GT_DEF 8 // Pokémon reaches the specified level with attack > defense
#define EVO_LEVEL_ATK_EQ_DEF 9 // Pokémon reaches the specified level with attack = defense
#define EVO_LEVEL_ATK_LT_DEF 10 // Pokémon reaches the specified level with attack < defense
#define EVO_LEVEL_SILCOON 11 // Pokémon reaches the specified level with a Silcoon personality value
#define EVO_LEVEL_CASCOON 12 // Pokémon reaches the specified level with a Cascoon personality value
#define EVO_LEVEL_NINJASK 13 // Pokémon reaches the specified level (special value for Ninjask)
#define EVO_LEVEL_SHEDINJA 14 // Pokémon reaches the specified level (special value for Shedinja)
#define EVO_BEAUTY 15 // Pokémon levels up with beauty ≥ specified value
#define EVO_LEVEL_FEMALE 16 // Pokémon reaches the specified level, is female
#define EVO_LEVEL_MALE 17 // Pokémon reaches the specified level, is male
#define EVO_LEVEL_NIGHT 18 // Pokémon reaches the specified level, is night
#define EVO_LEVEL_DAY 19 // Pokémon reaches the specified level, is day
#define EVO_LEVEL_DUSK 20 // Pokémon reaches the specified level, is dusk (5-6 P.M)
#define EVO_ITEM_HOLD_DAY 21 // Pokémon levels up, holds specified item at day
#define EVO_ITEM_HOLD_NIGHT 22 // Pokémon levels up, holds specified item at night
#define EVO_MOVE 23 // Pokémon levels up, knows specified move
#define EVO_MOVE_TYPE 24 // Pokémon levels up, knows move with specified type
#define EVO_MAPSEC 25 // Pokémon levels up on specified mapsec
#define EVO_ITEM_MALE 26 // specified item is used on a male Pokémon
#define EVO_ITEM_FEMALE 27 // specified item is used on a female Pokémon
#define EVO_LEVEL_RAIN 28 // Pokémon reaches the specified level while it's raining
#define EVO_SPECIFIC_MON_IN_PARTY 29 // Pokémon levels up with a specified Pokémon in party
#define EVO_LEVEL_DARK_TYPE_MON_IN_PARTY 30 // Pokémon reaches the specified level with a Dark Type Pokémon in party
#define EVO_TRADE_SPECIFIC_MON 31 // Pokémon is traded for a specified Pokémon
#define EVO_SPECIFIC_MAP 32 // Pokémon levels up on specified map
#define EVOS_PER_MON 5
#define EVOS_PER_MON 10
// Evolution 'modes,' for GetEvolutionTargetSpecies
#define EVO_MODE_NORMAL 0

View File

@ -4749,6 +4749,8 @@ extern const u32 gBattleAnimSpriteGfx_MegaStone[];
extern const u32 gBattleAnimSpritePal_MegaStone[];
extern const u32 gBattleAnimSpriteGfx_MegaParticles[];
extern const u32 gBattleAnimSpritePal_MegaParticles[];
extern const u32 gBattleAnimSpriteGfx_PrimalParticles[];
extern const u32 gBattleAnimSpritePal_PrimalParticles[];
extern const u32 gBattleAnimSpriteGfx_MegaSymbol[];
extern const u32 gBattleAnimSpritePal_MegaSymbol[];
extern const u32 gBattleAnimSpriteGfx_FlashCannonBall[];
@ -4765,6 +4767,8 @@ extern const u32 gBattleAnimSpriteGfx_AcupressureFinger[];
extern const u32 gBattleAnimSpritePal_AcupressureFinger[];
extern const u32 gBattleAnimSpriteGfx_AlphaStone[];
extern const u32 gBattleAnimSpritePal_AlphaStone[];
extern const u32 gBattleAnimSpriteGfx_AlphaSymbol[];
extern const u32 gBattleAnimSpritePal_AlphaSymbol[];
extern const u32 gBattleAnimSpriteGfx_Anchor[];
extern const u32 gBattleAnimSpriteGfx_Apple[];
extern const u32 gBattleAnimSpritePal_Apple[];
@ -4867,6 +4871,8 @@ extern const u32 gBattleAnimSpriteGfx_Obstruct[];
extern const u32 gBattleAnimSpritePal_Obstruct[];
extern const u32 gBattleAnimSpriteGfx_OmegaStone[];
extern const u32 gBattleAnimSpritePal_OmegaStone[];
extern const u32 gBattleAnimSpriteGfx_OmegaSymbol[];
extern const u32 gBattleAnimSpritePal_OmegaSymbol[];
extern const u32 gBattleAnimSpriteGfx_PinkDiamond[];
extern const u32 gBattleAnimSpritePal_PinkDiamond[];
extern const u32 gBattleAnimSpriteGfx_PoisonColumn[];

View File

@ -1564,6 +1564,9 @@ const struct CompressedSpriteSheet gBattleAnimPicTable[] =
{gBattleAnimSpriteGfx_DreepyMissile, 0x200, ANIM_TAG_DREEPY},
{gBattleAnimSpriteGfx_IceRock, 0x1800, ANIM_TAG_ICE_ROCK_SINGLE},
{gBattleAnimSpriteGfx_StonePillar, 0x1800, ANIM_TAG_STONE_PILLAR_MULTI},
{gBattleAnimSpriteGfx_AlphaSymbol, 0x0200, ANIM_TAG_ALPHA_SYMBOL},
{gBattleAnimSpriteGfx_OmegaSymbol, 0x0200, ANIM_TAG_OMEGA_SYMBOL},
{gBattleAnimSpriteGfx_PrimalParticles, 0x0180, ANIM_TAG_PRIMAL_PARTICLES},
};
const struct CompressedSpritePalette gBattleAnimPaletteTable[] =
@ -2011,6 +2014,9 @@ const struct CompressedSpritePalette gBattleAnimPaletteTable[] =
{gBattleAnimSpritePal_DreepyMissile, ANIM_TAG_DREEPY},
{gBattleAnimSpritePal_IceRock, ANIM_TAG_ICE_ROCK_SINGLE},
{gBattleAnimSpritePal_StonePillar, ANIM_TAG_STONE_PILLAR_MULTI},
{gBattleAnimSpritePal_AlphaSymbol, ANIM_TAG_ALPHA_SYMBOL},
{gBattleAnimSpritePal_OmegaSymbol, ANIM_TAG_OMEGA_SYMBOL},
{gBattleAnimSpritePal_PrimalParticles, ANIM_TAG_PRIMAL_PARTICLES},
};
const struct BattleAnimBackground gBattleAnimBackgroundTable[] =

View File

@ -1219,6 +1219,61 @@ const struct SpriteTemplate gMegaSymbolSpriteTemplate =
.callback = AnimGhostStatusSprite,
};
const struct SpriteTemplate gAlphaStoneSpriteTemplate =
{
.tileTag = ANIM_TAG_ALPHA_STONE,
.paletteTag = ANIM_TAG_ALPHA_STONE,
.oam = &gOamData_AffineDouble_ObjBlend_64x64,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gAffineAnims_LusterPurgeCircle,
.callback = AnimSpriteOnMonPos,
};
const struct SpriteTemplate gOmegaStoneSpriteTemplate =
{
.tileTag = ANIM_TAG_OMEGA_STONE,
.paletteTag = ANIM_TAG_OMEGA_STONE,
.oam = &gOamData_AffineDouble_ObjBlend_64x64,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gAffineAnims_LusterPurgeCircle,
.callback = AnimSpriteOnMonPos,
};
const struct SpriteTemplate gPrimalParticlesSpriteTemplate =
{
.tileTag = ANIM_TAG_PRIMAL_PARTICLES,
.paletteTag = ANIM_TAG_PRIMAL_PARTICLES,
.oam = &gOamData_AffineNormal_ObjBlend_16x16,
.anims = gPowerAbsorptionOrbAnimTable,
.images = NULL,
.affineAnims = gPowerAbsorptionOrbAffineAnimTable,
.callback = AnimPowerAbsorptionOrb,
};
const struct SpriteTemplate gAlphaSymbolSpriteTemplate =
{
.tileTag = ANIM_TAG_ALPHA_SYMBOL,
.paletteTag = ANIM_TAG_ALPHA_SYMBOL,
.oam = &gOamData_AffineOff_ObjBlend_32x32,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimGhostStatusSprite,
};
const struct SpriteTemplate gOmegaSymbolSpriteTemplate =
{
.tileTag = ANIM_TAG_OMEGA_SYMBOL,
.paletteTag = ANIM_TAG_OMEGA_SYMBOL,
.oam = &gOamData_AffineOff_ObjBlend_32x32,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimGhostStatusSprite,
};
void AnimBlackSmoke(struct Sprite *sprite)
{
sprite->x += gBattleAnimArgs[0];

View File

@ -15,6 +15,7 @@
#include "battle_controllers.h"
#include "constants/moves.h"
#include "constants/hold_effects.h"
#include "constants/items.h"
//// function declarations
static void SpriteCB_SpriteToCentreOfSide(struct Sprite* sprite);
@ -5020,3 +5021,12 @@ void AnimTask_TechnoBlast(u8 taskId)
gBattleAnimArgs[0] = 0;
DestroyAnimVisualTask(taskId);
}
void AnimTask_PrimalReversion(u8 taskId)
{
if (ItemId_GetId(gBattleMons[gBattleAnimAttacker].item) == ITEM_RED_ORB)
gBattleAnimArgs[0] = ItemId_GetId(gBattleMons[gBattleAnimAttacker].item);
else
gBattleAnimArgs[0] = 0;
DestroyAnimVisualTask(taskId);
}

View File

@ -665,6 +665,28 @@ static const struct SpritePalette sSpritePalette_MegaIndicator =
sMegaIndicatorPal, TAG_MEGA_INDICATOR_PAL
};
static const u8 sAlphaIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/alpha_indicator.4bpp");
static const u16 sAlphaIndicatorPal[] = INCBIN_U16("graphics/battle_interface/alpha_indicator.gbapal");
static const u8 sOmegaIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/omega_indicator.4bpp");
static const u16 sOmegaIndicatorPal[] = INCBIN_U16("graphics/battle_interface/omega_indicator.gbapal");
static const struct SpriteSheet sSpriteSheet_AlphaIndicator =
{
sAlphaIndicatorGfx, sizeof(sAlphaIndicatorGfx), TAG_ALPHA_INDICATOR_TILE
};
static const struct SpritePalette sSpritePalette_AlphaIndicator =
{
sAlphaIndicatorPal, TAG_ALPHA_INDICATOR_PAL
};
static const struct SpriteSheet sSpriteSheet_OmegaIndicator =
{
sOmegaIndicatorGfx, sizeof(sOmegaIndicatorGfx), TAG_OMEGA_INDICATOR_TILE
};
static const struct SpritePalette sSpritePalette_OmegaIndicator =
{
sOmegaIndicatorPal, TAG_OMEGA_INDICATOR_PAL
};
static const struct OamData sOamData_MegaIndicator =
{
.y = 0,
@ -693,6 +715,28 @@ static const struct SpriteTemplate sSpriteTemplate_MegaIndicator =
.callback = SpriteCb_MegaIndicator,
};
static const struct SpriteTemplate sSpriteTemplate_AlphaIndicator =
{
.tileTag = TAG_ALPHA_INDICATOR_TILE,
.paletteTag = TAG_ALPHA_INDICATOR_PAL,
.oam = &sOamData_MegaIndicator,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCb_MegaIndicator,
};
static const struct SpriteTemplate sSpriteTemplate_OmegaIndicator =
{
.tileTag = TAG_OMEGA_INDICATOR_TILE,
.paletteTag = TAG_OMEGA_INDICATOR_PAL,
.oam = &sOamData_MegaIndicator,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCb_MegaIndicator,
};
// code
@ -805,8 +849,9 @@ u8 CreateBattlerHealthboxSprites(u8 battlerId)
healthBarSpritePtr->hBar_Data6 = data6;
healthBarSpritePtr->invisible = TRUE;
// Create mega indicator sprite if is a mega evolved mon.
if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]])
// Create mega indicator sprite if is a mega evolved or a primal reverted mon.
if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]
|| gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]])
{
megaIndicatorSpriteId = CreateMegaIndicatorSprite(battlerId, 0);
gSprites[megaIndicatorSpriteId].invisible = TRUE;
@ -910,7 +955,8 @@ void SetHealthboxSpriteVisible(u8 healthboxSpriteId)
gSprites[healthboxSpriteId].invisible = FALSE;
gSprites[gSprites[healthboxSpriteId].hMain_HealthBarSpriteId].invisible = FALSE;
gSprites[gSprites[healthboxSpriteId].oam.affineParam].invisible = FALSE;
if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]])
if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]
|| gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]])
{
u8 spriteId = GetMegaIndicatorSpriteId(healthboxSpriteId);
if (spriteId != 0xFF)
@ -1033,8 +1079,9 @@ static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl)
u8 *objVram;
u8 battler = gSprites[healthboxSpriteId].hMain_Battler;
// Don't print Lv char if mon is mega evolved.
if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]])
// Don't print Lv char if mon is mega evolved or primal reverted.
if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]]
|| gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]])
{
objVram = ConvertIntToDecimalStringN(text, lvl, STR_CONV_MODE_LEFT_ALIGN, 3);
xPos = 5 * (3 - (objVram - (text + 2))) - 1;
@ -1506,12 +1553,28 @@ u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which)
u32 spriteId, position;
s16 x, y;
LoadSpritePalette(&sSpritePalette_MegaIndicator);
LoadSpriteSheet(&sSpriteSheet_MegaIndicator);
if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]])
{
LoadSpritePalette(&sSpritePalette_MegaIndicator);
LoadSpriteSheet(&sSpriteSheet_MegaIndicator);
}
else if (gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]])
{
if (GET_BASE_SPECIES_ID(gBattleMons[battlerId].species) == SPECIES_GROUDON)
{
LoadSpritePalette(&sSpritePalette_OmegaIndicator);
LoadSpriteSheet(&sSpriteSheet_OmegaIndicator);
}
else if (GET_BASE_SPECIES_ID(gBattleMons[battlerId].species) == SPECIES_KYOGRE)
{
LoadSpritePalette(&sSpritePalette_AlphaIndicator);
LoadSpriteSheet(&sSpriteSheet_AlphaIndicator);
}
}
position = GetBattlerPosition(battlerId);
GetBattlerHealthboxCoords(battlerId, &x, &y);
x += sIndicatorPositions[position][0];
y += sIndicatorPositions[position][1];
@ -1519,10 +1582,20 @@ u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which)
x -= 4;
else if (gBattleMons[battlerId].level < 10)
x += 5;
spriteId = CreateSpriteAtEnd(&sSpriteTemplate_MegaIndicator, x, y, 0);
gSprites[gSprites[gHealthboxSpriteIds[battlerId]].oam.affineParam].hOther_IndicatorSpriteId = spriteId;
if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]])
{
spriteId = CreateSpriteAtEnd(&sSpriteTemplate_MegaIndicator, x, y, 0);
}
else if (gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]])
{
if (GET_BASE_SPECIES_ID(gBattleMons[battlerId].species) == SPECIES_GROUDON)
spriteId = CreateSpriteAtEnd(&sSpriteTemplate_OmegaIndicator, x, y, 0);
else if (GET_BASE_SPECIES_ID(gBattleMons[battlerId].species) == SPECIES_KYOGRE)
spriteId = CreateSpriteAtEnd(&sSpriteTemplate_AlphaIndicator, x, y, 0);
}
gSprites[gSprites[gHealthboxSpriteIds[battlerId]].oam.affineParam].hOther_IndicatorSpriteId = spriteId;
gSprites[spriteId].tBattler = battlerId;
return spriteId;
}

View File

@ -3512,6 +3512,18 @@ static void TryDoEventsBeforeFirstTurn(void)
}
memset(gTotemBoosts, 0, sizeof(gTotemBoosts)); // erase all totem boosts just to be safe
// Primal Reversion
for (i = 0; i < gBattlersCount; i++)
{
if (CanMegaEvolve(i)
&& GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_PRIMAL_ORB)
{
gBattlerAttacker = i;
BattleScriptExecute(BattleScript_PrimalReversion);
return;
}
}
// Check all switch in abilities happening from the fastest mon to slowest.
while (gBattleStruct->switchInAbilitiesCounter < gBattlersCount)
{

View File

@ -718,9 +718,11 @@ static const u8 sText_MysteriousAirCurrent[] = _("A mysterious air current is\np
static const u8 sText_StrongWindsDissipated[] = _("The mysterious strong winds\nhave dissipated!{PAUSE 64}");
static const u8 sText_MysteriousAirCurrentBlowsOn[] = _("The mysterious air current\nblows on regardless!");
static const u8 sText_AttackWeakenedByStrongWinds[] = _("The mysterious strong winds\nweakened the attack!");
static const u8 sText_PkmnRevertedToPrimal[] = _("{B_ATK_NAME_WITH_PREFIX}'s Primal Reversion!\nIt reverted to its primal form!");
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
{
[STRINGID_PKMNREVERTEDTOPRIMAL - 12] = sText_PkmnRevertedToPrimal,
[STRINGID_ATTACKWEAKENEDBSTRONGWINDS - 12] = sText_AttackWeakenedByStrongWinds,
[STRINGID_MYSTERIOUSAIRCURRENTBLOWSON - 12] = sText_MysteriousAirCurrentBlowsOn,
[STRINGID_STRONGWINDSDISSIPATED - 12] = sText_StrongWindsDissipated,

View File

@ -56,6 +56,7 @@
#include "constants/party_menu.h"
extern struct MusicPlayerInfo gMPlayInfo_BGM;
extern struct Evolution gEvolutionTable[][EVOS_PER_MON];
extern const u8* const gBattleScriptsForMoveEffects[];
@ -4545,7 +4546,12 @@ static void Cmd_playanimation(void)
|| gBattlescriptCurrInstr[2] == B_ANIM_MEGA_EVOLUTION
|| gBattlescriptCurrInstr[2] == B_ANIM_ILLUSION_OFF
|| gBattlescriptCurrInstr[2] == B_ANIM_FORM_CHANGE
|| gBattlescriptCurrInstr[2] == B_ANIM_SUBSTITUTE_FADE)
|| gBattlescriptCurrInstr[2] == B_ANIM_SUBSTITUTE_FADE
|| gBattlescriptCurrInstr[2] == B_ANIM_RAIN_CONTINUES
|| gBattlescriptCurrInstr[2] == B_ANIM_SUN_CONTINUES
|| gBattlescriptCurrInstr[2] == B_ANIM_SANDSTORM_CONTINUES
|| gBattlescriptCurrInstr[2] == B_ANIM_HAIL_CONTINUES
|| gBattlescriptCurrInstr[2] == B_ANIM_PRIMAL_REVERSION)
{
BtlController_EmitBattleAnimation(0, gBattlescriptCurrInstr[2], *argumentPtr);
MarkBattlerForControllerExec(gActiveBattler);
@ -4591,7 +4597,11 @@ static void Cmd_playanimation2(void) // animation Id is stored in the first poin
|| *animationIdPtr == B_ANIM_MEGA_EVOLUTION
|| *animationIdPtr == B_ANIM_ILLUSION_OFF
|| *animationIdPtr == B_ANIM_FORM_CHANGE
|| *animationIdPtr == B_ANIM_SUBSTITUTE_FADE)
|| *animationIdPtr == B_ANIM_SUBSTITUTE_FADE
|| *animationIdPtr == B_ANIM_RAIN_CONTINUES
|| *animationIdPtr == B_ANIM_SUN_CONTINUES
|| *animationIdPtr == B_ANIM_SANDSTORM_CONTINUES
|| *animationIdPtr == B_ANIM_PRIMAL_REVERSION)
{
BtlController_EmitBattleAnimation(0, *animationIdPtr, *argumentPtr);
MarkBattlerForControllerExec(gActiveBattler);
@ -8179,6 +8189,47 @@ static void Cmd_various(void)
}
gBattlescriptCurrInstr += 4;
return;
case VARIOUS_HANDLE_PRIMAL_REVERSION:
if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT)
mon = &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]];
else
mon = &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]];
// Change species.
if (gBattlescriptCurrInstr[3] == 0)
{
u16 primalSpecies;
gBattleStruct->mega.primalRevertedSpecies[gActiveBattler] = gBattleMons[gActiveBattler].species;
if (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_LEFT
|| (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_RIGHT && !(gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER))))
{
gBattleStruct->mega.playerPrimalRevertedSpecies = gBattleStruct->mega.primalRevertedSpecies[gActiveBattler];
}
// Checks Primal Reversion
primalSpecies = GetMegaEvolutionSpecies(gBattleStruct->mega.primalRevertedSpecies[gActiveBattler], gBattleMons[gActiveBattler].item);
gBattleMons[gActiveBattler].species = primalSpecies;
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gActiveBattler].species);
BtlController_EmitSetMonData(0, REQUEST_SPECIES_BATTLE, gBitTable[gBattlerPartyIndexes[gActiveBattler]], 2, &gBattleMons[gActiveBattler].species);
MarkBattlerForControllerExec(gActiveBattler);
}
// Change stats.
else if (gBattlescriptCurrInstr[3] == 1)
{
RecalcBattlerStats(gActiveBattler, mon);
gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(gActiveBattler)] |= gBitTable[gBattlerPartyIndexes[gActiveBattler]];
}
// Update healthbox and elevation.
else
{
UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], mon, HEALTHBOX_ALL);
CreateMegaIndicatorSprite(gActiveBattler, 0);
if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT)
SetBattlerShadowSpriteCallback(gActiveBattler, gBattleMons[gActiveBattler].species);
}
gBattlescriptCurrInstr += 4;
return;
case VARIOUS_HANDLE_FORM_CHANGE:
if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT)
mon = &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]];
@ -8822,6 +8873,21 @@ static void Cmd_various(void)
}
break;
}
case VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL:
{
bool8 canDoPrimalReversion = FALSE;
for (i = 0; i < EVOS_PER_MON; i++)
{
if (gEvolutionTable[gBattleMons[gActiveBattler].species][i].method == EVO_PRIMAL_REVERSION
&& gEvolutionTable[gBattleMons[gActiveBattler].species][i].param == gBattleMons[gActiveBattler].item)
canDoPrimalReversion = TRUE;
}
if (!canDoPrimalReversion)
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
else
gBattlescriptCurrInstr += 7;
}
}
gBattlescriptCurrInstr += 3;

View File

@ -8154,7 +8154,8 @@ static bool32 CanEvolve(u32 species)
{
if (gEvolutionTable[species][i].method
&& gEvolutionTable[species][i].method != EVO_MEGA_EVOLUTION
&& gEvolutionTable[species][i].method != EVO_MOVE_MEGA_EVOLUTION)
&& gEvolutionTable[species][i].method != EVO_MOVE_MEGA_EVOLUTION
&& gEvolutionTable[species][i].method != EVO_PRIMAL_REVERSION)
return TRUE;
}
return FALSE;
@ -8708,9 +8709,10 @@ u16 GetMegaEvolutionSpecies(u16 preEvoSpecies, u16 heldItemId)
for (i = 0; i < EVOS_PER_MON; i++)
{
if (gEvolutionTable[preEvoSpecies][i].method == EVO_MEGA_EVOLUTION
&& gEvolutionTable[preEvoSpecies][i].param == heldItemId)
return gEvolutionTable[preEvoSpecies][i].targetSpecies;
if ((gEvolutionTable[preEvoSpecies][i].method == EVO_MEGA_EVOLUTION
|| gEvolutionTable[preEvoSpecies][i].method == EVO_PRIMAL_REVERSION)
&& gEvolutionTable[preEvoSpecies][i].param == heldItemId)
return gEvolutionTable[preEvoSpecies][i].targetSpecies;
}
return SPECIES_NONE;
}
@ -8775,12 +8777,20 @@ bool32 CanMegaEvolve(u8 battlerId)
else
holdEffect = ItemId_GetHoldEffect(itemId);
// Can Mega Evolve via Item.
// Can Mega Evolve via Mega Stone.
if (holdEffect == HOLD_EFFECT_MEGA_STONE)
{
gBattleStruct->mega.isWishMegaEvo = FALSE;
return TRUE;
}
// Can undergo Primal Reversion.
if (holdEffect == HOLD_EFFECT_PRIMAL_ORB)
{
gBattleStruct->mega.isWishMegaEvo = FALSE;
gBattleStruct->mega.isPrimalReversion = TRUE;
return TRUE;
}
}
// Check if there is an entry in the evolution table for Wish Mega Evolution.
@ -8796,12 +8806,20 @@ bool32 CanMegaEvolve(u8 battlerId)
void UndoMegaEvolution(u32 monId)
{
u16 baseSpecies = GET_BASE_SPECIES_ID(GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES));
if (gBattleStruct->mega.evolvedPartyIds[B_SIDE_PLAYER] & gBitTable[monId])
{
gBattleStruct->mega.evolvedPartyIds[B_SIDE_PLAYER] &= ~(gBitTable[monId]);
SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &gBattleStruct->mega.playerEvolvedSpecies);
CalculateMonStats(&gPlayerParty[monId]);
}
else if (gBattleStruct->mega.primalRevertedPartyIds[B_SIDE_PLAYER] & gBitTable[monId])
{
gBattleStruct->mega.primalRevertedPartyIds[B_SIDE_PLAYER] &= ~(gBitTable[monId]);
SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &baseSpecies);
CalculateMonStats(&gPlayerParty[monId]);
}
// While not exactly a mega evolution, Zygarde follows the same rules.
else if (GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, NULL) == SPECIES_ZYGARDE_COMPLETE)
{

View File

@ -41,6 +41,15 @@ const u32 gBattleAnimSpritePal_MegaParticles[] = INCBIN_U32("graphics/battle_ani
const u32 gBattleAnimSpriteGfx_MegaSymbol[] = INCBIN_U32("graphics/battle_anims/sprites/mega_symbol.4bpp.lz");
const u32 gBattleAnimSpritePal_MegaSymbol[] = INCBIN_U32("graphics/battle_anims/sprites/mega_symbol.gbapal.lz");
const u32 gBattleAnimSpriteGfx_AlphaSymbol[] = INCBIN_U32("graphics/battle_anims/sprites/alpha_symbol.4bpp.lz");
const u32 gBattleAnimSpritePal_AlphaSymbol[] = INCBIN_U32("graphics/battle_anims/sprites/alpha_symbol.gbapal.lz");
const u32 gBattleAnimSpriteGfx_OmegaSymbol[] = INCBIN_U32("graphics/battle_anims/sprites/omega_symbol.4bpp.lz");
const u32 gBattleAnimSpritePal_OmegaSymbol[] = INCBIN_U32("graphics/battle_anims/sprites/omega_symbol.gbapal.lz");
const u32 gBattleAnimSpriteGfx_PrimalParticles[] = INCBIN_U32("graphics/battle_anims/sprites/primal_particles.4bpp.lz");
const u32 gBattleAnimSpritePal_PrimalParticles[] = INCBIN_U32("graphics/battle_anims/sprites/primal_particles.gbapal.lz");
const u32 gBattleAnimSpriteGfx_FlashCannonBall[] = INCBIN_U32("graphics/battle_anims/sprites/flash_cannon_ball.4bpp.lz");
const u32 gBattleAnimSpritePal_FlashCannonBall[] = INCBIN_U32("graphics/battle_anims/sprites/flash_cannon_ball.gbapal.lz");