Merge remote-tracking branch 'RHH/battle_engine' into BE_plusMinus

# Conflicts:
#	include/constants/battle_config.h
This commit is contained in:
Eduardo Quezada D'Ottone 2022-07-21 16:28:16 -04:00
commit 56b9a50109
52 changed files with 12354 additions and 245 deletions

View File

@ -288,43 +288,57 @@
createvisualtask AnimTask_IsDoubleBattle, 0
jumprettrue \ptr
.endm
@ keep CFRU macros cause I'm lazy. todo: update to createsprite and createvisualtask, respectively
.macro launchtemplate launchtemplatePtr launchtemplatePriority launchtemplateArgsNo launchtemplatearg0 launchtemplatearg1 launchtemplatearg2 launchtemplatearg3 launchtemplatearg4 launchtemplatearg5 launchtemplatearg6 launchtemplatearg7 launchtemplatearg8
.byte 0x2
.word \launchtemplatePtr
.byte \launchtemplatePriority
.byte \launchtemplateArgsNo
.hword \launchtemplatearg0
.hword \launchtemplatearg1
.hword \launchtemplatearg2
.hword \launchtemplatearg3
.hword \launchtemplatearg4
.hword \launchtemplatearg5
.hword \launchtemplatearg6
.hword \launchtemplatearg7
.hword \launchtemplatearg8
.endm
.byte 0x2
.word \launchtemplatePtr
.byte \launchtemplatePriority
.byte \launchtemplateArgsNo
.hword \launchtemplatearg0
.hword \launchtemplatearg1
.hword \launchtemplatearg2
.hword \launchtemplatearg3
.hword \launchtemplatearg4
.hword \launchtemplatearg5
.hword \launchtemplatearg6
.hword \launchtemplatearg7
.hword \launchtemplatearg8
.endm
.macro launchtask launchtaskPtr launchtaskPriority launchtaskArgsNo launchtaskarg0 launchtaskarg1 launchtaskarg2 launchtaskarg3 launchtaskarg4 launchtaskarg5 launchtaskarg6 launchtaskarg7 launchtaskarg8
.byte 0x3
.word \launchtaskPtr
.byte \launchtaskPriority
.byte \launchtaskArgsNo
.hword \launchtaskarg0
.hword \launchtaskarg1
.hword \launchtaskarg2
.hword \launchtaskarg3
.hword \launchtaskarg4
.hword \launchtaskarg5
.hword \launchtaskarg6
.hword \launchtaskarg7
.hword \launchtaskarg8
.endm
.byte 0x3
.word \launchtaskPtr
.byte \launchtaskPriority
.byte \launchtaskArgsNo
.hword \launchtaskarg0
.hword \launchtaskarg1
.hword \launchtaskarg2
.hword \launchtaskarg3
.hword \launchtaskarg4
.hword \launchtaskarg5
.hword \launchtaskarg6
.hword \launchtaskarg7
.hword \launchtaskarg8
.endm
.macro setblends setblends_value
.byte 0xC
.hword \setblends_value
.endm
.byte 0xC
.hword \setblends_value
.endm
.macro launchsoundtask launchsoundtaskPtr launchsoundtaskArgsNo launchsoundtaskarg0 launchsoundtaskarg1 launchsoundtaskarg2 launchsoundtaskarg3 launchsoundtaskarg4 launchsoundtaskarg5 launchsoundtaskarg6 launchsoundtaskarg7 launchsoundtaskarg8
.byte 0x1F
.word \launchsoundtaskPtr
.byte \launchsoundtaskArgsNo
.hword \launchsoundtaskarg0
.hword \launchsoundtaskarg1
.hword \launchsoundtaskarg2
.hword \launchsoundtaskarg3
.hword \launchsoundtaskarg4
.hword \launchsoundtaskarg5
.hword \launchsoundtaskarg6
.hword \launchsoundtaskarg7
.hword \launchsoundtaskarg8
.endm

View File

@ -1785,6 +1785,10 @@
various \battler, VARIOUS_TRY_ACTIVATE_GRIM_NEIGH
.endm
.macro setzeffect
various BS_ATTACKER, VARIOUS_SET_Z_EFFECT
.endm
.macro consumeberry battler:req, restoreItem=FALSE
various \battler, VARIOUS_CONSUME_BERRY
.byte \restoreItem
@ -1924,8 +1928,8 @@
.4byte \ptr
.endm
.macro photongeysercheck
various BS_ATTACKER, VARIOUS_PHOTON_GEYSER_CHECK
.macro photongeysercheck battler:req
various \battler, VARIOUS_PHOTON_GEYSER_CHECK
.endm
.macro shellsidearmcheck

File diff suppressed because it is too large Load Diff

View File

@ -411,6 +411,8 @@ gBattleScriptsForMoveEffects::
.4byte BattleScript_EffectHit @ EFFECT_BEAK_BLAST
.4byte BattleScript_EffectCourtChange @ EFFECT_COURT_CHANGE
.4byte BattleScript_EffectSteelBeam @ EFFECT_STEEL_BEAM
.4byte BattleScript_EffectExtremeEvoboost @ EFFECT_EXTREME_EVOBOOST
.4byte BattleScript_EffectTerrainHit @ EFFECT_DAMAGE_SET_TERRAIN
BattleScript_EffectSteelBeam::
attackcanceler
@ -720,7 +722,7 @@ BattleScript_EffectPhotonGeyser:
critcalc
damagecalc
adjustdamage
photongeysercheck
photongeysercheck BS_ATTACKER
attackanimation
waitanimation
effectivenesssound
@ -2152,9 +2154,7 @@ BattleScript_GrowthDoMoveAnim::
waitanimation
setbyte sSTAT_ANIM_PLAYED, FALSE
playstatchangeanimation BS_ATTACKER, BIT_ATK | BIT_SPATK, 0
.if B_GROWTH_UNDER_SUN >= GEN_5
jumpifweatheraffected BS_ATTACKER, B_WEATHER_SUN, BattleScript_GrowthAtk2
.endif
setstatchanger STAT_ATK, 1, FALSE
goto BattleScript_GrowthAtk
BattleScript_GrowthAtk2:
@ -2165,9 +2165,7 @@ BattleScript_GrowthAtk:
printfromtable gStatUpStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_GrowthTrySpAtk::
.if B_GROWTH_UNDER_SUN >= GEN_5
jumpifweatheraffected BS_ATTACKER, B_WEATHER_SUN, BattleScript_GrowthSpAtk2
.endif
setstatchanger STAT_SPATK, 1, FALSE
goto BattleScript_GrowthSpAtk
BattleScript_GrowthSpAtk2:
@ -5542,6 +5540,7 @@ BattleScript_EffectCharge::
setcharge
attackanimation
waitanimation
.if B_CHARGE_SPDEF_RAISE >= GEN_5
setstatchanger STAT_SPDEF, 1, FALSE
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_EffectChargeString
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectChargeString
@ -5550,6 +5549,7 @@ BattleScript_EffectCharge::
printfromtable gStatUpStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_EffectChargeString:
.endif
printstring STRINGID_PKMNCHARGINGPOWER
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
@ -9514,6 +9514,124 @@ BattleScript_JabocaRowapBerryActivate_Dmg:
removeitem BS_TARGET
return
@ z moves / effects
BattleScript_ZMoveActivateDamaging::
printstring STRINGID_ZPOWERSURROUNDS
playanimation BS_ATTACKER, B_ANIM_ZMOVE_ACTIVATE, NULL
printstring STRINGID_ZMOVEUNLEASHED
waitmessage 0x40
return
BattleScript_ZMoveActivateStatus::
savetarget
printstring STRINGID_ZPOWERSURROUNDS
playanimation BS_ATTACKER, B_ANIM_ZMOVE_ACTIVATE, NULL
setzeffect
restoretarget
copybyte sSTATCHANGER, sSAVED_STAT_CHANGER
return
BattleScript_ZEffectPrintString::
printfromtable gZEffectStringIds
waitmessage 0x40
return
BattleScript_RecoverHPZMove::
healthbarupdate BS_SCRIPTING
datahpupdate BS_SCRIPTING
printfromtable gZEffectStringIds
waitmessage 0x40
return
BattleScript_StatUpZMove::
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_StatUpZMoveEnd
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_StatUpZMoveEnd
setgraphicalstatchangevalues
playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
printstring STRINGID_ZMOVESTATUP
waitmessage 0x40
printfromtable gStatUpStringIds
waitmessage 0x40
BattleScript_StatUpZMoveEnd:
return
BattleScript_HealReplacementZMove::
playanimation BS_SCRIPTING B_ANIM_WISH_HEAL 0x0
printfromtable gZEffectStringIds
waitmessage 0x40
healthbarupdate BS_SCRIPTING
datahpupdate BS_SCRIPTING
return
BattleScript_EffectExtremeEvoboost::
attackcanceler
attackstring
ppreduce
jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_ExtremeEvoboostAnim
jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_DEF, MAX_STAT_STAGE, BattleScript_ExtremeEvoboostAnim
jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPEED, MAX_STAT_STAGE, BattleScript_ExtremeEvoboostAnim
jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_ExtremeEvoboostAnim
jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPDEF, MAX_STAT_STAGE, BattleScript_ExtremeEvoboostAnim
goto BattleScript_ButItFailed
BattleScript_ExtremeEvoboostAnim:
attackanimation
waitanimation
BattleScript_ExtremeEvoboostAtk::
setbyte sSTAT_ANIM_PLAYED, FALSE
playstatchangeanimation BS_ATTACKER, BIT_ATK | BIT_DEF | BIT_SPEED | BIT_SPATK | BIT_SPDEF, 0x0
setstatchanger STAT_ATK, 2, FALSE
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_ExtremeEvoboostDef
printfromtable gStatUpStringIds
waitmessage 0x40
BattleScript_ExtremeEvoboostDef::
setstatchanger STAT_DEF, 2, FALSE
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_ExtremeEvoboostSpeed
printfromtable gStatUpStringIds
waitmessage 0x40
BattleScript_ExtremeEvoboostSpeed::
setstatchanger STAT_SPEED, 2, FALSE
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_ExtremeEvoboostSpAtk
printfromtable gStatUpStringIds
waitmessage 0x40
BattleScript_ExtremeEvoboostSpAtk::
setstatchanger STAT_SPATK, 2, FALSE
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_ExtremeEvoboostSpDef
printfromtable gStatUpStringIds
waitmessage 0x40
BattleScript_ExtremeEvoboostSpDef::
setstatchanger STAT_SPDEF, 2, FALSE
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_ExtremeEvoboostEnd
printfromtable gStatUpStringIds
waitmessage 0x40
BattleScript_ExtremeEvoboostEnd::
goto BattleScript_MoveEnd
BattleScript_EffectTerrainHit:
attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
ppreduce
critcalc
damagecalc
adjustdamage
attackanimation
waitanimation
effectivenesssound
hitanimation BS_TARGET
waitstate
healthbarupdate BS_TARGET
datahpupdate BS_TARGET
critmessage
waitmessage 0x40
resultmessage
waitmessage 0x40
setterrain BattleScript_TryFaint
playanimation BS_ATTACKER, B_ANIM_RESTORE_BG
printfromtable gTerrainStringIds
BattleScript_TryFaint:
tryfaintmon BS_TARGET
goto BattleScript_MoveEnd
BattleScript_Pickpocket::
call BattleScript_AbilityPopUp
jumpifability BS_ATTACKER, ABILITY_STICKY_HOLD, BattleScript_PickpocketPrevented

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 B

View File

@ -467,6 +467,25 @@ struct Illusion
struct Pokemon *mon;
};
struct ZMoveData
{
u8 viable:1; // current move can become a z move
u8 viewing:1; // if player is viewing the z move name instead of regular moves
u8 active:1; // is z move being used this turn
u8 zStatusActive:1;
u8 healReplacement:1;
u8 activeSplit:2; // active z move split
u8 zUnused:1;
u8 triggerSpriteId;
u8 possibleZMoves[MAX_BATTLERS_COUNT];
u16 chosenZMove; // z move of move cursor is on
u8 effect;
u8 used[MAX_BATTLERS_COUNT]; //one per bank for multi-battles
u16 toBeUsed[MAX_BATTLERS_COUNT]; // z moves per battler to be used
u16 baseMoves[MAX_BATTLERS_COUNT];
u8 splits[MAX_BATTLERS_COUNT];
};
struct StolenItem
{
u16 originalItem:15;
@ -571,6 +590,7 @@ struct BattleStruct
u8 abilityPopUpSpriteIds[MAX_BATTLERS_COUNT][2]; // two per battler
bool8 throwingPokeBall;
struct MegaEvolutionData mega;
struct ZMoveData zmove;
const u8 *trainerSlideMsg;
bool8 trainerSlideLowHpMsgDone;
u8 introState;
@ -595,6 +615,7 @@ struct BattleStruct
u8 quickClawBattlerId;
struct StolenItem itemStolen[PARTY_SIZE]; // Player's team that had items stolen (two bytes per party member)
u8 blunderPolicy:1; // should blunder policy activate
u8 swapDamageCategory:1; // Photon Geyser, Shell Side Arm, Light That Burns the Sky
u8 ballSpriteIds[2]; // item gfx, window gfx
u8 stickyWebUser;
u8 appearedInBattle; // Bitfield to track which Pokemon appeared in battle. Used for Burmy's form change
@ -811,7 +832,7 @@ extern u16 gBattle_WIN1V;
extern u8 gDisplayedStringBattle[400];
extern u8 gBattleTextBuff1[TEXT_BUFF_ARRAY_COUNT];
extern u8 gBattleTextBuff2[TEXT_BUFF_ARRAY_COUNT];
extern u8 gBattleTextBuff3[TEXT_BUFF_ARRAY_COUNT];
extern u8 gBattleTextBuff3[30]; //to handle stupidly large z move names
extern u32 gBattleTypeFlags;
extern u8 gBattleTerrain;
extern u32 gUnusedFirstBattleVar1;
@ -918,7 +939,6 @@ extern u8 gBattleControllerData[MAX_BATTLERS_COUNT];
extern bool8 gHasFetchedBall;
extern u8 gLastUsedBall;
extern u16 gLastThrownBall;
extern bool8 gSwapDamageCategory; // Photon Geyser, Shell Side Arm, Light That Burns the Sky
extern u8 gPartyCriticalHits[PARTY_SIZE];
#endif // GUARD_BATTLE_H

View File

@ -62,6 +62,7 @@ s8 GetAbilityRating(u16 ability);
bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability);
bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u16 move);
u32 AI_GetBattlerMoveTargetType(u8 battlerId, u16 move);
bool32 ShouldUseZMove(u8 activeId, u8 targetId, u16 chosenMove);
// stat stage checks
bool32 AnyStatIsRaised(u8 battlerId);
@ -82,7 +83,7 @@ bool32 ShouldLowerEvasion(u8 battlerAtk, u8 battlerDef, u16 defAbility);
// move checks
bool32 IsAffectedByPowder(u8 battler, u16 ability, u16 holdEffect);
bool32 MovesWithSplitUnusable(u32 attacker, u32 target, u32 split);
s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 *effectiveness);
s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 *effectiveness, bool32 considerZPower);
u8 GetMoveDamageResult(u16 move);
u32 GetCurrDamageHpPercent(u8 battlerAtk, u8 battlerDef);
u16 AI_GetTypeEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef);

View File

@ -205,12 +205,14 @@ u8 GetSubstituteSpriteDefault_Y(u8 battlerId);
#define STAT_ANIM_MULTIPLE_MINUS1 57
#define STAT_ANIM_MULTIPLE_MINUS2 58
void LaunchStatusAnimation(u8 battlerId, u8 statusAnimId);
extern const union AnimCmd *const sAnims_SpinningSparkle[];
// battle_anim_ground.c
void AnimTask_HorizontalShake(u8 taskId);
void AnimMudSportDirt(struct Sprite *sprite);
void AnimDirtScatter(struct Sprite *sprite);
void AnimMudSportDirtRising(struct Sprite *sprite);
void AnimDirtPlumeParticle(struct Sprite *);
extern const union AffineAnimCmd *const gAffineAnims_SpinningBone[];
// battle_anim_throw.c
@ -272,6 +274,7 @@ extern const union AnimCmd *const gScratchAnimTable[];
extern const union AnimCmd *const gIngrainRootAnimTable[];
extern const union AffineAnimCmd *const gSwiftStarAffineAnimTable[];
extern const union AnimCmd *const gMetronomeThroughtBubbleAnimTable[];
extern const union AffineAnimCmd *const gStockpileAbsorptionOrbAffineAnimTable[];
// battle_anim_effects_2.c
void AnimUproarRing(struct Sprite *sprite);
@ -280,6 +283,7 @@ void AnimOrbitFast(struct Sprite *sprite);
void AnimOrbitScatter(struct Sprite *sprite);
void AnimAngerMark(struct Sprite *sprite);
void AnimHyperVoiceRing(struct Sprite *sprite);
void AnimMagentaHeart(struct Sprite *);
extern const union AffineAnimCmd *const gThinRingShrinkingAffineAnimTable[];
extern const union AffineAnimCmd *const gThinRingExpandingAffineAnimTable[];
extern const union AnimCmd *const gExplosionAnimTable[];
@ -295,8 +299,13 @@ void AnimBlackSmoke(struct Sprite *sprite);
void AnimSweetScentPetal(struct Sprite *sprite);
void AnimTealAlert(struct Sprite *sprite);
void AnimBlockX(struct Sprite *sprite);
void AnimFlatterSpotlight_Step(struct Sprite *);
void AnimAssistPawprint(struct Sprite *);
void AnimReversalOrb(struct Sprite *);
void AnimFlatterSpotlight_Step(struct Sprite *sprite);
extern const union AnimCmd *const gOpeningEyeAnimTable[];
extern const union AnimCmd *const gEclipsingOrbAnimTable[];
extern const union AffineAnimCmd *const gSpotlightAffineAnimTable[];
// battle_anim_water.c
void AnimWaterPulseRing(struct Sprite *sprite);
@ -314,16 +323,21 @@ void AnimFlyBallUp(struct Sprite *sprite);
void AnimFlyBallAttack(struct Sprite *sprite);
void AnimFlyBallAttack_Step(struct Sprite *sprite);
void AnimFlyBallUp_Step(struct Sprite *sprite);
void AnimBounceBallLand(struct Sprite *);
void AnimEllipticalGust(struct Sprite *);
extern const union AnimCmd *const gAffineAnims_AirWaveCrescent[];
extern const union AffineAnimCmd *const gAffineAnims_FlyBallUp[];
extern const union AffineAnimCmd *const gAffineAnims_FlyBallAttack[];
extern const union AffineAnimCmd *const gAffineAnims_BounceBallLand[];
// battle_anim_poison.c
void AnimSludgeBombHitParticle(struct Sprite *);
void AnimAcidPoisonBubble_Step(struct Sprite *sprite);
void AnimBubbleEffect(struct Sprite *);
extern const union AffineAnimCmd *const gAffineAnims_PoisonProjectile[];
extern const union AnimCmd *const gAnims_PoisonProjectile[];
extern const union AnimCmd *const gAnims_AcidPoisonDroplet[];
extern const union AffineAnimCmd *const gAffineAnims_Bubble[];
// battle_anim_ghost.c
void AnimGhostStatusSprite(struct Sprite *sprite);
@ -419,6 +433,7 @@ void AnimSparkElectricity(struct Sprite *sprite);
void AnimElectricPuff(struct Sprite *sprite);
void AnimSparkElectricityFlashing(struct Sprite *sprite);
void AnimGrowingShockWaveOrb(struct Sprite *sprite);
void AnimElectricity(struct Sprite *);
extern const union AffineAnimCmd *const gAffineAnims_GrowingElectricOrb[];
extern const union AffineAnimCmd *const gAffineAnims_FlashingSpark[];
extern const union AnimCmd *const gAnims_ThunderboltOrb[];
@ -434,6 +449,7 @@ void AnimBasicFistOrFoot(struct Sprite *sprite);
void AnimSpinningKickOrPunchFinish(struct Sprite *sprite);
void AnimRevengeScratch(struct Sprite *sprite);
void AnimDizzyPunchDuck(struct Sprite *sprite);
void AnimSuperpowerFireball(struct Sprite *);
extern const union AnimCmd *const gAnims_HandsAndFeet[];
extern const union AffineAnimCmd *const gAffineAnims_MegaPunchKick[];
extern const union AffineAnimCmd *const gAffineAnims_SpinningHandOrFoot[];
@ -443,6 +459,7 @@ extern const union AnimCmd *const gAnims_RevengeBigScratch[];
extern const union AnimCmd *const gAnims_FlyingRock[];
extern const union AffineAnimCmd *const gAffineAnims_Whirlpool[];
extern const union AffineAnimCmd *const gAffineAnims_BasicRock[];
extern const union AnimCmd *const gAnims_FlyingRock[];
void AnimParticleInVortex(struct Sprite *sprite);
void AnimFallingRock(struct Sprite *sprite);
void AnimRaiseSprite(struct Sprite *sprite);
@ -477,7 +494,13 @@ extern const union AnimCmd *const gAnims_BlizzardIceCrystal[];
// battle_anim_fire.c
void AnimFireSpread(struct Sprite *sprite);
void AnimFireSpiralOutward(struct Sprite *sprite);
void AnimWillOWispOrb(struct Sprite *);
void AnimEruptionFallingRock(struct Sprite *);
void AnimFireCross(struct Sprite *);
void AnimFirePlume(struct Sprite *);
extern const union AnimCmd *const gAnims_FireBlastCross[];
extern const union AnimCmd *const gAnims_WillOWispOrb[];
extern const union AnimCmd *const gAnims_FirePlume[];
// battle_anim_dragon.c
extern const union AnimCmd *const gAnims_DragonBreathFire[];

View File

@ -129,6 +129,7 @@ struct ChooseMoveStruct
u8 monType2;
u8 monType3;
struct MegaEvolutionData mega;
struct ZMoveData zmove;
};
enum
@ -276,6 +277,8 @@ void Task_PlayerController_RestoreBgmAfterCry(u8 taskId);
void ActionSelectionCreateCursorAt(u8 cursorPos, u8 unused);
void ActionSelectionDestroyCursorAt(u8 cursorPos);
void InitMoveSelectionsVarsAndStrings(void);
void MoveSelectionCreateCursorAt(u8 cursorPos, u8 arg1);
void MoveSelectionDestroyCursorAt(u8 cursorPosition);
// recorded player controller
void SetControllerToRecordedPlayer(void);

View File

@ -43,6 +43,7 @@ enum
#define TAG_MEGA_INDICATOR_TILE 0xD778
#define TAG_ALPHA_INDICATOR_TILE 0xD779
#define TAG_OMEGA_INDICATOR_TILE 0xD77A
#define TAG_ZMOVE_TRIGGER_TILE 0xD77B
#define TAG_HEALTHBOX_PAL 0xD6FF
#define TAG_HEALTHBAR_PAL 0xD704
@ -53,6 +54,7 @@ enum
#define TAG_MEGA_INDICATOR_PAL 0xD778
#define TAG_ALPHA_INDICATOR_PAL 0xD779
#define TAG_OMEGA_INDICATOR_PAL 0xD77A
#define TAG_ZMOVE_TRIGGER_PAL 0xD77B
enum
{
@ -97,6 +99,7 @@ u8 GetScaledHPFraction(s16 hp, s16 maxhp, u8 scale);
u8 GetHPBarLevel(s16 hp, s16 maxhp);
void CreateAbilityPopUp(u8 battlerId, u32 ability, bool32 isDoubleBattle);
void DestroyAbilityPopUp(u8 battlerId);
void HideTriggerSprites(void);
bool32 CanThrowLastUsedBall(void);
void TryHideLastUsedBall(void);
void TryRestoreLastUsedBall(void);

View File

@ -240,6 +240,7 @@ void BattlePutTextOnWindow(const u8* text, u8 windowId);
void SetPpNumbersPaletteInMoveSelection(void);
u8 GetCurrentPpToMaxPpState(u8 currentPp, u8 maxPp);
bool32 ShouldDoTrainerSlide(u32 battlerId, u32 trainerId, u32 which);
void ExpandBattleTextBuffPlaceholders(const u8 *src, u8 *dst);
extern struct BattleMsgData *gBattleMsgDataPtr;

View File

@ -421,4 +421,13 @@ extern const u8 BattleScript_BeakBlastSetUp[];
extern const u8 BattleScript_BeakBlastBurn[];
extern const u8 BattleScript_DefDownSpeedUp[];
// zmoves
extern const u8 BattleScript_ZMoveActivateDamaging[];
extern const u8 BattleScript_ZMoveActivateStatus[];
extern const u8 BattleScript_ZEffectPrintString[];
extern const u8 BattleScript_RecoverHPZMove[];
extern const u8 BattleScript_StatUpZMove[];
extern const u8 BattleScript_HealReplacementZMove[];
extern const u8 BattleScript_EffectExtremeEvoboost[];
#endif // GUARD_BATTLE_SCRIPTS_H

View File

@ -153,6 +153,8 @@ bool32 CanFling(u8 battlerId);
bool32 IsTelekinesisBannedSpecies(u16 species);
bool32 IsHealBlockPreventingMove(u32 battler, u32 move);
bool32 HasEnoughHpToEatBerry(u32 battlerId, u32 hpFraction, u32 itemId);
bool32 IsPartnerMonFromSameTrainer(u8 battlerId);
u8 GetSplitBasedOnStats(u8 battlerId);
void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast);
bool32 TestSheerForceFlag(u8 battler, u16 move);
void TryRestoreStolenItems(void);

30
include/battle_z_move.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef GUARD_BATTLE_Z_MOVE_H
#define GUARD_BATTLE_Z_MOVE_H
#include "constants/z_move_effects.h"
#define MOVE_Z_STATUS 0xFFFF
struct SignatureZMove
{
u16 species;
u16 item;
u16 move;
u16 zmove;
};
bool8 IsZMove(u16 move);
void QueueZMove(u8 battlerId, u16 baseMove);
bool32 IsViableZMove(u8 battlerId, u16 move);
bool32 TryChangeZIndicator(u8 battlerId, u8 moveIndex);
void CreateZMoveTriggerSprite(u8, bool8);
void HideZMoveTriggerSprite(void);
bool32 IsZMoveTriggerSpriteActive(void);
void DestroyZMoveTriggerSprite(void);
bool32 MoveSelectionDisplayZMove(u16 zmove);
const u8* GetZMoveName(u16 move);
void SetZEffect(void);
bool32 IsZMoveUsable(u8 battlerId, u16 moveIndex);
void GetUsableZMoves(u8 battlerId, u16 *moves);
#endif // GUARD_BATTLE_Z_MOVE_H

View File

@ -535,6 +535,7 @@
#define B_ANIM_AQUA_RING_HEAL 32
#define B_ANIM_BEAK_BLAST_SETUP 33
#define B_ANIM_SHELL_TRAP_SETUP 34
#define B_ANIM_ZMOVE_ACTIVATE 35 // Using Z Moves
// special animations table (gBattleAnims_Special)
#define B_ANIM_LVL_UP 0
@ -601,6 +602,12 @@
#define ANIM_RIGHT_FIST 0
#define ANIM_LEFT_FIST 2
// fist/chop frames
#define ANIM_FIST_1 0
#define ANIM_FOOT_1 1
#define ANIM_FOOT_2 2
#define ANIM_CHOP 3
// surf wave palettes
#define ANIM_SURF_PAL_SURF 0
#define ANIM_SURF_PAL_MUDDY_WATER 1

View File

@ -87,6 +87,41 @@
#define ITEM_RINDO_BERRY 207
#define ITEM_YACHE_BERRY 208
#define ITEM_GRISEOUS_ORB 369
// z crystals
#define ITEM_NORMALIUM_Z 568
#define ITEM_FIGHTINIUM_Z 569
#define ITEM_FLYINIUM_Z 570
#define ITEM_POISONIUM_Z 571
#define ITEM_GROUNDIUM_Z 572
#define ITEM_ROCKIUM_Z 573
#define ITEM_BUGINIUM_Z 574
#define ITEM_GHOSTIUM_Z 575
#define ITEM_STEELIUM_Z 576
#define ITEM_FIRIUM_Z 577
#define ITEM_WATERIUM_Z 578
#define ITEM_GRASSIUM_Z 579
#define ITEM_ELECTRIUM_Z 580
#define ITEM_PSYCHIUM_Z 581
#define ITEM_ICIUM_Z 582
#define ITEM_DRAGONIUM_Z 583
#define ITEM_DARKINIUM_Z 584
#define ITEM_FAIRIUM_Z 585
#define ITEM_ALORAICHIUM_Z 586
#define ITEM_DECIDIUM_Z 587
#define ITEM_EEVIUM_Z 588
#define ITEM_INCINIUM_Z 589
#define ITEM_KOMMONIUM_Z 590
#define ITEM_LUNALIUM_Z 591
#define ITEM_LYCANIUM_Z 592
#define ITEM_MARSHADIUM_Z 593
#define ITEM_MEWNIUM_Z 594
#define ITEM_MIMIKIUM_Z 595
#define ITEM_PIKANIUM_Z 596
#define ITEM_PIKASHUNIUM_Z 597
#define ITEM_PRIMARIUM_Z 598
#define ITEM_SNORLIUM_Z 599
#define ITEM_SOLGANIUM_Z 600
#define ITEM_TAPUNIUM_Z 601
#endif
#ifndef GEN_3
@ -125,6 +160,7 @@
#define B_ROUGH_SKIN_DMG GEN_7 // In Gen4+, Rough Skin contact damage is 1/8th of max HP instead of 1/16th. This will also affect Iron Barbs.
#define B_KNOCK_OFF_DMG GEN_8 // In Gen6+, Knock Off deals 50% more damage when knocking off an item.
#define B_SPORT_DMG_REDUCTION GEN_7 // In Gen5+, Water/Mud Sport reduce Fire/Electric Damage by 67% instead of 50%.
#define B_EXPLOSION_DEFENSE GEN_7 // In Gen5+, Self-Destruct and Explosion don't halve the targets' defense.
// Type settings
#define B_GHOSTS_ESCAPE GEN_7 // In Gen6+, abilities like Shadow Tag or moves like Mean Look fail on Ghost-type Pokémon. They can also escape any Wild Battle.
@ -148,14 +184,10 @@
// Move data settings
#define B_UPDATED_MOVE_DATA GEN_8 // Updates move data in gBattleMoves, including Power, Accuracy, PP, stat changes, targets, chances of secondary effects, etc.
#define B_PHYSICAL_SPECIAL_SPLIT GEN_7 // In Gen3, the move's type determines if it will do physical or special damage. The split icon in the summary will reflect this.
#define B_FELL_STINGER_STAT_RAISE GEN_7 // In Gen7+, it raises Atk by 3 stages instead of 2 if it causes the target to faint.
#define B_KINGS_SHIELD_LOWER_ATK GEN_7 // In Gen7+, it lowers Atk by 1 stage instead of 2 of oponents that hit it.
#define B_SPEED_BUFFING_RAPID_SPIN GEN_8 // In Gen8, Rapid Spin raises the user's Speed by 1 stage.
#define B_RECOIL_IF_MISS_DMG GEN_7 // In Gen5+, Jump Kick and High Jump Kick will always do half of the user's max HP when missing.
#define B_KLUTZ_FLING_INTERACTION GEN_7 // In Gen5+, Pokémon with the Klutz ability can't use Fling.
#define B_UPDATED_CONVERSION GEN_7 // In Gen6+, Conversion changes the user's type to match their first move's. Before, it would choose a move at random.
#define B_PP_REDUCED_BY_SPITE GEN_7 // In Gen4+, Spite reduces the foe's last move's PP by 4, instead of 2 to 5.
#define B_MINIMIZE_EVASION GEN_7 // In Gen5+, Minimize raises evasion by 2 stages instead of 1.
// Move accuracy settings
#define B_TOXIC_NEVER_MISS GEN_7 // In Gen6+, if Toxic is used by a Poison-type Pokémon, it will never miss.
@ -163,6 +195,14 @@
#define B_BLIZZARD_HAIL GEN_7 // In Gen4+, Blizzard bypasses accuracy checks if it's hailing.
#define B_SHEER_COLD_ACC GEN_7 // In Gen7+, Sheer Cold's base chance of hitting is reduced to 20% if the user isn't Ice-typed.
// Move stat change settings
#define B_FELL_STINGER_STAT_RAISE GEN_7 // In Gen7+, it raises Atk by 3 stages instead of 2 if it causes the target to faint.
#define B_KINGS_SHIELD_LOWER_ATK GEN_7 // In Gen7+, it lowers Atk by 1 stage instead of 2 of oponents that hit it.
#define B_SPEED_BUFFING_RAPID_SPIN GEN_8 // In Gen8, Rapid Spin raises the user's Speed by 1 stage.
#define B_CHARGE_SPDEF_RAISE GEN_7 // In Gen5+, Charge raises the user's Special Defense by 1 stage.
#define B_MINIMIZE_EVASION GEN_7 // In Gen5+, Minimize raises evasion by 2 stages instead of 1.
#define B_GROWTH_STAT_RAISE GEN_7 // In Gen5+, Growth raises Attack in addition to Special Attack by 1 stage each. Under the effects of the sun, it raises them by 2 stages each instead.
// Other move settings
#define B_SOUND_SUBSTITUTE GEN_7 // In Gen6+, sound moves bypass Substitute.
#define B_INCINERATE_GEMS GEN_7 // In Gen6+, Incinerate can destroy Gems.
@ -177,7 +217,6 @@
#define B_HEAL_BLOCKING GEN_7 // In Gen5+, Heal Block prevents healing by Black Sludge, Leftovers, Shell Bell. Affected Pokémon will not consume held HP-restoring Berries or Berry Juice.
// Draining abilities will not heal but will prevent damage. In Gen6+, Heal Block prevents the use of most HP-draining moves.
#define B_ROOTED_GROUNDING GEN_7 // In Gen4+, Ingrain causes the affected Pokémon to become grounded.
#define B_GROWTH_UNDER_SUN GEN_7 // In Gen5+, Growth's effects are doubled when under the effects of the sun.
// Ability settings
#define B_EXPANDED_ABILITY_NAMES TRUE // If TRUE, ability names are increased from 12 characters to 16 characters.
@ -191,6 +230,7 @@
#define B_SYNCHRONIZE_TOXIC GEN_8 // In Gen5+, if a Pokémon with Synchronize is badly poisoned, the opponent will also become badly poisoned. Previously, the opponent would become regular poisoned.
#define B_UPDATED_INTIMIDATE GEN_8 // In Gen8, Intimidate doesn't work on opponents with the Inner Focus, Scrappy, Own Tempo or Oblivious abilities. It also activates Rattled.
#define B_OBLIVIOUS_TAUNT GEN_7 // In Gen6+, Pokémon with Oblivious can't be taunted.
#define B_STURDY GEN_7 // In Gen5+, Sturdy causes the Pokémon to have 1 HP remaining if another Pokémon's attack or confusion damage would have brought it from full health to 0 HP.
#define B_PLUS_MINUS_INTERACTION GEN_7 // In Gen5+, Plus and Minus can be activated with themselves and the opposite ability. Before, only the opposing ability could activate it.
// Item settings

View File

@ -394,7 +394,9 @@
#define EFFECT_BEAK_BLAST 388
#define EFFECT_COURT_CHANGE 389
#define EFFECT_STEEL_BEAM 390
#define EFFECT_EXTREME_EVOBOOST 391
#define EFFECT_DAMAGE_SET_TERRAIN 392 // genesis supernova
#define NUM_BATTLE_MOVE_EFFECTS 391
#define NUM_BATTLE_MOVE_EFFECTS 393
#endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H

View File

@ -241,6 +241,7 @@
#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 150
#define VARIOUS_SET_BEAK_BLAST 151
#define VARIOUS_SWAP_SIDE_STATUSES 152
#define VARIOUS_SET_Z_EFFECT 153
// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0

View File

@ -615,8 +615,17 @@
#define STRINGID_COURTCHANGE 613
#define STRINGID_PLAYERLOSTTOENEMYTRAINER 614
#define STRINGID_PLAYERPAIDPRIZEMONEY 615
#define STRINGID_ZPOWERSURROUNDS 616
#define STRINGID_ZMOVEUNLEASHED 617
#define STRINGID_ZMOVERESETSSTATS 618
#define STRINGID_ZMOVEALLSTATSUP 619
#define STRINGID_ZMOVEZBOOSTCRIT 620
#define STRINGID_ZMOVERESTOREHP 621
#define STRINGID_ZMOVESTATUP 622
#define STRINGID_ZMOVEHPTRAP 623
#define STRINGID_TERRAINREMOVED 624
#define BATTLESTRINGS_COUNT 616
#define BATTLESTRINGS_COUNT 625
// This is the string id that gBattleStringsTable starts with.
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,
@ -886,4 +895,13 @@
#define B_MSG_WRAPPED_SNAP_TRAP 8
#define TRAPPING_MOVES_COUNT 9
// z effects
#define B_MSG_Z_RESET_STATS 0
#define B_MSG_Z_ALL_STATS_UP 1
#define B_MSG_Z_BOOST_CRITS 2
#define B_MSG_Z_FOLLOW_ME 3
#define B_MSG_Z_RECOVER_HP 4
#define B_MSG_Z_STAT_UP 5
#define B_MSG_Z_HP_TRAP 6
#endif // GUARD_CONSTANTS_BATTLE_STRING_IDS_H

View File

@ -784,6 +784,49 @@
#define MOVES_COUNT_GEN8 755
#define MOVES_COUNT MOVES_COUNT_GEN8
#define MOVES_COUNT MOVES_COUNT_GEN8
// Z Moves
#define MOVE_BREAKNECK_BLITZ (MOVES_COUNT + 0)
#define MOVE_ALL_OUT_PUMMELING (MOVES_COUNT + 1)
#define MOVE_SUPERSONIC_SKYSTRIKE (MOVES_COUNT + 2)
#define MOVE_ACID_DOWNPOUR (MOVES_COUNT + 3)
#define MOVE_TECTONIC_RAGE (MOVES_COUNT + 4)
#define MOVE_CONTINENTAL_CRUSH (MOVES_COUNT + 5)
#define MOVE_SAVAGE_SPIN_OUT (MOVES_COUNT + 6)
#define MOVE_NEVER_ENDING_NIGHTMARE (MOVES_COUNT + 7)
#define MOVE_CORKSCREW_CRASH (MOVES_COUNT + 8)
#define MOVE_INFERNO_OVERDRIVE (MOVES_COUNT + 9)
#define MOVE_HYDRO_VORTEX (MOVES_COUNT + 10)
#define MOVE_BLOOM_DOOM (MOVES_COUNT + 11)
#define MOVE_GIGAVOLT_HAVOC (MOVES_COUNT + 12)
#define MOVE_SHATTERED_PSYCHE (MOVES_COUNT + 13)
#define MOVE_SUBZERO_SLAMMER (MOVES_COUNT + 14)
#define MOVE_DEVASTATING_DRAKE (MOVES_COUNT + 15)
#define MOVE_BLACK_HOLE_ECLIPSE (MOVES_COUNT + 16)
#define MOVE_TWINKLE_TACKLE (MOVES_COUNT + 17)
// Signature Z Moves
#define MOVE_CATASTROPIKA (MOVES_COUNT + 18)
#define MOVE_10000000_VOLT_THUNDERBOLT (MOVES_COUNT + 19)
#define MOVE_STOKED_SPARKSURFER (MOVES_COUNT + 20)
#define MOVE_EXTREME_EVOBOOST (MOVES_COUNT + 21)
#define MOVE_PULVERIZING_PANCAKE (MOVES_COUNT + 22)
#define MOVE_GENESIS_SUPERNOVA (MOVES_COUNT + 23)
#define MOVE_SINISTER_ARROW_RAID (MOVES_COUNT + 24)
#define MOVE_MALICIOUS_MOONSAULT (MOVES_COUNT + 25)
#define MOVE_OCEANIC_OPERETTA (MOVES_COUNT + 26)
#define MOVE_SPLINTERED_STORMSHARDS (MOVES_COUNT + 27)
#define MOVE_LETS_SNUGGLE_FOREVER (MOVES_COUNT + 28)
#define MOVE_CLANGOROUS_SOULBLAZE (MOVES_COUNT + 29)
#define MOVE_GUARDIAN_OF_ALOLA (MOVES_COUNT + 30)
#define MOVE_SEARING_SUNRAZE_SMASH (MOVES_COUNT + 31)
#define MOVE_MENACING_MOONRAZE_MAELSTROM (MOVES_COUNT + 32)
#define MOVE_LIGHT_THAT_BURNS_THE_SKY (MOVES_COUNT + 33)
#define MOVE_SOUL_STEALING_7_STAR_STRIKE (MOVES_COUNT + 34)
#define FIRST_Z_MOVE MOVE_BREAKNECK_BLITZ
#define LAST_Z_MOVE MOVE_SOUL_STEALING_7_STAR_STRIKE
#define MOVES_COUNT_Z (LAST_Z_MOVE + 1)
#endif // GUARD_CONSTANTS_MOVES_H

View File

@ -0,0 +1,38 @@
#ifndef GUARD_Z_MOVE_EFFECTS_H
#define GUARD_Z_MOVE_EFFECTS_H
#define Z_EFFECT_NONE 0
#define Z_EFFECT_RESET_STATS 1
#define Z_EFFECT_ALL_STATS_UP_1 2
#define Z_EFFECT_BOOST_CRITS 3
#define Z_EFFECT_FOLLOW_ME 4
#define Z_EFFECT_CURSE 5
#define Z_EFFECT_RECOVER_HP 6
#define Z_EFFECT_RESTORE_REPLACEMENT_HP 7
#define Z_EFFECT_ATK_UP_1 8
#define Z_EFFECT_DEF_UP_1 9
#define Z_EFFECT_SPD_UP_1 10
#define Z_EFFECT_SPATK_UP_1 11
#define Z_EFFECT_SPDEF_UP_1 12
#define Z_EFFECT_ACC_UP_1 13
#define Z_EFFECT_EVSN_UP_1 14
#define Z_EFFECT_ATK_UP_2 15
#define Z_EFFECT_DEF_UP_2 16
#define Z_EFFECT_SPD_UP_2 17
#define Z_EFFECT_SPATK_UP_2 18
#define Z_EFFECT_SPDEF_UP_2 19
#define Z_EFFECT_ACC_UP_2 20
#define Z_EFFECT_EVSN_UP_2 21
#define Z_EFFECT_ATK_UP_3 22
#define Z_EFFECT_DEF_UP_3 23
#define Z_EFFECT_SPD_UP_3 24
#define Z_EFFECT_SPATK_UP_3 25
#define Z_EFFECT_SPDEF_UP_3 26
#define Z_EFFECT_ACC_UP_3 27
#define Z_EFFECT_EVSN_UP_3 28
#endif // GUARD_Z_MOVE_EFFECTS_H

View File

@ -126,5 +126,6 @@ extern const struct Trainer gTrainers[];
extern const u8 gTrainerClassNames[][13];
extern const u8 gSpeciesNames[][POKEMON_NAME_LENGTH + 1];
extern const u8 gMoveNames[MOVES_COUNT][MOVE_NAME_LENGTH + 1];
extern const u8 *const gZMoveNames[];
#endif // GUARD_DATA_H

View File

@ -231,7 +231,7 @@ struct BaseStats
struct BattleMove
{
u16 effect;
u8 power;
u16 power; //higher than 255 for z moves
u8 type;
u8 accuracy;
u8 pp;
@ -241,6 +241,8 @@ struct BattleMove
u32 flags;
u8 split;
u8 argument;
u8 zMovePower;
u8 zMoveEffect;
};
#define SPINDA_SPOT_WIDTH 16

View File

@ -91,6 +91,7 @@ SECTIONS {
src/battle_bg.o(.text);
src/battle_main.o(.text);
src/battle_util.o(.text);
src/battle_z_move.o(.text);
src/battle_script_commands.o(.text);
src/battle_util2.o(.text);
src/battle_controller_player.o(.text);
@ -481,6 +482,7 @@ SECTIONS {
src/battle_bg.o(.rodata);
src/battle_main.o(.rodata);
src/battle_util.o(.rodata);
src/battle_z_move.o(.rodata);
src/battle_script_commands.o(.rodata);
src/battle_controller_player.o(.rodata);
src/battle_anim_smokescreen.o(.rodata);

View File

@ -6,6 +6,7 @@
#include "battle_ai_main.h"
#include "battle_factory.h"
#include "battle_setup.h"
#include "battle_z_move.h"
#include "data.h"
#include "event_data.h"
#include "item.h"
@ -255,8 +256,8 @@ void GetAiLogicData(void)
memset(AI_DATA, 0, sizeof(struct AiLogicData));
if (!(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER)
&& !IsWildMonSmart()))
if (!(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER))
&& !IsWildMonSmart())
return;
// get/assume all battler data
@ -291,7 +292,7 @@ void GetAiLogicData(void)
&& move != 0xFFFF
//&& gBattleMoves[move].power != 0 /* we want to get effectiveness of status moves */
&& !(AI_DATA->moveLimitations[battlerAtk] & gBitTable[i])) {
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness);
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, TRUE);
}
AI_DATA->simulatedDmg[battlerAtk][battlerDef][i] = dmg;
@ -985,8 +986,10 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score -= 20;
else if (!HasMoveWithType(battlerAtk, TYPE_ELECTRIC))
score -= 10;
#if B_CHARGE_SPDEF_RAISE >= GEN_5
else if (!BattlerStatCanRise(battlerAtk, AI_DATA->abilities[battlerAtk], STAT_SPDEF))
score -= 5;
#endif
break;
case EFFECT_QUIVER_DANCE:
case EFFECT_GEOMANCY:
@ -2383,9 +2386,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|| IsInstructBannedMove(instructedMove)
|| MoveRequiresRecharging(instructedMove)
|| MoveCallsOtherMove(instructedMove)
#ifdef ITEM_Z_POWER_RING
//|| (IsZMove(instructedMove))
#endif
|| IsZMove(instructedMove)
|| (gLockedMoves[battlerDef] != 0 && gLockedMoves[battlerDef] != 0xFFFF)
|| gBattleMons[battlerDef].status2 & STATUS2_MULTIPLETURNS
|| PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, AI_DATA->partnerMove))
@ -2491,15 +2492,14 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
//break;
//case EFFECT_BEAK_BLAST:
//break;
/*case EFFECT_SKY_DROP:
case EFFECT_SKY_DROP:
if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_FLYING))
score -= 10;
if (WillFaintFromWeather(battlerAtk)
|| MoveBlockedBySubstitute(move, battlerAtk, battlerDef)
|| GetSpeciesWeight(gBattleMons[battlerDef].species, AI_DATA->abilities[battlerDef], AI_DATA->holdEffects[battlerDef], battlerDef, TRUE) >= 2000) //200.0 kg
if (BattlerWillFaintFromWeather(battlerAtk, AI_DATA->abilities[battlerAtk])
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|| GetBattlerWeight(battlerDef) >= 2000) //200.0 kg
score -= 10;
break;
*/
/*case EFFECT_NO_RETREAT:
if (TrappedByNoRetreat(battlerAtk))
score -= 10;
@ -4051,8 +4051,9 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_CHARGE:
if (HasDamagingMoveOfType(battlerAtk, TYPE_ELECTRIC))
score += 2;
#if B_CHARGE_SPDEF_RAISE >= GEN_5
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPDEF, &score);
#endif
break;
case EFFECT_TAUNT:
if (IS_MOVE_STATUS(predictedMove))

View File

@ -1,4 +1,5 @@
#include "global.h"
#include "battle_z_move.h"
#include "malloc.h"
#include "battle.h"
#include "battle_anim.h"
@ -374,15 +375,9 @@ static const u16 sIgnoreMoldBreakerMoves[] =
MOVE_MOONGEIST_BEAM,
MOVE_SUNSTEEL_STRIKE,
MOVE_PHOTON_GEYSER,
#ifdef MOVE_LIGHT_THAT_BURNS_THE_SKY
MOVE_LIGHT_THAT_BURNS_THE_SKY,
#endif
#ifdef MOVE_MENACING_MOONRAZE_MAELSTROM
MOVE_MENACING_MOONRAZE_MAELSTROM,
#endif
#ifdef MOVE_SEARING_SUNRAZE_SMASH
MOVE_SEARING_SUNRAZE_SMASH,
#endif
};
static const u16 sInstructBannedMoves[] =
@ -605,7 +600,7 @@ bool32 AtMaxHp(u8 battlerId)
bool32 IsBattlerTrapped(u8 battler, bool8 checkSwitch)
{
u8 holdEffect = AI_DATA->holdEffects[battler];
if (IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)
if ((B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
|| (checkSwitch && holdEffect == HOLD_EFFECT_SHED_SHELL)
|| (!checkSwitch && GetBattlerAbility(battler) == ABILITY_RUN_AWAY)
|| (!checkSwitch && holdEffect == HOLD_EFFECT_CAN_ALWAYS_RUN))
@ -616,7 +611,7 @@ bool32 IsBattlerTrapped(u8 battler, bool8 checkSwitch)
{
if (gBattleMons[battler].status2 & (STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED)
|| IsAbilityPreventingEscape(battler)
|| gStatuses3[battler] & (STATUS3_ROOTED) // TODO: sky drop target in air
|| gStatuses3[battler] & (STATUS3_ROOTED | STATUS3_SKY_DROPPED)
|| (gFieldStatuses & STATUS_FIELD_FAIRY_LOCK))
return TRUE;
}
@ -720,12 +715,19 @@ static bool32 AI_GetIfCrit(u32 move, u8 battlerAtk, u8 battlerDef)
return isCrit;
}
s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 *typeEffectiveness)
s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 *typeEffectiveness, bool32 considerZPower)
{
s32 dmg, moveType, critDmg, normalDmg;
s8 critChance;
u16 effectivenessMultiplier;
if (considerZPower && IsViableZMove(battlerAtk, move))
{
//temporarily enable z moves for damage calcs
gBattleStruct->zmove.baseMoves[battlerAtk] = move;
gBattleStruct->zmove.active = TRUE;
}
SaveBattlerData(battlerAtk);
SaveBattlerData(battlerDef);
@ -800,6 +802,8 @@ s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 *typeEffectiveness)
// convert multiper to AI_EFFECTIVENESS_xX
*typeEffectiveness = AI_GetEffectiveness(effectivenessMultiplier);
gBattleStruct->zmove.active = FALSE;
gBattleStruct->zmove.baseMoves[battlerAtk] = MOVE_NONE;
return dmg;
}
@ -1102,7 +1106,7 @@ bool32 CanMoveFaintBattler(u16 move, u8 battlerDef, u8 battlerAtk, u8 nHits)
if (move != MOVE_NONE
&& move != 0xFFFF
&& !(unusable & gBitTable[i])
&& AI_CalcDamage(move, battlerDef, battlerAtk, &effectiveness) >= gBattleMons[battlerAtk].hp)
&& AI_CalcDamage(move, battlerDef, battlerAtk, &effectiveness, FALSE) >= gBattleMons[battlerAtk].hp)
return TRUE;
return FALSE;
@ -2053,7 +2057,9 @@ bool32 IsStatRaisingEffect(u16 effect)
case EFFECT_EVASION_UP_2:
case EFFECT_MINIMIZE:
case EFFECT_DEFENSE_CURL:
#if B_CHARGE_SPDEF_RAISE >= GEN_5
case EFFECT_CHARGE:
#endif
case EFFECT_CALM_MIND:
case EFFECT_COSMIC_POWER:
case EFFECT_DRAGON_DANCE:
@ -2457,13 +2463,13 @@ bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 mo
if (!IS_MOVE_STATUS(move) && (shouldSwitch
|| (AtMaxHp(battlerDef) && (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH
|| defAbility == ABILITY_STURDY || defAbility == ABILITY_MULTISCALE || defAbility == ABILITY_SHADOW_SHIELD))))
|| (defAbility == ABILITY_STURDY && B_STURDY >= GEN_5) || defAbility == ABILITY_MULTISCALE || defAbility == ABILITY_SHADOW_SHIELD))))
return PIVOT; // pivot to break sash/sturdy/multiscale
}
else if (!hasStatBoost)
{
if (!IS_MOVE_STATUS(move) && (AtMaxHp(battlerDef) && (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH
|| defAbility == ABILITY_STURDY || defAbility == ABILITY_MULTISCALE || defAbility == ABILITY_SHADOW_SHIELD)))
|| (defAbility == ABILITY_STURDY && B_STURDY >= GEN_5) || defAbility == ABILITY_MULTISCALE || defAbility == ABILITY_SHADOW_SHIELD)))
return PIVOT; // pivot to break sash/sturdy/multiscale
if (shouldSwitch)
@ -3219,7 +3225,7 @@ s32 AI_CalcPartyMonDamage(u16 move, u8 battlerAtk, u8 battlerDef, struct Pokemon
battleMons[i] = gBattleMons[i];
PokemonToBattleMon(mon, &gBattleMons[battlerAtk]);
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness);
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, FALSE);
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
gBattleMons[i] = battleMons[i];
@ -3599,3 +3605,37 @@ bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u16 move)
return TRUE;
return FALSE;
}
//TODO - this could use some more sophisticated logic
bool32 ShouldUseZMove(u8 battlerAtk, u8 battlerDef, u16 chosenMove)
{
// simple logic. just upgrades chosen move to z move if possible, unless regular move would kill opponent
if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && battlerDef == BATTLE_PARTNER(battlerAtk))
return FALSE; //don't use z move on partner
if (gBattleStruct->zmove.used[battlerAtk])
return FALSE; //cant use z move twice
if (IsViableZMove(battlerAtk, chosenMove))
{
u8 effectiveness;
#ifdef POKEMON_EXPANSION
if (gBattleMons[battlerDef].ability == ABILITY_DISGUISE && gBattleMons[battlerDef].species == SPECIES_MIMIKYU)
return FALSE; // Don't waste a Z-Move busting disguise
if (gBattleMons[battlerDef].ability == ABILITY_ICE_FACE && gBattleMons[battlerDef].species == SPECIES_EISCUE && IS_MOVE_PHYSICAL(chosenMove))
return FALSE; // Don't waste a Z-Move busting Ice Face
#endif
if (IS_MOVE_STATUS(chosenMove) && !IS_MOVE_STATUS(gBattleStruct->zmove.chosenZMove))
return FALSE;
else if (!IS_MOVE_STATUS(chosenMove) && IS_MOVE_STATUS(gBattleStruct->zmove.chosenZMove))
return FALSE;
if (!IS_MOVE_STATUS(chosenMove) && AI_CalcDamage(chosenMove, battlerAtk, battlerDef, &effectiveness, FALSE) >= gBattleMons[battlerDef].hp)
return FALSE; // don't waste damaging z move if can otherwise faint target
return TRUE;
}
return FALSE;
}

View File

@ -58,7 +58,6 @@ static void AnimSoftBoiledEgg_Step4(struct Sprite *);
static void AnimSoftBoiledEgg_Step4_Callback(struct Sprite *);
static void AnimSpeedDust(struct Sprite *);
static void AnimHealBellMusicNote(struct Sprite *);
static void AnimMagentaHeart(struct Sprite *);
static void AnimRedHeartProjectile(struct Sprite *);
static void AnimRedHeartProjectile_Step(struct Sprite *);
static void AnimRedHeartRising(struct Sprite *);
@ -3101,7 +3100,7 @@ static void AnimHealBellMusicNote(struct Sprite *sprite)
SetMusicNotePalette(sprite, gBattleAnimArgs[5], gBattleAnimArgs[6]);
}
static void AnimMagentaHeart(struct Sprite *sprite)
void AnimMagentaHeart(struct Sprite *sprite)
{
if (++sprite->data[0] == 1)
InitSpritePosToAnimAttacker(sprite, FALSE);

View File

@ -66,8 +66,6 @@ static void AnimPainSplitProjectile(struct Sprite *);
static void AnimFlatterConfetti(struct Sprite *);
static void AnimFlatterConfetti_Step(struct Sprite *);
static void AnimFlatterSpotlight(struct Sprite *);
static void AnimFlatterSpotlight_Step(struct Sprite *);
static void AnimReversalOrb(struct Sprite *);
static void AnimReversalOrb_Step(struct Sprite *);
static void AnimYawnCloud(struct Sprite *);
static void AnimYawnCloud_Step(struct Sprite *);
@ -76,7 +74,6 @@ static void AnimFacadeSweatDrop(struct Sprite *);
static void AnimRoarNoiseLine(struct Sprite *);
static void AnimRoarNoiseLine_Step(struct Sprite *);
static void AnimGlareEyeDot(struct Sprite *);
static void AnimAssistPawprint(struct Sprite *);
static void AnimSmellingSaltsHand(struct Sprite *);
static void AnimSmellingSaltsHand_Step(struct Sprite *);
static void AnimSmellingSaltExclamation(struct Sprite *);
@ -3200,7 +3197,7 @@ static void AnimFlatterSpotlight(struct Sprite *sprite)
sprite->callback = AnimFlatterSpotlight_Step;
}
static void AnimFlatterSpotlight_Step(struct Sprite *sprite)
void AnimFlatterSpotlight_Step(struct Sprite *sprite)
{
switch (sprite->data[1])
{
@ -3234,7 +3231,7 @@ static void AnimFlatterSpotlight_Step(struct Sprite *sprite)
// Spins an orb around the attacking mon, while its path radius grows and shrinks.
// arg 0: duration
// arg 1: initial wave offset
static void AnimReversalOrb(struct Sprite *sprite)
void AnimReversalOrb(struct Sprite *sprite)
{
sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2);
sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET);
@ -4162,7 +4159,7 @@ static void AnimGlareEyeDot(struct Sprite *sprite)
// arg 2: destination x position
// arg 3: destination y position
// arg 4: duration
static void AnimAssistPawprint(struct Sprite *sprite)
void AnimAssistPawprint(struct Sprite *sprite)
{
sprite->x = gBattleAnimArgs[0];
sprite->y = gBattleAnimArgs[1];

View File

@ -15,7 +15,6 @@ static void AnimZapCannonSpark_Step(struct Sprite *);
static void AnimThunderboltOrb(struct Sprite *);
static void AnimThunderboltOrb_Step(struct Sprite *);
static void AnimSparkElectricityFlashing_Step(struct Sprite *);
static void AnimElectricity(struct Sprite *);
static void AnimTask_ElectricBolt_Step(u8 taskId);
static void AnimElectricBoltSegment(struct Sprite *);
static void AnimThunderWave_Step(struct Sprite *);
@ -758,7 +757,7 @@ static void AnimSparkElectricityFlashing_Step(struct Sprite *sprite)
}
// Electricity arcs around the target. Used for Paralysis and various electric move hits
static void AnimElectricity(struct Sprite *sprite)
void AnimElectricity(struct Sprite *sprite)
{
if (!InitSpritePosToAnimBattler(gBattleAnimArgs[4], sprite, FALSE))
return;

View File

@ -24,7 +24,6 @@ static void AnimSuperpowerOrb_Step(struct Sprite *);
static void AnimSuperpowerRock(struct Sprite *);
static void AnimSuperpowerRock_Step1(struct Sprite *);
static void AnimSuperpowerRock_Step2(struct Sprite *);
static void AnimSuperpowerFireball(struct Sprite *);
static void AnimArmThrustHit(struct Sprite *);
static void AnimArmThrustHit_Step(struct Sprite *sprite);
static void AnimFocusPunchFist(struct Sprite *);
@ -966,7 +965,7 @@ static void AnimSuperpowerRock_Step2(struct Sprite *sprite)
DestroyAnimSprite(sprite);
}
static void AnimSuperpowerFireball(struct Sprite *sprite)
void AnimSuperpowerFireball(struct Sprite *sprite)
{
u8 battler;

View File

@ -8,7 +8,6 @@
#include "trig.h"
static void AnimFireSpiralInward(struct Sprite *);
static void AnimFirePlume(struct Sprite *);
static void AnimLargeFlame(struct Sprite *);
static void AnimLargeFlame_Step(struct Sprite *);
static void AnimUnusedSmallEmber(struct Sprite *);
@ -21,7 +20,6 @@ static void AnimFireRing_Step1(struct Sprite *);
static void AnimFireRing_Step2(struct Sprite *);
static void AnimFireRing_Step3(struct Sprite *);
static void UpdateFireRingCircleOffset(struct Sprite *);
static void AnimFireCross(struct Sprite *);
static void AnimFireSpiralOutward_Step1(struct Sprite *);
static void AnimFireSpiralOutward_Step2(struct Sprite *);
static void AnimTask_EruptionLaunchRocks_Step(u8 taskId);
@ -30,9 +28,7 @@ static void AnimEruptionLaunchRock(struct Sprite *);
static u16 GetEruptionLaunchRockInitialYPos(u8 spriteId);
static void InitEruptionLaunchRockCoordData(struct Sprite *sprite, s16 x, s16 y);
static void UpdateEruptionLaunchRockPos(struct Sprite *);
static void AnimEruptionFallingRock(struct Sprite *);
static void AnimEruptionFallingRock_Step(struct Sprite *);
static void AnimWillOWispOrb(struct Sprite *);
static void AnimWillOWispOrb_Step(struct Sprite *);
static void AnimWillOWispFire(struct Sprite *);
static void AnimTask_MoveHeatWaveTargets_Step(u8 taskId);
@ -111,7 +107,7 @@ static const union AnimCmd sAnim_FirePlume[] =
ANIMCMD_JUMP(0),
};
static const union AnimCmd *const sAnims_FirePlume[] =
const union AnimCmd *const gAnims_FirePlume[] =
{
sAnim_FirePlume,
};
@ -155,7 +151,7 @@ const struct SpriteTemplate gFirePlumeSpriteTemplate =
.tileTag = ANIM_TAG_FIRE_PLUME,
.paletteTag = ANIM_TAG_FIRE_PLUME,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = sAnims_FirePlume,
.anims = gAnims_FirePlume,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimFirePlume,
@ -167,7 +163,7 @@ static const struct SpriteTemplate sUnusedEmberFirePlumeSpriteTemplate =
.tileTag = ANIM_TAG_SMALL_EMBER,
.paletteTag = ANIM_TAG_SMALL_EMBER,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = sAnims_FirePlume,
.anims = gAnims_FirePlume,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimFirePlume,
@ -428,7 +424,7 @@ static const union AnimCmd sAnim_WillOWispOrb_3[] =
ANIMCMD_END,
};
static const union AnimCmd *const sAnims_WillOWispOrb[] =
const union AnimCmd *const gAnims_WillOWispOrb[] =
{
sAnim_WillOWispOrb_0,
sAnim_WillOWispOrb_1,
@ -441,7 +437,7 @@ const struct SpriteTemplate gWillOWispOrbSpriteTemplate =
.tileTag = ANIM_TAG_WISP_ORB,
.paletteTag = ANIM_TAG_WISP_ORB,
.oam = &gOamData_AffineOff_ObjNormal_16x16,
.anims = sAnims_WillOWispOrb,
.anims = gAnims_WillOWispOrb,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimWillOWispOrb,
@ -502,7 +498,7 @@ const struct SpriteTemplate gLavaPlumeSpriteTemplate =
.tileTag = ANIM_TAG_FIRE_PLUME,
.paletteTag = ANIM_TAG_FIRE_PLUME,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = sAnims_FirePlume,
.anims = gAnims_FirePlume,
.images = NULL,
.affineAnims = gLavaPlumeAffineAnims,
.callback = AnimLavaPlumeOrbitScatter,
@ -576,7 +572,7 @@ void AnimFireSpread(struct Sprite *sprite)
StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
}
static void AnimFirePlume(struct Sprite *sprite)
void AnimFirePlume(struct Sprite *sprite)
{
SetSpriteCoordsToAnimAttackerCoords(sprite);
@ -806,7 +802,7 @@ static void UpdateFireRingCircleOffset(struct Sprite *sprite)
// arg 3: x delta
// arg 4: y delta
// AnimFireCross(struct Sprite *sprite)
static void AnimFireCross(struct Sprite *sprite)
void AnimFireCross(struct Sprite *sprite)
{
sprite->x += gBattleAnimArgs[0];
sprite->y += gBattleAnimArgs[1];
@ -1075,7 +1071,7 @@ static void UpdateEruptionLaunchRockPos(struct Sprite *sprite)
sprite->invisible = TRUE;
}
static void AnimEruptionFallingRock(struct Sprite *sprite)
void AnimEruptionFallingRock(struct Sprite *sprite)
{
sprite->x = gBattleAnimArgs[0];
sprite->y = gBattleAnimArgs[1];
@ -1133,7 +1129,7 @@ static void AnimEruptionFallingRock_Step(struct Sprite *sprite)
}
}
static void AnimWillOWispOrb(struct Sprite *sprite)
void AnimWillOWispOrb(struct Sprite *sprite)
{
switch (sprite->data[0])
{

View File

@ -10,7 +10,6 @@
extern const struct SpriteTemplate gFlashingHitSplatSpriteTemplate;
static void AnimEllipticalGust(struct Sprite *);
static void AnimEllipticalGust_Step(struct Sprite *);
static void AnimGustToTarget(struct Sprite *);
static void AnimGustToTarget_Step(struct Sprite *);
@ -20,7 +19,6 @@ static void AnimWhirlwindLine_Step(struct Sprite *);
static void AnimUnusedBubbleThrow(struct Sprite *);
static void AnimWhirlwindLine(struct Sprite *);
static void AnimBounceBallShrink(struct Sprite *);
static void AnimBounceBallLand(struct Sprite *);
static void AnimDiveBall(struct Sprite *);
static void AnimDiveBall_Step1(struct Sprite *);
static void AnimDiveBall_Step2(struct Sprite *);
@ -246,7 +244,7 @@ static const union AffineAnimCmd sAffineAnim_BounceBallLand[] =
AFFINEANIMCMD_END,
};
static const union AffineAnimCmd *const sAffineAnims_BounceBallLand[] =
const union AffineAnimCmd *const gAffineAnims_BounceBallLand[] =
{
sAffineAnim_BounceBallLand,
};
@ -258,7 +256,7 @@ const struct SpriteTemplate gBounceBallLandSpriteTemplate =
.oam = &gOamData_AffineDouble_ObjNormal_64x64,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = sAffineAnims_BounceBallLand,
.affineAnims = gAffineAnims_BounceBallLand,
.callback = AnimBounceBallLand,
};
@ -347,7 +345,7 @@ const struct SpriteTemplate gSkyAttackBirdSpriteTemplate =
};
static void AnimEllipticalGust(struct Sprite *sprite)
void AnimEllipticalGust(struct Sprite *sprite)
{
InitSpritePosToAnimTarget(sprite, FALSE);
sprite->y += 20;
@ -980,7 +978,7 @@ static void AnimBounceBallShrink(struct Sprite *sprite)
}
}
static void AnimBounceBallLand(struct Sprite *sprite)
void AnimBounceBallLand(struct Sprite *sprite)
{
switch (sprite->data[0])
{

View File

@ -1442,3 +1442,68 @@ static void AnimPoltergeistItem(struct Sprite *sprite)
if (sprite->data[2] == 256)
DestroyAnimSprite(sprite);
}
//pulverizing pancake - destiny bond shadow from attacker to target
void AnimTask_PulverizingPancakeWhiteShadow(u8 taskId)
{
struct Task *task;
s16 battler;
u8 spriteId;
s16 baseX, baseY;
s16 x, y;
task = &gTasks[taskId];
SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL));
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0x10));
task->data[5] = 0;
task->data[6] = 0;
task->data[7] = 0;
task->data[8] = 0;
task->data[9] = 16;
task->data[10] = gBattleAnimArgs[0];
baseX = GetBattlerSpriteCoord(gBattleAnimAttacker, 2);
baseY = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_BOTTOM);
if (!IsContest())
{
spriteId = CreateSprite(&gDestinyBondWhiteShadowSpriteTemplate, baseX, baseY, 55);
if (spriteId != MAX_SPRITES)
{
x = GetBattlerSpriteCoord(gBattleAnimTarget, 2);
y = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_BOTTOM);
gSprites[spriteId].data[0] = baseX << 4;
gSprites[spriteId].data[1] = baseY << 4;
gSprites[spriteId].data[2] = ((x - baseX) << 4) / gBattleAnimArgs[1];
gSprites[spriteId].data[3] = ((y - baseY) << 4) / gBattleAnimArgs[1];
gSprites[spriteId].data[4] = gBattleAnimArgs[1];
gSprites[spriteId].data[5] = x;
gSprites[spriteId].data[6] = y;
gSprites[spriteId].callback = AnimDestinyBondWhiteShadow_Step;
task->data[task->data[12] + 13] = spriteId;
task->data[12]++;
}
}
else
{
spriteId = CreateSprite(&gDestinyBondWhiteShadowSpriteTemplate, baseX, baseY, 55);
if (spriteId != MAX_SPRITES)
{
x = 48;
y = 40;
gSprites[spriteId].data[0] = baseX << 4;
gSprites[spriteId].data[1] = baseY << 4;
gSprites[spriteId].data[2] = ((x - baseX) << 4) / gBattleAnimArgs[1];
gSprites[spriteId].data[3] = ((y - baseY) << 4) / gBattleAnimArgs[1];
gSprites[spriteId].data[4] = gBattleAnimArgs[1];
gSprites[spriteId].data[5] = x;
gSprites[spriteId].data[6] = y;
gSprites[spriteId].callback = AnimDestinyBondWhiteShadow_Step;
task->data[13] = spriteId;
task->data[12] = 1;
}
}
task->func = AnimTask_DestinyBondWhiteShadow_Step;
}

View File

@ -8,7 +8,6 @@
static void AnimBonemerangProjectile(struct Sprite *);
static void AnimBoneHitProjectile(struct Sprite *);
static void AnimDirtPlumeParticle(struct Sprite *);
static void AnimDirtPlumeParticle_Step(struct Sprite *);
static void AnimDigDirtMound(struct Sprite *);
static void AnimBonemerangProjectile_Step(struct Sprite *);

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,6 @@ static void AnimSludgeProjectile_Step(struct Sprite *);
static void AnimAcidPoisonBubble(struct Sprite *);
static void AnimSludgeBombHitParticle_Step(struct Sprite *);
static void AnimAcidPoisonDroplet(struct Sprite *);
static void AnimBubbleEffect(struct Sprite *);
static void AnimBubbleEffect_Step(struct Sprite *);
static void AnimSuckerPunchStep(struct Sprite *sprite);
static void AnimSuckerPunch(struct Sprite *sprite);
@ -161,7 +160,7 @@ static const union AffineAnimCmd sAffineAnim_Bubble[] =
AFFINEANIMCMD_END,
};
static const union AffineAnimCmd *const sAffineAnims_Bubble[] =
const union AffineAnimCmd *const gAffineAnims_Bubble[] =
{
sAffineAnim_Bubble,
};
@ -173,7 +172,7 @@ const struct SpriteTemplate gPoisonBubbleSpriteTemplate =
.oam = &gOamData_AffineNormal_ObjNormal_16x16,
.anims = gAnims_PoisonProjectile,
.images = NULL,
.affineAnims = sAffineAnims_Bubble,
.affineAnims = gAffineAnims_Bubble,
.callback = AnimBubbleEffect,
};
@ -184,7 +183,7 @@ const struct SpriteTemplate gWaterBubbleSpriteTemplate =
.oam = &gOamData_AffineNormal_ObjBlend_16x16,
.anims = gAnims_WaterBubble,
.images = NULL,
.affineAnims = sAffineAnims_Bubble,
.affineAnims = gAffineAnims_Bubble,
.callback = AnimBubbleEffect,
};
@ -505,7 +504,7 @@ static void AnimAcidPoisonDroplet(struct Sprite *sprite)
// arg 0: initial x pixel offset
// arg 1: initial y pixel offset
// arg 2: 0 = single-target, 1 = multi-target
static void AnimBubbleEffect(struct Sprite *sprite)
void AnimBubbleEffect(struct Sprite *sprite)
{
if (!gBattleAnimArgs[2])
{

View File

@ -703,6 +703,54 @@ void AnimTask_Rollout(u8 taskId)
task->func = AnimTask_Rollout_Step;
}
void AnimTask_TectonicRageRollout(u8 taskId)
{
u16 var0, var1, var2, var3;
int var5;
s16 pan1, pan2;
struct Task *task;
u8 rolloutCounter = 1;
task = &gTasks[taskId];
var0 = GetBattlerSpriteCoord(gBattleAnimAttacker, 2);
var1 = GetBattlerSpriteCoord(gBattleAnimAttacker, 1) + 24;
var2 = GetBattlerSpriteCoord(gBattleAnimTarget, 2);
var3 = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + 24;
if (BATTLE_PARTNER(gBattleAnimAttacker) == gBattleAnimTarget)
var3 = var1;
task->data[8] = 48 - (rolloutCounter * 8); //rollout speed
task->data[0] = 0;
task->data[11] = 0;
task->data[9] = 0;
task->data[12] = 1;
var5 = task->data[8];
if (var5 < 0)
var5 += 7;
task->data[10] = (var5 >> 3) - 1;
task->data[2] = var0 * 8;
task->data[3] = var1 * 8;
task->data[4] = ((var2 - var0) * 8) / task->data[8];
task->data[5] = ((var3 - var1) * 8) / task->data[8];
task->data[6] = 0;
task->data[7] = 0;
pan1 = BattleAnimAdjustPanning(-64);
pan2 = BattleAnimAdjustPanning(63);
task->data[13] = pan1;
task->data[14] = (pan2 - pan1) / task->data[8];
task->data[1] = rolloutCounter;
task->data[15] = GetAnimBattlerSpriteId(ANIM_ATTACKER);
task->func = AnimTask_Rollout_Step;
}
static void AnimTask_Rollout_Step(u8 taskId)
{
struct Task *task;

View File

@ -107,7 +107,7 @@ static const union AnimCmd sAnim_SpinningSparkle[] =
ANIMCMD_END
};
static const union AnimCmd *const sAnims_SpinningSparkle[] =
const union AnimCmd *const sAnims_SpinningSparkle[] =
{
sAnim_SpinningSparkle
};
@ -379,6 +379,25 @@ static void AnimFlashingCircleImpact_Step(struct Sprite *sprite)
}
}
void AnimTask_FrozenIceCubeAttacker(u8 taskId)
{
s16 x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2) - 32;
s16 y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET) - 36;
u8 spriteId;
if (IsContest())
x -= 6;
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL);
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16));
spriteId = CreateSprite(&gFrozenIceCubeSpriteTemplate, x, y, 4);
if (GetSpriteTileStartByTag(ANIM_TAG_ICE_CUBE) == 0xFFFF)
gSprites[spriteId].invisible = TRUE;
SetSubspriteTables(&gSprites[spriteId], sFrozenIceCubeSubspriteTable);
gTasks[taskId].data[15] = spriteId;
gTasks[taskId].func = AnimTask_FrozenIceCube_Step1;
}
void AnimTask_FrozenIceCube(u8 taskId)
{
s16 x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) - 32;

View File

@ -194,7 +194,7 @@ static const struct WindowTemplate gStandardBattleWindowTemplates[] =
.bg = 0,
.tilemapLeft = 2,
.tilemapTop = 55,
.width = 8,
.width = 12, //for z move names
.height = 2,
.paletteNum = 5,
.baseBlock = 0x0300,
@ -206,7 +206,7 @@ static const struct WindowTemplate gStandardBattleWindowTemplates[] =
.width = 8,
.height = 2,
.paletteNum = 5,
.baseBlock = 0x0310,
.baseBlock = 0x0318,
},
[B_WIN_MOVE_NAME_3] = {
.bg = 0,
@ -215,7 +215,7 @@ static const struct WindowTemplate gStandardBattleWindowTemplates[] =
.width = 8,
.height = 2,
.paletteNum = 5,
.baseBlock = 0x0320,
.baseBlock = 0x0328,
},
[B_WIN_MOVE_NAME_4] = {
.bg = 0,
@ -224,7 +224,7 @@ static const struct WindowTemplate gStandardBattleWindowTemplates[] =
.width = 8,
.height = 2,
.paletteNum = 5,
.baseBlock = 0x0330,
.baseBlock = 0x0338,
},
[B_WIN_PP] = {
.bg = 0,

View File

@ -1,6 +1,7 @@
#include "global.h"
#include "battle.h"
#include "battle_ai_main.h"
#include "battle_ai_util.h"
#include "battle_anim.h"
#include "battle_arena.h"
#include "battle_controllers.h"
@ -9,6 +10,7 @@
#include "battle_setup.h"
#include "battle_tower.h"
#include "battle_tv.h"
#include "battle_z_move.h"
#include "bg.h"
#include "data.h"
#include "frontier_util.h"
@ -1580,16 +1582,25 @@ static void OpponentHandleChooseMove(void)
gBattlerTarget = gActiveBattler;
if (GetBattlerMoveTargetType(gActiveBattler, moveInfo->moves[chosenMoveId]) & MOVE_TARGET_BOTH)
{
gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
u16 chosenMove = moveInfo->moves[chosenMoveId];
if (gBattleMoves[chosenMove].target & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER))
gBattlerTarget = gActiveBattler;
if (gBattleMoves[chosenMove].target & MOVE_TARGET_BOTH)
{
gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
}
if (ShouldUseZMove(gActiveBattler, gBattlerTarget, chosenMove))
QueueZMove(gActiveBattler, chosenMove);
if (CanMegaEvolve(gActiveBattler)) // If opponent can mega evolve, do it.
BtlController_EmitTwoReturnValues(BUFFER_B, 10, (chosenMoveId) | (RET_MEGA_EVOLUTION) | (gBattlerTarget << 8));
else
BtlController_EmitTwoReturnValues(BUFFER_B, 10, (chosenMoveId) | (gBattlerTarget << 8));
}
// If opponent can mega evolve, do it.
if (CanMegaEvolve(gActiveBattler))
BtlController_EmitTwoReturnValues(BUFFER_B, 10, (chosenMoveId) | (RET_MEGA_EVOLUTION) | (gBattlerTarget << 8));
else
BtlController_EmitTwoReturnValues(BUFFER_B, 10, (chosenMoveId) | (gBattlerTarget << 8));
break;
}
OpponentBufferExecCompleted();

View File

@ -8,6 +8,7 @@
#include "battle_message.h"
#include "battle_setup.h"
#include "battle_tv.h"
#include "battle_z_move.h"
#include "bg.h"
#include "data.h"
#include "item.h"
@ -98,8 +99,6 @@ static void PlayerCmdEnd(void);
static void PlayerBufferRunCommand(void);
static void HandleInputChooseTarget(void);
static void HandleInputChooseMove(void);
static void MoveSelectionCreateCursorAt(u8 cursorPos, u8 arg1);
static void MoveSelectionDestroyCursorAt(u8 cursorPos);
static void MoveSelectionDisplayPpNumber(void);
static void MoveSelectionDisplayPpString(void);
static void MoveSelectionDisplayMoveType(void);
@ -122,6 +121,8 @@ static void PlayerDoMoveAnimation(void);
static void Task_StartSendOutAnim(u8 taskId);
static void EndDrawPartyStatusSummary(void);
static void ReloadMoveNames(void);
static void (*const sPlayerBufferCommands[CONTROLLER_CMDS_COUNT])(void) =
{
[CONTROLLER_GETMONDATA] = PlayerHandleGetMonData,
@ -381,7 +382,7 @@ static void HandleInputChooseTarget(void)
BtlController_EmitTwoReturnValues(BUFFER_B, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8));
EndBounceEffect(gMultiUsePlayerCursor, BOUNCE_HEALTHBOX);
TryHideLastUsedBall();
HideMegaTriggerSprite();
HideTriggerSprites();
PlayerBufferExecCompleted();
}
else if (JOY_NEW(B_BUTTON) || gPlayerDpadHoldFrames > 59)
@ -565,7 +566,7 @@ static void HandleInputShowTargets(void)
BtlController_EmitTwoReturnValues(BUFFER_B, 10, gMoveSelectionCursor[gActiveBattler] | RET_MEGA_EVOLUTION | (gMultiUsePlayerCursor << 8));
else
BtlController_EmitTwoReturnValues(BUFFER_B, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8));
HideMegaTriggerSprite();
HideTriggerSprites();
TryHideLastUsedBall();
PlayerBufferExecCompleted();
}
@ -613,7 +614,17 @@ static void HandleInputChooseMove(void)
{
moveTarget = GetBattlerMoveTargetType(gActiveBattler, moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]);
}
if (gBattleStruct->zmove.viewing)
{
u16 chosenMove = moveInfo->moves[gMoveSelectionCursor[gActiveBattler]];
QueueZMove(gActiveBattler, chosenMove);
gBattleStruct->zmove.viewing = FALSE;
if (gBattleMoves[moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]].split != SPLIT_STATUS)
moveTarget = MOVE_TARGET_SELECTED; //damaging z moves always have selected target
}
if (moveTarget & MOVE_TARGET_USER)
gMultiUsePlayerCursor = gActiveBattler;
else
@ -671,7 +682,7 @@ static void HandleInputChooseMove(void)
BtlController_EmitTwoReturnValues(BUFFER_B, 10, gMoveSelectionCursor[gActiveBattler] | RET_MEGA_EVOLUTION | (gMultiUsePlayerCursor << 8));
else
BtlController_EmitTwoReturnValues(BUFFER_B, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8));
HideMegaTriggerSprite();
HideTriggerSprites();
TryHideLastUsedBall();
PlayerBufferExecCompleted();
break;
@ -698,12 +709,20 @@ static void HandleInputChooseMove(void)
else if (JOY_NEW(B_BUTTON) || gPlayerDpadHoldFrames > 59)
{
PlaySE(SE_SELECT);
gBattleStruct->mega.playerSelect = FALSE;
BtlController_EmitTwoReturnValues(BUFFER_B, 10, 0xFFFF);
HideMegaTriggerSprite();
PlayerBufferExecCompleted();
if (gBattleStruct->zmove.viewing)
{
ReloadMoveNames();
}
else
{
gBattleStruct->mega.playerSelect = FALSE;
gBattleStruct->zmove.viable = FALSE;
BtlController_EmitTwoReturnValues(BUFFER_B, 10, 0xFFFF);
HideTriggerSprites();
PlayerBufferExecCompleted();
}
}
else if (JOY_NEW(DPAD_LEFT))
else if (JOY_NEW(DPAD_LEFT) && !gBattleStruct->zmove.viewing)
{
if (gMoveSelectionCursor[gActiveBattler] & 1)
{
@ -713,9 +732,10 @@ static void HandleInputChooseMove(void)
MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBattler], 0);
MoveSelectionDisplayPpNumber();
MoveSelectionDisplayMoveType();
TryChangeZIndicator(gActiveBattler, gMoveSelectionCursor[gActiveBattler]);
}
}
else if (JOY_NEW(DPAD_RIGHT))
else if (JOY_NEW(DPAD_RIGHT) && !gBattleStruct->zmove.viewing)
{
if (!(gMoveSelectionCursor[gActiveBattler] & 1)
&& (gMoveSelectionCursor[gActiveBattler] ^ 1) < gNumberOfMovesToChoose)
@ -726,9 +746,10 @@ static void HandleInputChooseMove(void)
MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBattler], 0);
MoveSelectionDisplayPpNumber();
MoveSelectionDisplayMoveType();
TryChangeZIndicator(gActiveBattler, gMoveSelectionCursor[gActiveBattler]);
}
}
else if (JOY_NEW(DPAD_UP))
else if (JOY_NEW(DPAD_UP) && !gBattleStruct->zmove.viewing)
{
if (gMoveSelectionCursor[gActiveBattler] & 2)
{
@ -738,9 +759,10 @@ static void HandleInputChooseMove(void)
MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBattler], 0);
MoveSelectionDisplayPpNumber();
MoveSelectionDisplayMoveType();
TryChangeZIndicator(gActiveBattler, gMoveSelectionCursor[gActiveBattler]);
}
}
else if (JOY_NEW(DPAD_DOWN))
else if (JOY_NEW(DPAD_DOWN) && !gBattleStruct->zmove.viewing)
{
if (!(gMoveSelectionCursor[gActiveBattler] & 2)
&& (gMoveSelectionCursor[gActiveBattler] ^ 2) < gNumberOfMovesToChoose)
@ -751,9 +773,10 @@ static void HandleInputChooseMove(void)
MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBattler], 0);
MoveSelectionDisplayPpNumber();
MoveSelectionDisplayMoveType();
TryChangeZIndicator(gActiveBattler, gMoveSelectionCursor[gActiveBattler]);
}
}
else if (JOY_NEW(SELECT_BUTTON))
else if (JOY_NEW(SELECT_BUTTON) && !gBattleStruct->zmove.viewing)
{
if (gNumberOfMovesToChoose > 1 && !(gBattleTypeFlags & BATTLE_TYPE_LINK))
{
@ -769,7 +792,7 @@ static void HandleInputChooseMove(void)
gBattlerControllerFuncs[gActiveBattler] = HandleMoveSwitching;
}
}
else if (gMain.newKeys & START_BUTTON)
else if (JOY_NEW(START_BUTTON))
{
if (CanMegaEvolve(gActiveBattler))
{
@ -777,9 +800,30 @@ static void HandleInputChooseMove(void)
ChangeMegaTriggerSprite(gBattleStruct->mega.triggerSpriteId, gBattleStruct->mega.playerSelect);
PlaySE(SE_SELECT);
}
else if (gBattleStruct->zmove.viable)
{
// show z move name / info
//TODO: brighten z move symbol
PlaySE(SE_SELECT);
if (!gBattleStruct->zmove.viewing)
MoveSelectionDisplayZMove(gBattleStruct->zmove.chosenZMove);
else
ReloadMoveNames();
}
}
}
static void ReloadMoveNames(void)
{
gBattleStruct->mega.playerSelect = FALSE;
gBattleStruct->zmove.viewing = FALSE;
MoveSelectionDestroyCursorAt(0);
MoveSelectionDisplayMoveNames();
MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBattler], 0);
MoveSelectionDisplayPpNumber();
MoveSelectionDisplayMoveType();
}
static u32 HandleMoveInputUnused(void)
{
u32 var = 0;
@ -1684,7 +1728,7 @@ static void MoveSelectionDisplayMoveType(void)
BattlePutTextOnWindow(gDisplayedStringBattle, B_WIN_MOVE_TYPE);
}
static void MoveSelectionCreateCursorAt(u8 cursorPosition, u8 arg1)
void MoveSelectionCreateCursorAt(u8 cursorPosition, u8 arg1)
{
u16 src[2];
src[0] = arg1 + 1;
@ -1694,7 +1738,7 @@ static void MoveSelectionCreateCursorAt(u8 cursorPosition, u8 arg1)
CopyBgTilemapBufferToVram(0);
}
static void MoveSelectionDestroyCursorAt(u8 cursorPosition)
void MoveSelectionDestroyCursorAt(u8 cursorPosition)
{
u16 src[2];
src[0] = 0x1016;
@ -2813,12 +2857,20 @@ static void PlayerHandleChooseMove(void)
}
else
{
struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct*)(&gBattleResources->bufferA[gActiveBattler][4]);
InitMoveSelectionsVarsAndStrings();
gBattleStruct->mega.playerSelect = FALSE;
if (!IsMegaTriggerSpriteActive())
gBattleStruct->mega.triggerSpriteId = 0xFF;
if (CanMegaEvolve(gActiveBattler))
CreateMegaTriggerSprite(gActiveBattler, 0);
if (!IsZMoveTriggerSpriteActive())
gBattleStruct->zmove.triggerSpriteId = 0xFF;
GetUsableZMoves(gActiveBattler, moveInfo->moves);
gBattleStruct->zmove.viable = IsZMoveUsable(gActiveBattler, gMoveSelectionCursor[gActiveBattler]);
CreateZMoveTriggerSprite(gActiveBattler, gBattleStruct->zmove.viable);
gBattlerControllerFuncs[gActiveBattler] = HandleChooseMoveAfterDma3;
}
}

View File

@ -1,12 +1,14 @@
#include "global.h"
#include "battle.h"
#include "battle_ai_main.h"
#include "battle_ai_util.h"
#include "battle_anim.h"
#include "battle_controllers.h"
#include "battle_message.h"
#include "battle_interface.h"
#include "battle_setup.h"
#include "battle_tower.h"
#include "battle_z_move.h"
#include "bg.h"
#include "data.h"
#include "item_use.h"
@ -1526,6 +1528,9 @@ static void PlayerPartnerHandleChooseMove(void)
if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
}
if (ShouldUseZMove(gActiveBattler, gBattlerTarget, moveInfo->moves[chosenMoveId]))
QueueZMove(gActiveBattler, moveInfo->moves[chosenMoveId]);
// If partner can mega evolve, do it.
if (CanMegaEvolve(gActiveBattler))

View File

@ -4,6 +4,7 @@
#include "pokemon.h"
#include "battle_controllers.h"
#include "battle_interface.h"
#include "battle_z_move.h"
#include "graphics.h"
#include "sprite.h"
#include "window.h"
@ -1530,6 +1531,12 @@ void HideMegaTriggerSprite(void)
}
}
void HideTriggerSprites(void)
{
HideMegaTriggerSprite();
HideZMoveTriggerSprite();
}
void DestroyMegaTriggerSprite(void)
{
FreeSpritePaletteByTag(TAG_MEGA_TRIGGER_PAL);

View File

@ -134,7 +134,7 @@ EWRAM_DATA u16 gBattle_WIN1V = 0;
EWRAM_DATA u8 gDisplayedStringBattle[400] = {0};
EWRAM_DATA u8 gBattleTextBuff1[TEXT_BUFF_ARRAY_COUNT] = {0};
EWRAM_DATA u8 gBattleTextBuff2[TEXT_BUFF_ARRAY_COUNT] = {0};
EWRAM_DATA u8 gBattleTextBuff3[TEXT_BUFF_ARRAY_COUNT] = {0};
EWRAM_DATA u8 gBattleTextBuff3[30] = {0}; //expanded for stupidly long z move names
// The below array is never intentionally used. However, Juan's
// defeat text (SootopolisCity_Gym_1F_Text_JuanDefeat) is too long
// for gDisplayedStringBattle and overflows into this array. If it
@ -239,7 +239,6 @@ EWRAM_DATA struct TotemBoost gTotemBoosts[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA bool8 gHasFetchedBall = FALSE;
EWRAM_DATA u8 gLastUsedBall = 0;
EWRAM_DATA u16 gLastThrownBall = 0;
EWRAM_DATA bool8 gSwapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky
EWRAM_DATA u8 gPartyCriticalHits[PARTY_SIZE] = {0};
EWRAM_DATA static u8 sTriedEvolving = 0;
@ -3007,7 +3006,7 @@ static void BattleStartClearSetData(void)
gPartyCriticalHits[i] = 0;
}
gSwapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky
gBattleStruct->swapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky
}
void SwitchInClearSetData(void)
@ -3992,6 +3991,7 @@ static void HandleTurnActionSelectionState(void)
{
struct ChooseMoveStruct moveInfo;
moveInfo.zmove = gBattleStruct->zmove;
moveInfo.mega = gBattleStruct->mega;
moveInfo.species = gBattleMons[gActiveBattler].species;
moveInfo.monType1 = gBattleMons[gActiveBattler].type1;
@ -4107,6 +4107,7 @@ static void HandleTurnActionSelectionState(void)
}
gBattleStruct->mega.toEvolve &= ~(gBitTable[BATTLE_PARTNER(GetBattlerPosition(gActiveBattler))]);
gBattleStruct->zmove.toBeUsed[BATTLE_PARTNER(GetBattlerPosition(gActiveBattler))] = MOVE_NONE;
BtlController_EmitEndBounceEffect(BUFFER_A);
MarkBattlerForControllerExec(gActiveBattler);
return;

View File

@ -5,6 +5,7 @@
#include "battle_message.h"
#include "battle_setup.h"
#include "battle_tower.h"
#include "battle_z_move.h"
#include "data.h"
#include "event_data.h"
#include "frontier_util.h"
@ -48,7 +49,6 @@ struct BattleWindowText
static void ChooseMoveUsedParticle(u8 *textPtr);
static void ChooseTypeOfMoveUsedString(u8 *dst);
static void ExpandBattleTextBuffPlaceholders(const u8 *src, u8 *dst);
static EWRAM_DATA u16 sBattlerAbilities[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA struct BattleMsgData *gBattleMsgDataPtr = NULL;
@ -700,6 +700,15 @@ static const u8 sText_CanActFaster[] = _("{B_ATK_NAME_WITH_PREFIX} can act faste
static const u8 sText_MicleBerryActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} boosted the accuracy of its\nnext move using {B_LAST_ITEM}!");
static const u8 sText_PkmnShookOffTheTaunt[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} shook off\nthe taunt!");
static const u8 sText_PkmnGotOverItsInfatuation[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} got over\nits infatuation!");
static const u8 sText_ZPowerSurrounds[] = _("{B_ATK_NAME_WITH_PREFIX} surrounds\nitself with its Z-Power!");
static const u8 sText_ZPowerUnleashed[] = _("{B_ATK_NAME_WITH_PREFIX} unleashes\nits full-force Z-Move!");
static const u8 sText_ZMoveResetsStats[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} returned its\ndecreased stats to normal using\lits Z-Power!");
static const u8 sText_ZMoveAllStatsUp[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} boosted all\nof its stats using its Z-Power!");
static const u8 sText_ZMoveBoostCrit[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} boosted its\ncritical-hit ratio using its Z-Power!");
static const u8 sText_ZMoveRestoreHp[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} restored its\nHP using its Z-Power!");
static const u8 sText_ZMoveStatUp[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} boosted\nits stats using its Z-Power!");
static const u8 sText_ZMoveHpSwitchInTrap[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s HP was restored by the Z-Power!");
static const u8 sText_TerrainReturnedToNormal[] = _("The terrain returned to\nnormal!");
static const u8 sText_ItemCannotBeRemoved[] = _("{B_ATK_NAME_WITH_PREFIX}'s item cannot be removed!");
static const u8 sText_StickyBarbTransfer[] = _("The {B_LAST_ITEM} attached itself to\n{B_ATK_NAME_WITH_PREFIX}!");
static const u8 sText_PkmnBurnHealed[] = _("{B_DEF_NAME_WITH_PREFIX}'s\nburn was healed.");
@ -745,8 +754,17 @@ static const u8 sText_MeteorBeamCharging[] = _("{B_ATK_NAME_WITH_PREFIX} is over
static const u8 sText_HeatingUpBeak[] = _("{B_ATK_NAME_WITH_PREFIX} started\nheating up its beak!");
static const u8 sText_CourtChange[] = _("{B_ATK_NAME_WITH_PREFIX} swapped the battle\neffects affecting each side!");
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
{
[STRINGID_ZPOWERSURROUNDS - BATTLESTRINGS_TABLE_START] = sText_ZPowerSurrounds,
[STRINGID_ZMOVEUNLEASHED - BATTLESTRINGS_TABLE_START] = sText_ZPowerUnleashed,
[STRINGID_ZMOVERESETSSTATS - BATTLESTRINGS_TABLE_START] = sText_ZMoveResetsStats,
[STRINGID_ZMOVEALLSTATSUP - BATTLESTRINGS_TABLE_START] = sText_ZMoveAllStatsUp,
[STRINGID_ZMOVEZBOOSTCRIT - BATTLESTRINGS_TABLE_START] = sText_ZMoveBoostCrit,
[STRINGID_ZMOVERESTOREHP - BATTLESTRINGS_TABLE_START] = sText_ZMoveRestoreHp,
[STRINGID_ZMOVESTATUP - BATTLESTRINGS_TABLE_START] = sText_ZMoveStatUp,
[STRINGID_ZMOVEHPTRAP - BATTLESTRINGS_TABLE_START] = sText_ZMoveHpSwitchInTrap,
[STRINGID_PLAYERLOSTTOENEMYTRAINER - BATTLESTRINGS_TABLE_START] = sText_PlayerLostToEnemyTrainer,
[STRINGID_PLAYERPAIDPRIZEMONEY - BATTLESTRINGS_TABLE_START] = sText_PlayerPaidPrizeMoney,
[STRINGID_COURTCHANGE - BATTLESTRINGS_TABLE_START] = sText_CourtChange,
@ -1353,6 +1371,17 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
[STRINGID_TARGETTOOHEAVY - BATTLESTRINGS_TABLE_START] = sText_TargetTooHeavy,
};
const u16 gZEffectStringIds[] =
{
[B_MSG_Z_RESET_STATS] = STRINGID_ZMOVERESETSSTATS,
[B_MSG_Z_ALL_STATS_UP]= STRINGID_ZMOVEALLSTATSUP,
[B_MSG_Z_BOOST_CRITS] = STRINGID_ZMOVEZBOOSTCRIT,
[B_MSG_Z_FOLLOW_ME] = STRINGID_PKMNCENTERATTENTION,
[B_MSG_Z_RECOVER_HP] = STRINGID_ZMOVERESTOREHP,
[B_MSG_Z_STAT_UP] = STRINGID_ZMOVESTATUP,
[B_MSG_Z_HP_TRAP] = STRINGID_ZMOVEHPTRAP,
};
const u16 gMentalHerbCureStringIds[] =
{
[B_MSG_MENTALHERBCURE_INFATUATION] = STRINGID_ATKGOTOVERINFATUATION,
@ -1365,7 +1394,7 @@ const u16 gMentalHerbCureStringIds[] =
const u16 gTerrainStringIds[] =
{
STRINGID_TERRAINBECOMESMISTY, STRINGID_TERRAINBECOMESGRASSY, STRINGID_TERRAINBECOMESELECTRIC, STRINGID_TERRAINBECOMESPSYCHIC
STRINGID_TERRAINBECOMESMISTY, STRINGID_TERRAINBECOMESGRASSY, STRINGID_TERRAINBECOMESELECTRIC, STRINGID_TERRAINBECOMESPSYCHIC, STRINGID_TERRAINREMOVED,
};
const u16 gTerrainEndingStringIds[] =
@ -2794,7 +2823,9 @@ void BufferStringBattle(u16 stringID)
}
break;
case STRINGID_USEDMOVE: // pokemon used a move msg
if (gBattleMsgDataPtr->currentMove >= MOVES_COUNT)
if (gBattleStruct->zmove.active && gBattleStruct->zmove.activeSplit != SPLIT_STATUS)
StringCopy(gBattleTextBuff3, GetZMoveName(gBattleMsgDataPtr->currentMove));
else if (gBattleMsgDataPtr->currentMove >= MOVES_COUNT)
StringCopy(gBattleTextBuff3, sATypeMove_Table[*(&gBattleStruct->stringMoveType)]);
else
StringCopy(gBattleTextBuff3, gMoveNames[gBattleMsgDataPtr->currentMove]);
@ -3222,13 +3253,17 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst)
HANDLE_NICKNAME_STRING_CASE(gBattleScripting.battler)
break;
case B_TXT_CURRENT_MOVE: // current move name
if (gBattleMsgDataPtr->currentMove >= MOVES_COUNT)
if (gBattleStruct->zmove.active)
toCpy = GetZMoveName(gBattleMsgDataPtr->currentMove);
else if (gBattleMsgDataPtr->currentMove >= MOVES_COUNT)
toCpy = sATypeMove_Table[gBattleStruct->stringMoveType];
else
toCpy = gMoveNames[gBattleMsgDataPtr->currentMove];
break;
case B_TXT_LAST_MOVE: // originally used move name
if (gBattleMsgDataPtr->originallyUsedMove >= MOVES_COUNT)
if (gBattleStruct->zmove.active)
toCpy = GetZMoveName(gBattleMsgDataPtr->originallyUsedMove);
else if (gBattleMsgDataPtr->originallyUsedMove >= MOVES_COUNT)
toCpy = sATypeMove_Table[gBattleStruct->stringMoveType];
else
toCpy = gMoveNames[gBattleMsgDataPtr->originallyUsedMove];
@ -3558,7 +3593,7 @@ static void IllusionNickHack(u32 battlerId, u32 partyId, u8 *dst)
GetMonData(mon, MON_DATA_NICKNAME, dst);
}
static void ExpandBattleTextBuffPlaceholders(const u8 *src, u8 *dst)
void ExpandBattleTextBuffPlaceholders(const u8 *src, u8 *dst)
{
u32 srcID = 1;
u32 value = 0;

View File

@ -5,6 +5,9 @@
#include "battle_ai_main.h"
#include "battle_ai_util.h"
#include "battle_scripts.h"
#include "battle_z_move.h"
#include "constants/moves.h"
#include "constants/abilities.h"
#include "item.h"
#include "util.h"
#include "pokemon.h"
@ -1618,6 +1621,12 @@ static bool32 AccuracyCalcHelper(u16 move)
RecordAbilityBattle(gBattlerTarget, ABILITY_NO_GUARD);
return TRUE;
}
if (gBattleStruct->zmove.active && !(gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE))
{
JumpIfMoveFailed(7, move);
return TRUE;
}
if ((gStatuses3[gBattlerTarget] & STATUS3_PHANTOM_FORCE)
|| (!(gBattleMoves[move].flags & (FLAG_DMG_IN_AIR | FLAG_DMG_2X_IN_AIR)) && gStatuses3[gBattlerTarget] & STATUS3_ON_AIR)
@ -1975,16 +1984,18 @@ static void Cmd_adjustdamage(void)
RecordItemEffectBattle(gBattlerTarget, holdEffect);
gSpecialStatuses[gBattlerTarget].focusBanded = TRUE;
}
else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && BATTLER_MAX_HP(gBattlerTarget))
{
RecordItemEffectBattle(gBattlerTarget, holdEffect);
gSpecialStatuses[gBattlerTarget].focusSashed = TRUE;
}
#if B_STURDY >= GEN_5
else if (GetBattlerAbility(gBattlerTarget) == ABILITY_STURDY && BATTLER_MAX_HP(gBattlerTarget))
{
RecordAbilityBattle(gBattlerTarget, ABILITY_STURDY);
gSpecialStatuses[gBattlerTarget].sturdied = TRUE;
}
#endif
else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && BATTLER_MAX_HP(gBattlerTarget))
{
RecordItemEffectBattle(gBattlerTarget, holdEffect);
gSpecialStatuses[gBattlerTarget].focusSashed = TRUE;
}
if (gBattleMoves[gCurrentMove].effect != EFFECT_FALSE_SWIPE
&& !gProtectStructs[gBattlerTarget].endured
@ -5622,6 +5633,10 @@ static void Cmd_moveend(void)
gSpecialStatuses[gBattlerAttacker].damagedMons = 0;
gSpecialStatuses[gBattlerTarget].berryReduced = FALSE;
gBattleScripting.moveEffect = 0;
// clear attacker z move data
gBattleStruct->zmove.active = FALSE;
gBattleStruct->zmove.toBeUsed[gBattlerAttacker] = MOVE_NONE;
gBattleStruct->zmove.effect = EFFECT_HIT;
gBattleScripting.moveendState++;
break;
case MOVEEND_COUNT:
@ -6400,6 +6415,16 @@ static void Cmd_switchineffects(void)
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_StickyWebOnSwitchIn;
}
else if (gBattleMons[gActiveBattler].hp != gBattleMons[gActiveBattler].maxHP && gBattleStruct->zmove.healReplacement)
{
gBattleStruct->zmove.healReplacement = FALSE;
gBattleMoveDamage = -1 * (gBattleMons[gActiveBattler].maxHP);
gBattleScripting.battler = gActiveBattler;
BattleScriptPushCursor();
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_HP_TRAP;
gBattlescriptCurrInstr = BattleScript_HealReplacementZMove;
return;
}
else
{
// There is a hack here to ensure the truant counter will be 0 when the battler's next turn starts.
@ -7498,12 +7523,12 @@ static bool32 HasAttackerFaintedTarget(void)
return FALSE;
}
static void HandleTerrainMove(u32 moveEffect)
static void HandleTerrainMove(u16 move)
{
u32 statusFlag = 0;
u8 *timer = NULL;
switch (moveEffect)
switch (gBattleMoves[move].effect)
{
case EFFECT_MISTY_TERRAIN:
statusFlag = STATUS_FIELD_MISTY_TERRAIN, timer = &gFieldTimers.terrainTimer;
@ -7521,6 +7546,31 @@ static void HandleTerrainMove(u32 moveEffect)
statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN, timer = &gFieldTimers.terrainTimer;
gBattleCommunication[MULTISTRING_CHOOSER] = 3;
break;
case EFFECT_DAMAGE_SET_TERRAIN:
switch (gBattleMoves[move].argument)
{
case 0: //genesis supernova
statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN, timer = &gFieldTimers.terrainTimer;
gBattleCommunication[MULTISTRING_CHOOSER] = 3;
break;
case 1: //splintered stormshards
if (!(gFieldStatuses & (STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_GRASSY_TERRAIN | STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_PSYCHIC_TERRAIN)))
{
//no terrain to remove -> jump to battle script pointer
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
}
else
{
// remove all terrain
gFieldStatuses &= ~(STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_GRASSY_TERRAIN | STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_PSYCHIC_TERRAIN);
gBattleCommunication[MULTISTRING_CHOOSER] = 4;
gBattlescriptCurrInstr += 7;
}
return;
default:
break;
}
break;
}
if (gFieldStatuses & statusFlag || statusFlag == 0)
@ -8425,7 +8475,7 @@ static void Cmd_various(void)
}
break;
case VARIOUS_SET_TERRAIN:
HandleTerrainMove(gBattleMoves[gCurrentMove].effect);
HandleTerrainMove(gCurrentMove);
return;
case VARIOUS_TRY_ME_FIRST:
if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget))
@ -8986,6 +9036,9 @@ static void Cmd_various(void)
gBattlescriptCurrInstr += 7; // exit if loop failed (failsafe)
}
return;
case VARIOUS_SET_Z_EFFECT:
SetZEffect(); //handles battle script jumping internally
return;
case VARIOUS_MOVEEND_ITEM_EFFECTS:
if (ItemBattleEffects(ITEMEFFECT_NORMAL, gActiveBattler, FALSE))
return;
@ -9141,7 +9194,7 @@ static void Cmd_various(void)
break;
case VARIOUS_JUMP_IF_UNDER_200:
// If the Pokemon is less than 200 kg, or weighing less than 441 lbs, then Sky Drop will work. Otherwise, it will fail.
if (GetPokedexHeightWeight(SpeciesToNationalPokedexNum(gBattleMons[gBattlerTarget].species), 1) < 441)
if (GetBattlerWeight(gBattlerTarget) < 2000)
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
else
gBattlescriptCurrInstr += 7;
@ -9353,24 +9406,8 @@ static void Cmd_various(void)
gBattlescriptCurrInstr += 9;
return;
case VARIOUS_PHOTON_GEYSER_CHECK:
{
u32 attackerAtkStat = gBattleMons[gBattlerAttacker].attack;
u8 attackerAtkStage = gBattleMons[gBattlerAttacker].statStages[STAT_ATK];
u32 attackerSpAtkStat = gBattleMons[gBattlerAttacker].spAttack;
gSwapDamageCategory = FALSE;
attackerAtkStat *= gStatStageRatios[attackerAtkStage][0];
attackerAtkStat /= gStatStageRatios[attackerAtkStage][1];
attackerAtkStage = gBattleMons[gBattlerAttacker].statStages[STAT_SPATK];
attackerSpAtkStat *= gStatStageRatios[attackerAtkStage][0];
attackerSpAtkStat /= gStatStageRatios[attackerAtkStage][1];
if (attackerAtkStat > attackerSpAtkStat)
gSwapDamageCategory = TRUE;
gBattleStruct->swapDamageCategory = (GetSplitBasedOnStats(gActiveBattler) == SPLIT_SPECIAL);
break;
}
case VARIOUS_SHELL_SIDE_ARM_CHECK: // 0% chance GameFreak actually checks this way according to DaWobblefet, but this is the only functional explanation at the moment
{
u32 attackerAtkStat = gBattleMons[gBattlerAttacker].attack;
@ -9381,7 +9418,7 @@ static void Cmd_various(void)
u32 physical;
u32 special;
gSwapDamageCategory = FALSE;
gBattleStruct->swapDamageCategory = FALSE;
statStage = gBattleMons[gBattlerAttacker].statStages[STAT_ATK];
attackerAtkStat *= gStatStageRatios[statStage][0];
@ -9404,7 +9441,7 @@ static void Cmd_various(void)
special = ((((2 * gBattleMons[gBattlerAttacker].level / 5 + 2) * gBattleMoves[gCurrentMove].power * attackerSpAtkStat) / targetSpDefStat) / 50);
if (((physical > special) || (physical == special && (Random() % 2) == 0)))
gSwapDamageCategory = TRUE;
gBattleStruct->swapDamageCategory = TRUE;
break;
}
case VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED:

View File

@ -268,15 +268,15 @@ void HandleAction_UseMove(void)
gCurrentMove = gChosenMove = gLockedMoves[gBattlerAttacker];
}
// encore forces you to use the same move
else if (gDisableStructs[gBattlerAttacker].encoredMove != MOVE_NONE
&& gDisableStructs[gBattlerAttacker].encoredMove == gBattleMons[gBattlerAttacker].moves[gDisableStructs[gBattlerAttacker].encoredMovePos])
else if (!gBattleStruct->zmove.active && gDisableStructs[gBattlerAttacker].encoredMove != MOVE_NONE
&& gDisableStructs[gBattlerAttacker].encoredMove == gBattleMons[gBattlerAttacker].moves[gDisableStructs[gBattlerAttacker].encoredMovePos])
{
gCurrentMove = gChosenMove = gDisableStructs[gBattlerAttacker].encoredMove;
gCurrMovePos = gChosenMovePos = gDisableStructs[gBattlerAttacker].encoredMovePos;
*(gBattleStruct->moveTarget + gBattlerAttacker) = GetMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE);
}
// check if the encored move wasn't overwritten
else if (gDisableStructs[gBattlerAttacker].encoredMove != MOVE_NONE
else if (!gBattleStruct->zmove.active && gDisableStructs[gBattlerAttacker].encoredMove != MOVE_NONE
&& gDisableStructs[gBattlerAttacker].encoredMove != gBattleMons[gBattlerAttacker].moves[gDisableStructs[gBattlerAttacker].encoredMovePos])
{
gCurrMovePos = gChosenMovePos = gDisableStructs[gBattlerAttacker].encoredMovePos;
@ -295,6 +295,12 @@ void HandleAction_UseMove(void)
{
gCurrentMove = gChosenMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos];
}
// check z move used
if (gBattleStruct->zmove.toBeUsed[gBattlerAttacker] != MOVE_NONE && !IS_MOVE_STATUS(gCurrentMove))
{
gCurrentMove = gBattleStruct->zmove.toBeUsed[gBattlerAttacker];
}
if (gBattleMons[gBattlerAttacker].hp != 0)
{
@ -1758,7 +1764,7 @@ u8 TrySetCantSelectMoveBattleScript(void)
}
}
if (gDisableStructs[gActiveBattler].tauntTimer != 0 && gBattleMoves[move].power == 0)
if (!gBattleStruct->zmove.active && gDisableStructs[gActiveBattler].tauntTimer != 0 && gBattleMoves[move].power == 0)
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1773,7 +1779,7 @@ u8 TrySetCantSelectMoveBattleScript(void)
}
}
if (gDisableStructs[gActiveBattler].throatChopTimer != 0 && gBattleMoves[move].flags & FLAG_SOUND)
if (!gBattleStruct->zmove.active && gDisableStructs[gActiveBattler].throatChopTimer != 0 && gBattleMoves[move].flags & FLAG_SOUND)
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1788,7 +1794,7 @@ u8 TrySetCantSelectMoveBattleScript(void)
}
}
if (GetImprisonedMovesCount(gActiveBattler, move))
if (!gBattleStruct->zmove.active && GetImprisonedMovesCount(gActiveBattler, move))
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1803,7 +1809,7 @@ u8 TrySetCantSelectMoveBattleScript(void)
}
}
if (IsGravityPreventingMove(move))
if (!gBattleStruct->zmove.active && IsGravityPreventingMove(move))
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1818,7 +1824,7 @@ u8 TrySetCantSelectMoveBattleScript(void)
}
}
if (IsHealBlockPreventingMove(gActiveBattler, move))
if (!gBattleStruct->zmove.active && IsHealBlockPreventingMove(gActiveBattler, move))
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1833,7 +1839,7 @@ u8 TrySetCantSelectMoveBattleScript(void)
}
}
if (IsBelchPreventingMove(gActiveBattler, move))
if (!gBattleStruct->zmove.active && IsBelchPreventingMove(gActiveBattler, move))
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -3373,6 +3379,7 @@ enum
CANCELLER_POWDER_MOVE,
CANCELLER_POWDER_STATUS,
CANCELLER_THROAT_CHOP,
CANCELLER_Z_MOVES,
CANCELLER_END,
CANCELLER_PSYCHIC_TERRAIN,
CANCELLER_END2,
@ -3711,6 +3718,33 @@ u8 AtkCanceller_UnableToUseMove(void)
}
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_Z_MOVES:
if (gBattleStruct->zmove.toBeUsed[gBattlerAttacker] != MOVE_NONE)
{
//attacker has a queued z move
gBattleStruct->zmove.active = TRUE;
gBattleStruct->zmove.activeSplit = gBattleStruct->zmove.splits[gBattlerAttacker];
RecordItemEffectBattle(gBattlerAttacker, HOLD_EFFECT_Z_CRYSTAL);
gBattleStruct->zmove.used[gBattlerAttacker] = TRUE;
if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && IsPartnerMonFromSameTrainer(gBattlerAttacker))
gBattleStruct->zmove.used[BATTLE_PARTNER(gBattlerAttacker)] = TRUE; //if 1v1 double, set partner used flag as well
gBattleScripting.battler = gBattlerAttacker;
if (gBattleStruct->zmove.activeSplit == SPLIT_STATUS)
{
gBattleStruct->zmove.effect = gBattleMoves[gBattleStruct->zmove.baseMoves[gBattlerAttacker]].zMoveEffect;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_ZMoveActivateStatus;
}
else
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_ZMoveActivateDamaging;
}
effect = 1;
}
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_END:
break;
}
@ -7706,7 +7740,7 @@ bool32 IsMoveMakingContact(u16 move, u8 battlerAtk)
{
if (!(gBattleMoves[move].flags & FLAG_MAKES_CONTACT))
{
if (gBattleMoves[move].effect == EFFECT_SHELL_SIDE_ARM && gSwapDamageCategory)
if (gBattleMoves[move].effect == EFFECT_SHELL_SIDE_ARM && gBattleStruct->swapDamageCategory)
return TRUE;
else
return FALSE;
@ -7739,7 +7773,7 @@ bool32 IsBattlerProtected(u8 battlerId, u16 move)
// Protective Pads doesn't stop Unseen Fist from bypassing Protect effects, so IsMoveMakingContact() isn't used here.
// This means extra logic is needed to handle Shell Side Arm.
if (GetBattlerAbility(gBattlerAttacker) == ABILITY_UNSEEN_FIST
&& (gBattleMoves[move].flags & FLAG_MAKES_CONTACT || (gBattleMoves[move].effect == EFFECT_SHELL_SIDE_ARM && gSwapDamageCategory)))
&& (gBattleMoves[move].flags & FLAG_MAKES_CONTACT || (gBattleMoves[move].effect == EFFECT_SHELL_SIDE_ARM && gBattleStruct->swapDamageCategory)))
return FALSE;
else if (!(gBattleMoves[move].flags & FLAG_PROTECT_AFFECTED))
return FALSE;
@ -8012,6 +8046,9 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef)
u32 i;
u16 basePower = gBattleMoves[move].power;
u32 weight, hpFraction, speed;
if (gBattleStruct->zmove.active)
return gBattleMoves[gBattleStruct->zmove.baseMoves[battlerAtk]].zMovePower;
switch (gBattleMoves[move].effect)
{
@ -8813,6 +8850,12 @@ static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType,
usesDefStat = FALSE;
}
#if B_EXPLOSION_DEFENSE <= GEN_4
// Self-destruct / Explosion cut defense in half
if (gBattleMoves[gCurrentMove].effect == EFFECT_EXPLOSION)
defStat /= 2;
#endif
// critical hits ignore positive stat changes
if (isCrit && defStage > DEFAULT_STAT_STAGE)
defStage = DEFAULT_STAT_STAGE;
@ -9415,6 +9458,11 @@ bool32 CanMegaEvolve(u8 battlerId)
// Check if trainer already mega evolved a pokemon.
if (mega->alreadyEvolved[battlerPosition])
return FALSE;
// Cannot use z move and mega evolve on same turn
if (gBattleStruct->zmove.toBeUsed[battlerId])
return FALSE;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
&& IsPartnerMonFromSameTrainer(battlerId)
&& (mega->alreadyEvolved[partnerPosition] || (mega->toEvolve & gBitTable[BATTLE_PARTNER(battlerId)])))
@ -9660,7 +9708,9 @@ bool8 ShouldGetStatBadgeBoost(u16 badgeFlag, u8 battlerId)
u8 GetBattleMoveSplit(u32 moveId)
{
if (gSwapDamageCategory) // Photon Geyser, Shell Side Arm, Light That Burns the Sky
if (gBattleStruct != NULL && gBattleStruct->zmove.active && !IS_MOVE_STATUS(moveId))
return gBattleStruct->zmove.activeSplit;
if (gBattleStruct != NULL && gBattleStruct->swapDamageCategory) // Photon Geyser, Shell Side Arm, Light That Burns the Sky
return SPLIT_PHYSICAL;
else if (IS_MOVE_STATUS(moveId) || B_PHYSICAL_SPECIAL_SPLIT >= GEN_4)
return gBattleMoves[moveId].split;
@ -9708,6 +9758,24 @@ static bool32 IsUnnerveAbilityOnOpposingSide(u8 battlerId)
return FALSE;
}
// Photon geyser & light that burns the sky
u8 GetSplitBasedOnStats(u8 battlerId)
{
u32 attack = gBattleMons[battlerId].attack;
u32 spAttack = gBattleMons[battlerId].spAttack;
attack = attack * gStatStageRatios[gBattleMons[battlerId].statStages[STAT_ATK]][0];
attack = attack / gStatStageRatios[gBattleMons[battlerId].statStages[STAT_ATK]][1];
spAttack = spAttack * gStatStageRatios[gBattleMons[battlerId].statStages[STAT_SPATK]][0];
spAttack = spAttack / gStatStageRatios[gBattleMons[battlerId].statStages[STAT_SPATK]][1];
if (spAttack >= attack)
return SPLIT_SPECIAL;
else
return SPLIT_PHYSICAL;
}
bool32 TestMoveFlags(u16 move, u32 flag)
{
if (gBattleMoves[move].flags & flag)
@ -9726,7 +9794,7 @@ struct Pokemon *GetBattlerPartyData(u8 battlerId)
return mon;
}
//Make sure the input bank is any bank on the specific mon's side
// Make sure the input bank is any bank on the specific mon's side
bool32 CanFling(u8 battlerId)
{
u16 item = gBattleMons[battlerId].item;
@ -9745,7 +9813,7 @@ bool32 CanFling(u8 battlerId)
return TRUE;
}
// ability checks
// Ability checks
bool32 IsRolePlayBannedAbilityAtk(u16 ability)
{
u32 i;

679
src/battle_z_move.c Normal file
View File

@ -0,0 +1,679 @@
#include "global.h"
#include "malloc.h"
#include "battle.h"
#include "pokemon.h"
#include "battle_ai_main.h"
#include "battle_ai_util.h"
#include "battle_controllers.h"
#include "battle_interface.h"
#include "battle_message.h"
#include "battle_z_move.h"
#include "battle_scripts.h"
#include "graphics.h"
#include "sprite.h"
#include "window.h"
#include "string_util.h"
#include "text.h"
#include "item.h"
#include "strings.h"
#include "sound.h"
#include "constants/songs.h"
#include "decompress.h"
#include "task.h"
#include "util.h"
#include "gpu_regs.h"
#include "battle_message.h"
#include "pokedex.h"
#include "palette.h"
#include "international_string_util.h"
#include "safari_zone.h"
#include "battle_anim.h"
#include "constants/battle_anim.h"
#include "constants/rgb.h"
#include "battle_debug.h"
#include "constants/battle_config.h"
#include "data.h"
#include "pokemon_summary_screen.h"
#include "constants/songs.h"
#include "constants/items.h"
#include "constants/species.h"
#include "constants/hold_effects.h"
#include "constants/battle_string_ids.h"
#include "constants/battle_move_effects.h"
#include "constants/abilities.h"
#include "constants/moves.h"
#define STAT_STAGE(battler, stat) (gBattleMons[battler].statStages[stat - 1])
// Function Declarations
static void SpriteCB_ZMoveTrigger(struct Sprite *sprite);
static u16 GetSignatureZMove(u16 move, u16 species, u16 item);
static u16 GetTypeBasedZMove(u16 move, u8 battler);
static void ZMoveSelectionDisplayPpNumber(void);
static void ZMoveSelectionDisplayPower(u16 move, u16 zMove);
static void ShowZMoveTriggerSprite(void);
static bool32 AreStatsMaxed(u8 battlerId, u8 n);
static u8 GetZMoveScore(u8 battlerAtk, u8 battlerDef, u16 baseMove, u16 zMove);
// Const Data
static const struct SignatureZMove sSignatureZMoves[] =
{
#ifdef POKEMON_EXPANSION
{SPECIES_PIKACHU_COSPLAY, ITEM_PIKANIUM_Z, MOVE_VOLT_TACKLE, MOVE_CATASTROPIKA},
{SPECIES_PIKACHU_ROCK_STAR, ITEM_PIKANIUM_Z, MOVE_VOLT_TACKLE, MOVE_CATASTROPIKA},
{SPECIES_PIKACHU_BELLE, ITEM_PIKANIUM_Z, MOVE_VOLT_TACKLE, MOVE_CATASTROPIKA},
{SPECIES_PIKACHU_POP_STAR, ITEM_PIKANIUM_Z, MOVE_VOLT_TACKLE, MOVE_CATASTROPIKA},
{SPECIES_PIKACHU_PH_D, ITEM_PIKANIUM_Z, MOVE_VOLT_TACKLE, MOVE_CATASTROPIKA},
{SPECIES_PIKACHU_LIBRE, ITEM_PIKANIUM_Z, MOVE_VOLT_TACKLE, MOVE_CATASTROPIKA},
{SPECIES_RAICHU_ALOLAN, ITEM_ALORAICHIUM_Z, MOVE_THUNDERBOLT, MOVE_STOKED_SPARKSURFER},
{SPECIES_DECIDUEYE, ITEM_DECIDIUM_Z, MOVE_SPIRIT_SHACKLE, MOVE_SINISTER_ARROW_RAID},
{SPECIES_INCINEROAR, ITEM_INCINIUM_Z, MOVE_DARKEST_LARIAT, MOVE_MALICIOUS_MOONSAULT},
{SPECIES_KOMMO_O, ITEM_KOMMONIUM_Z, MOVE_CLANGING_SCALES, MOVE_CLANGOROUS_SOULBLAZE},
{SPECIES_LUNALA, ITEM_LUNALIUM_Z, MOVE_MOONGEIST_BEAM, MOVE_MENACING_MOONRAZE_MAELSTROM},
{SPECIES_NECROZMA_DAWN_WINGS, ITEM_LUNALIUM_Z, MOVE_MOONGEIST_BEAM, MOVE_MENACING_MOONRAZE_MAELSTROM},
{SPECIES_LYCANROC, ITEM_LYCANIUM_Z, MOVE_STONE_EDGE, MOVE_SPLINTERED_STORMSHARDS},
{SPECIES_LYCANROC_MIDNIGHT, ITEM_LYCANIUM_Z, MOVE_STONE_EDGE, MOVE_SPLINTERED_STORMSHARDS},
{SPECIES_LYCANROC_DUSK, ITEM_LYCANIUM_Z, MOVE_STONE_EDGE, MOVE_SPLINTERED_STORMSHARDS},
{SPECIES_MARSHADOW, ITEM_MARSHADIUM_Z, MOVE_SPECTRAL_THIEF, MOVE_SOUL_STEALING_7_STAR_STRIKE},
{SPECIES_MIMIKYU, ITEM_MIMIKIUM_Z, MOVE_PLAY_ROUGH, MOVE_LETS_SNUGGLE_FOREVER},
{SPECIES_MIMIKYU_BUSTED, ITEM_MIMIKIUM_Z, MOVE_PLAY_ROUGH, MOVE_LETS_SNUGGLE_FOREVER},
{SPECIES_PIKACHU_ORIGINAL_CAP, ITEM_PIKASHUNIUM_Z, MOVE_THUNDERBOLT, MOVE_10000000_VOLT_THUNDERBOLT},
{SPECIES_PIKACHU_HOENN_CAP, ITEM_PIKASHUNIUM_Z, MOVE_THUNDERBOLT, MOVE_10000000_VOLT_THUNDERBOLT},
{SPECIES_PIKACHU_SINNOH_CAP, ITEM_PIKASHUNIUM_Z, MOVE_THUNDERBOLT, MOVE_10000000_VOLT_THUNDERBOLT},
{SPECIES_PIKACHU_UNOVA_CAP, ITEM_PIKASHUNIUM_Z, MOVE_THUNDERBOLT, MOVE_10000000_VOLT_THUNDERBOLT},
{SPECIES_PIKACHU_KALOS_CAP, ITEM_PIKASHUNIUM_Z, MOVE_THUNDERBOLT, MOVE_10000000_VOLT_THUNDERBOLT},
{SPECIES_PIKACHU_ALOLA_CAP, ITEM_PIKASHUNIUM_Z, MOVE_THUNDERBOLT, MOVE_10000000_VOLT_THUNDERBOLT},
{SPECIES_PIKACHU_PARTNER_CAP, ITEM_PIKASHUNIUM_Z, MOVE_THUNDERBOLT, MOVE_10000000_VOLT_THUNDERBOLT},
{SPECIES_PIKACHU_WORLD_CAP, ITEM_PIKASHUNIUM_Z, MOVE_THUNDERBOLT, MOVE_10000000_VOLT_THUNDERBOLT},
{SPECIES_PRIMARINA, ITEM_PRIMARIUM_Z, MOVE_SPARKLING_ARIA, MOVE_OCEANIC_OPERETTA},
{SPECIES_SOLGALEO, ITEM_SOLGANIUM_Z, MOVE_SUNSTEEL_STRIKE, MOVE_SEARING_SUNRAZE_SMASH},
{SPECIES_NECROZMA_DUSK_MANE, ITEM_SOLGANIUM_Z, MOVE_SUNSTEEL_STRIKE, MOVE_SEARING_SUNRAZE_SMASH},
{SPECIES_TAPU_KOKO, ITEM_TAPUNIUM_Z, MOVE_NATURES_MADNESS, MOVE_GUARDIAN_OF_ALOLA},
{SPECIES_TAPU_BULU, ITEM_TAPUNIUM_Z, MOVE_NATURES_MADNESS, MOVE_GUARDIAN_OF_ALOLA},
{SPECIES_TAPU_LELE, ITEM_TAPUNIUM_Z, MOVE_NATURES_MADNESS, MOVE_GUARDIAN_OF_ALOLA},
{SPECIES_TAPU_FINI, ITEM_TAPUNIUM_Z, MOVE_NATURES_MADNESS, MOVE_GUARDIAN_OF_ALOLA},
{SPECIES_NECROZMA_ULTRA, ITEM_ULTRANECROZIUM_Z, MOVE_PHOTON_GEYSER, MOVE_LIGHT_THAT_BURNS_THE_SKY},
#endif
{SPECIES_MEW, ITEM_MEWNIUM_Z, MOVE_PSYCHIC, MOVE_GENESIS_SUPERNOVA},
{SPECIES_PIKACHU, ITEM_PIKANIUM_Z, MOVE_VOLT_TACKLE, MOVE_CATASTROPIKA},
{SPECIES_EEVEE, ITEM_EEVIUM_Z, MOVE_LAST_RESORT, MOVE_EXTREME_EVOBOOST},
{SPECIES_SNORLAX, ITEM_SNORLIUM_Z, MOVE_GIGA_IMPACT, MOVE_PULVERIZING_PANCAKE},
};
static const u8 sText_ResetStats[] = _("Reset Lowered Stats");
static const u8 sText_StatsPlus[] = _("+ All Stats");
static const u8 sText_StatsPlus2[] = _("++ All Stats");
static const u8 sText_CritHitsPlus[] = _("+ Critical Hit Chance");
static const u8 sText_FollowMe[] = _("Follow Me");
static const u8 sText_RecoverHP[] = _("Recover HP");
static const u8 sText_HealAllyHP[] = _("Heal Replacement HP");
static const u8 sText_PowerColon[] = _("Power: ");
static const u32 sZMoveTriggerGfx[] = INCBIN_U32("graphics/battle_interface/z_move_trigger.4bpp.lz");
static const u16 sZMoveTriggerPal[] = INCBIN_U16("graphics/battle_interface/z_move_trigger.gbapal");
static const struct CompressedSpriteSheet sSpriteSheet_ZMoveTrigger = {
sZMoveTriggerGfx, (32 * 32) / 2, TAG_ZMOVE_TRIGGER_TILE
};
static const struct SpritePalette sSpritePalette_ZMoveTrigger = {
sZMoveTriggerPal, TAG_ZMOVE_TRIGGER_PAL
};
static const struct OamData sOamData_ZMoveTrigger =
{
.affineMode = ST_OAM_AFFINE_OFF,
.objMode = ST_OAM_OBJ_NORMAL,
.shape = SPRITE_SHAPE(32x32),
.size = SPRITE_SIZE(32x32),
.priority = 1,
};
static const struct SpriteTemplate sSpriteTemplate_ZMoveTrigger =
{
.tileTag = TAG_ZMOVE_TRIGGER_TILE,
.paletteTag = TAG_ZMOVE_TRIGGER_PAL,
.oam = &sOamData_ZMoveTrigger,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCB_ZMoveTrigger
};
// Functions
bool8 IsZMove(u16 move)
{
return move >= FIRST_Z_MOVE && move <= LAST_Z_MOVE;
}
void QueueZMove(u8 battlerId, u16 baseMove)
{
gBattleStruct->zmove.toBeUsed[battlerId] = gBattleStruct->zmove.chosenZMove;
gBattleStruct->zmove.baseMoves[battlerId] = baseMove;
if (gBattleStruct->zmove.chosenZMove == MOVE_LIGHT_THAT_BURNS_THE_SKY)
gBattleStruct->zmove.splits[battlerId] = GetSplitBasedOnStats(battlerId);
else
gBattleStruct->zmove.splits[battlerId] = gBattleMoves[baseMove].split;
}
bool32 IsViableZMove(u8 battlerId, u16 move)
{
struct Pokemon *mon;
struct MegaEvolutionData *mega = &(((struct ChooseMoveStruct*)(&gBattleResources->bufferA[gActiveBattler][4]))->mega);
u8 battlerPosition = GetBattlerPosition(battlerId);
u8 partnerPosition = GetBattlerPosition(BATTLE_PARTNER(battlerId));
u32 item;
u16 holdEffect;
u16 species;
if (gBattleStruct->zmove.used[battlerId])
return FALSE;
species = gBattleMons[battlerId].species;
item = gBattleMons[battlerId].item;
if (gBattleTypeFlags & (BATTLE_TYPE_SAFARI | BATTLE_TYPE_WALLY_TUTORIAL | BATTLE_TYPE_FRONTIER))
return FALSE;
#ifdef ITEM_Z_RING
if ((GetBattlerPosition(battlerId) == B_POSITION_PLAYER_LEFT || (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) && GetBattlerPosition(battlerId) == B_POSITION_PLAYER_RIGHT)) && !CheckBagHasItem(ITEM_Z_RING, 1))
return FALSE;
#endif
if (mega->alreadyEvolved[battlerPosition])
return FALSE; // Trainer has mega evolved
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
if (IsPartnerMonFromSameTrainer(battlerId) && (mega->alreadyEvolved[partnerPosition] || (mega->toEvolve & gBitTable[BATTLE_PARTNER(battlerId)])))
return FALSE; // Partner has mega evolved or is about to mega evolve
}
if (B_ENABLE_DEBUG && gBattleStruct->debugHoldEffects[battlerId])
holdEffect = gBattleStruct->debugHoldEffects[battlerId];
else if (item == ITEM_ENIGMA_BERRY)
return FALSE; // HoldEffect = gEnigmaBerries[battlerId].holdEffect;
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)
{
gBattleStruct->zmove.chosenZMove = zMove; // Signature z move exists
return TRUE;
}
if (move != MOVE_NONE && zMove != MOVE_Z_STATUS && gBattleMoves[move].type == ItemId_GetSecondaryId(item))
{
if (IS_MOVE_STATUS(gBattleMoves[move].split))
gBattleStruct->zmove.chosenZMove = move;
else
gBattleStruct->zmove.chosenZMove = GetTypeBasedZMove(move, battlerId);
return TRUE;
}
}
return FALSE;
}
void GetUsableZMoves(u8 battlerId, u16 *moves)
{
u32 i;
gBattleStruct->zmove.possibleZMoves[battlerId] = 0;
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (moves[i] != MOVE_NONE && IsViableZMove(battlerId, moves[i]))
gBattleStruct->zmove.possibleZMoves[battlerId] |= (1 << i);
}
}
bool32 IsZMoveUsable(u8 battlerId, u16 moveIndex)
{
if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && IsPartnerMonFromSameTrainer(battlerId) && gBattleStruct->zmove.toBeUsed[BATTLE_PARTNER(battlerId)] != MOVE_NONE)
return FALSE; // Player's other mon has a z move queued up already
if (gBattleStruct->zmove.possibleZMoves[battlerId] & (1 << moveIndex))
return TRUE;
return FALSE;
}
bool32 TryChangeZIndicator(u8 battlerId, u8 moveIndex)
{
bool32 viableZMove = IsZMoveUsable(battlerId, moveIndex);
if (gBattleStruct->zmove.viable && !viableZMove)
HideZMoveTriggerSprite(); // Was a viable z move, now is not -> slide out
else if (!gBattleStruct->zmove.viable && viableZMove)
ShowZMoveTriggerSprite(); // Was not a viable z move, now is -> slide back in
}
#define SINGLES_Z_TRIGGER_POS_X_OPTIMAL (29)
#define SINGLES_Z_TRIGGER_POS_X_PRIORITY (29)
#define SINGLES_Z_TRIGGER_POS_X_SLIDE (15)
#define SINGLES_Z_TRIGGER_POS_Y_DIFF (-10)
#define DOUBLES_Z_TRIGGER_POS_X_OPTIMAL SINGLES_Z_TRIGGER_POS_X_OPTIMAL
#define DOUBLES_Z_TRIGGER_POS_X_PRIORITY SINGLES_Z_TRIGGER_POS_X_PRIORITY
#define DOUBLES_Z_TRIGGER_POS_X_SLIDE SINGLES_Z_TRIGGER_POS_X_SLIDE
#define DOUBLES_Z_TRIGGER_POS_Y_DIFF (-4)
#define tBattler data[0]
#define tHide data[1]
void CreateZMoveTriggerSprite(u8 battlerId, bool8 viable)
{
s16 x, y;
LoadSpritePalette(&sSpritePalette_ZMoveTrigger);
if (GetSpriteTileStartByTag(TAG_ZMOVE_TRIGGER_TILE) == 0xFFFF)
LoadCompressedSpriteSheetUsingHeap(&sSpriteSheet_ZMoveTrigger);
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
x = gSprites[gHealthboxSpriteIds[battlerId]].x - DOUBLES_Z_TRIGGER_POS_X_SLIDE;
y = gSprites[gHealthboxSpriteIds[battlerId]].y - DOUBLES_Z_TRIGGER_POS_Y_DIFF;
}
else
{
x = gSprites[gHealthboxSpriteIds[battlerId]].x - SINGLES_Z_TRIGGER_POS_X_SLIDE;
y = gSprites[gHealthboxSpriteIds[battlerId]].y - SINGLES_Z_TRIGGER_POS_Y_DIFF, 0;
}
if (gBattleStruct->zmove.triggerSpriteId == 0xFF)
gBattleStruct->zmove.triggerSpriteId = CreateSprite(&sSpriteTemplate_ZMoveTrigger, x, y, 0);
gSprites[gBattleStruct->zmove.triggerSpriteId].tBattler = battlerId;
gSprites[gBattleStruct->zmove.triggerSpriteId].tHide = (viable == TRUE) ? FALSE : TRUE;
}
static void SpriteCB_ZMoveTrigger(struct Sprite *sprite)
{
s32 xSlide, xPriority, xOptimal;
s32 yDiff;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
xSlide = DOUBLES_Z_TRIGGER_POS_X_SLIDE;
xPriority = DOUBLES_Z_TRIGGER_POS_X_PRIORITY;
xOptimal = DOUBLES_Z_TRIGGER_POS_X_OPTIMAL;
yDiff = DOUBLES_Z_TRIGGER_POS_Y_DIFF;
}
else
{
xSlide = SINGLES_Z_TRIGGER_POS_X_SLIDE;
xPriority = SINGLES_Z_TRIGGER_POS_X_PRIORITY;
xOptimal = SINGLES_Z_TRIGGER_POS_X_OPTIMAL;
yDiff = SINGLES_Z_TRIGGER_POS_Y_DIFF;
}
if (sprite->tHide)
{
if (sprite->x != gSprites[gHealthboxSpriteIds[sprite->tBattler]].x - xSlide)
sprite->x++;
if (sprite->x >= gSprites[gHealthboxSpriteIds[sprite->tBattler]].x - xPriority)
sprite->oam.priority = 2;
else
sprite->oam.priority = 1;
sprite->y = gSprites[gHealthboxSpriteIds[sprite->tBattler]].y - yDiff;
sprite->y2 = gSprites[gHealthboxSpriteIds[sprite->tBattler]].y2 - yDiff;
if (sprite->x == gSprites[gHealthboxSpriteIds[sprite->tBattler]].x - xSlide)
DestroyZMoveTriggerSprite();
}
else
{
if (sprite->x != gSprites[gHealthboxSpriteIds[sprite->tBattler]].x - xOptimal)
{
sprite->x--;
sprite->oam.priority = 2;
}
else
{
sprite->oam.priority = 1;
}
sprite->y = gSprites[gHealthboxSpriteIds[sprite->tBattler]].y - yDiff;
sprite->y2 = gSprites[gHealthboxSpriteIds[sprite->tBattler]].y2 - yDiff;
}
}
bool32 IsZMoveTriggerSpriteActive(void)
{
if (GetSpriteTileStartByTag(TAG_ZMOVE_TRIGGER_TILE) == 0xFFFF)
return FALSE;
else if (IndexOfSpritePaletteTag(TAG_ZMOVE_TRIGGER_PAL) != 0xFF)
return TRUE;
else
return FALSE;
}
void HideZMoveTriggerSprite(void)
{
struct Sprite *sprite = &gSprites[gBattleStruct->zmove.triggerSpriteId];
sprite->tHide = TRUE;
gBattleStruct->zmove.viable = FALSE;
}
static void ShowZMoveTriggerSprite(void)
{
struct Sprite *sprite = &gSprites[gBattleStruct->zmove.triggerSpriteId];
gBattleStruct->zmove.viable = TRUE;
CreateZMoveTriggerSprite(sprite->tBattler, TRUE);
}
void DestroyZMoveTriggerSprite(void)
{
FreeSpritePaletteByTag(TAG_ZMOVE_TRIGGER_PAL);
FreeSpriteTilesByTag(TAG_ZMOVE_TRIGGER_TILE);
if (gBattleStruct->zmove.triggerSpriteId != 0xFF)
DestroySprite(&gSprites[gBattleStruct->zmove.triggerSpriteId]);
gBattleStruct->zmove.triggerSpriteId = 0xFF;
}
static u16 GetSignatureZMove(u16 move, u16 species, u16 item)
{
u32 i;
// Check signature z move
for (i = 0; i < ARRAY_COUNT(sSignatureZMoves); ++i)
{
if (sSignatureZMoves[i].item == item && sSignatureZMoves[i].species == species && sSignatureZMoves[i].move == move)
return sSignatureZMoves[i].zmove;
}
return MOVE_NONE;
}
static u16 GetTypeBasedZMove(u16 move, u8 battler)
{
u8 moveType = gBattleMoves[move].type;
// Get z move from type
if (moveType < TYPE_FIRE)
return MOVE_BREAKNECK_BLITZ + moveType;
else if (moveType >= TYPE_FAIRY)
return MOVE_TWINKLE_TACKLE + (moveType - TYPE_FAIRY);
else
return MOVE_BREAKNECK_BLITZ + (moveType - 1);
}
bool32 MoveSelectionDisplayZMove(u16 zmove)
{
u32 i;
struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct*)(&gBattleResources->bufferA[gActiveBattler][4]);
u16 move = moveInfo->moves[gMoveSelectionCursor[gActiveBattler]];
PlaySE(SE_SELECT);
gBattleStruct->zmove.viewing = TRUE;
if (zmove != MOVE_NONE)
{
// Clear move slots
for (i = 0; i < MAX_MON_MOVES; ++i)
{
MoveSelectionDestroyCursorAt(i);
StringCopy(gDisplayedStringBattle, gText_EmptyString2);
BattlePutTextOnWindow(gDisplayedStringBattle, i + 3);
}
if (IS_MOVE_STATUS(move))
{
u8 zEffect = gBattleMoves[move].zMoveEffect;
gDisplayedStringBattle[0] = EOS;
if (zEffect == Z_EFFECT_CURSE)
{
if (moveInfo->monType1 == TYPE_GHOST || moveInfo->monType2 == TYPE_GHOST || moveInfo->monType3 == TYPE_GHOST)
zEffect = Z_EFFECT_RECOVER_HP;
else
zEffect = Z_EFFECT_ATK_UP_1;
}
switch (zEffect)
{
case Z_EFFECT_RESET_STATS:
StringCopy(gDisplayedStringBattle, sText_ResetStats);
break;
case Z_EFFECT_ALL_STATS_UP_1:
StringCopy(gDisplayedStringBattle, sText_StatsPlus);
break;
case Z_EFFECT_BOOST_CRITS:
StringCopy(gDisplayedStringBattle, sText_CritHitsPlus);
break;
case Z_EFFECT_FOLLOW_ME:
StringCopy(gDisplayedStringBattle, sText_FollowMe);
break;
case Z_EFFECT_RECOVER_HP:
StringCopy(gDisplayedStringBattle, sText_RecoverHP);
break;
case Z_EFFECT_RESTORE_REPLACEMENT_HP:
StringCopy(gDisplayedStringBattle, sText_HealAllyHP);
break;
case Z_EFFECT_ATK_UP_1:
case Z_EFFECT_DEF_UP_1:
case Z_EFFECT_SPD_UP_1:
case Z_EFFECT_SPATK_UP_1:
case Z_EFFECT_SPDEF_UP_1:
case Z_EFFECT_ACC_UP_1:
case Z_EFFECT_EVSN_UP_1:
gDisplayedStringBattle[0] = CHAR_PLUS;
gDisplayedStringBattle[1] = 0;
gDisplayedStringBattle[2] = EOS;
PREPARE_STAT_BUFFER(gBattleTextBuff1, zEffect - Z_EFFECT_ATK_UP_1 + 1);
ExpandBattleTextBuffPlaceholders(gBattleTextBuff1, gDisplayedStringBattle + 2);
break;
case Z_EFFECT_ATK_UP_2:
case Z_EFFECT_DEF_UP_2:
case Z_EFFECT_SPD_UP_2:
case Z_EFFECT_SPATK_UP_2:
case Z_EFFECT_SPDEF_UP_2:
case Z_EFFECT_ACC_UP_2:
case Z_EFFECT_EVSN_UP_2:
gDisplayedStringBattle[0] = CHAR_PLUS;
gDisplayedStringBattle[1] = CHAR_PLUS;
gDisplayedStringBattle[2] = 0;
gDisplayedStringBattle[3] = EOS;
PREPARE_STAT_BUFFER(gBattleTextBuff1, zEffect - Z_EFFECT_ATK_UP_2 + 1);
ExpandBattleTextBuffPlaceholders(gBattleTextBuff1, gDisplayedStringBattle + 3);
break;
case Z_EFFECT_ATK_UP_3:
case Z_EFFECT_DEF_UP_3:
case Z_EFFECT_SPD_UP_3:
case Z_EFFECT_SPATK_UP_3:
case Z_EFFECT_SPDEF_UP_3:
case Z_EFFECT_ACC_UP_3:
case Z_EFFECT_EVSN_UP_3:
gDisplayedStringBattle[0] = CHAR_PLUS;
gDisplayedStringBattle[1] = CHAR_PLUS;
gDisplayedStringBattle[2] = CHAR_PLUS;
gDisplayedStringBattle[3] = 0;
gDisplayedStringBattle[4] = EOS;
PREPARE_STAT_BUFFER(gBattleTextBuff1, zEffect - Z_EFFECT_ATK_UP_3 + 1);
ExpandBattleTextBuffPlaceholders(gBattleTextBuff1, gDisplayedStringBattle + 4);
break;
}
BattlePutTextOnWindow(gDisplayedStringBattle, 5); // Slot of Move 3
gDisplayedStringBattle[0] = CHAR_Z;
gDisplayedStringBattle[1] = CHAR_HYPHEN;
StringCopy(gDisplayedStringBattle + 2, gMoveNames[move]);
}
else if (zmove == MOVE_EXTREME_EVOBOOST)
{
// Damaging move -> status z move
StringCopy(gDisplayedStringBattle, sText_StatsPlus2);
BattlePutTextOnWindow(gDisplayedStringBattle, 5); // Slot of Move 3
StringCopy(gDisplayedStringBattle, GetZMoveName(zmove));
}
else
{
ZMoveSelectionDisplayPower(move, zmove);
StringCopy(gDisplayedStringBattle, GetZMoveName(zmove));
}
BattlePutTextOnWindow(gDisplayedStringBattle, 3); // First move slot
ZMoveSelectionDisplayPpNumber();
MoveSelectionCreateCursorAt(0, 0);
return TRUE;
}
return FALSE;
}
static void ZMoveSelectionDisplayPower(u16 move, u16 zMove)
{
u8 *txtPtr;
u16 power = gBattleMoves[move].zMovePower;
if (zMove >= MOVE_CATASTROPIKA)
power = gBattleMoves[zMove].power;
if (gBattleMoves[move].split != SPLIT_STATUS)
{
txtPtr = StringCopy(gDisplayedStringBattle, sText_PowerColon);
ConvertIntToDecimalStringN(txtPtr, power, STR_CONV_MODE_LEFT_ALIGN, 3);
BattlePutTextOnWindow(gDisplayedStringBattle, 5); // Bottom left
}
}
static void ZMoveSelectionDisplayPpNumber(void)
{
u8 *txtPtr;
struct ChooseMoveStruct *moveInfo;
if (gBattleResources->bufferA[gActiveBattler][2] == TRUE) // Check if we didn't want to display pp number
return;
SetPpNumbersPaletteInMoveSelection();
moveInfo = (struct ChooseMoveStruct*)(&gBattleResources->bufferA[gActiveBattler][4]);
txtPtr = ConvertIntToDecimalStringN(gDisplayedStringBattle, 1, STR_CONV_MODE_RIGHT_ALIGN, 2);
*(txtPtr)++ = CHAR_SLASH;
ConvertIntToDecimalStringN(txtPtr, 1, STR_CONV_MODE_RIGHT_ALIGN, 2);
BattlePutTextOnWindow(gDisplayedStringBattle, 9);
}
const u8* GetZMoveName(u16 move)
{
if (IsZMove(move))
return gZMoveNames[move - FIRST_Z_MOVE];
else
return gZMoveNames[0]; // Failsafe
}
#define Z_EFFECT_BS_LENGTH 3
// This function kinda cheats by setting a return battle script to after the setzeffect various command
// and then jumping to a z effect script
void SetZEffect(void)
{
u32 i;
gBattleStruct->zmove.zStatusActive = TRUE;
if (gBattleStruct->zmove.effect == Z_EFFECT_CURSE)
{
if (IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST))
gBattleStruct->zmove.effect = Z_EFFECT_RECOVER_HP;
else
gBattleStruct->zmove.effect = Z_EFFECT_ATK_UP_1;
}
gBattleScripting.savedStatChanger = gBattleScripting.statChanger; // Save used move's stat changer (e.g. for Z-Growl)
gBattleScripting.battler = gBattlerAttacker;
switch (gBattleStruct->zmove.effect)
{
case Z_EFFECT_RESET_STATS:
for (i = 0; i < NUM_BATTLE_STATS - 1; i++)
{
if (gBattleMons[gBattlerAttacker].statStages[i] < DEFAULT_STAT_STAGE)
gBattleMons[gBattlerAttacker].statStages[i] = DEFAULT_STAT_STAGE;
}
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_RESET_STATS;
BattleScriptPush(gBattlescriptCurrInstr + Z_EFFECT_BS_LENGTH);
gBattlescriptCurrInstr = BattleScript_ZEffectPrintString;
break;
case Z_EFFECT_ALL_STATS_UP_1:
if (!AreStatsMaxed(gBattlerAttacker, STAT_SPDEF))
{
for (i = 0; i < STAT_ACC - 1; i++) // Doesn't increase Acc or Evsn
{
if (gBattleMons[gBattlerAttacker].statStages[i] < 12)
++gBattleMons[gBattlerAttacker].statStages[i];
}
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_ALL_STATS_UP;
BattleScriptPush(gBattlescriptCurrInstr + Z_EFFECT_BS_LENGTH);
gBattlescriptCurrInstr = BattleScript_ZEffectPrintString;
}
break;
case Z_EFFECT_BOOST_CRITS:
if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_FOCUS_ENERGY))
{
gBattleMons[gBattlerAttacker].status2 |= STATUS2_FOCUS_ENERGY;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_BOOST_CRITS;
BattleScriptPush(gBattlescriptCurrInstr + Z_EFFECT_BS_LENGTH);
gBattlescriptCurrInstr = BattleScript_ZEffectPrintString;
}
break;
case Z_EFFECT_FOLLOW_ME:
gSideTimers[GetBattlerSide(gBattlerAttacker)].followmeTimer = 1;
gSideTimers[GetBattlerSide(gBattlerAttacker)].followmeTarget = gBattlerAttacker;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_FOLLOW_ME;
BattleScriptPush(gBattlescriptCurrInstr + Z_EFFECT_BS_LENGTH);
gBattlescriptCurrInstr = BattleScript_ZEffectPrintString;
break;
case Z_EFFECT_RECOVER_HP:
if (gBattleMons[gBattlerAttacker].hp != gBattleMons[gBattlerAttacker].maxHP)
{
gBattleMoveDamage = (-1) * gBattleMons[gBattlerAttacker].maxHP;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_RECOVER_HP;
BattleScriptPush(gBattlescriptCurrInstr + Z_EFFECT_BS_LENGTH);
gBattlescriptCurrInstr = BattleScript_RecoverHPZMove;
}
break;
case Z_EFFECT_RESTORE_REPLACEMENT_HP:
gBattleStruct->zmove.healReplacement = TRUE;
BattleScriptPush(gBattlescriptCurrInstr + Z_EFFECT_BS_LENGTH);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_HP_TRAP;
gBattlescriptCurrInstr = BattleScript_ZEffectPrintString;
break;
case Z_EFFECT_ATK_UP_1 ... Z_EFFECT_EVSN_UP_1:
SET_STATCHANGER(gBattleStruct->zmove.effect - Z_EFFECT_ATK_UP_1 + 1, 1, FALSE);
BattleScriptPush(gBattlescriptCurrInstr + Z_EFFECT_BS_LENGTH);
gBattlescriptCurrInstr = BattleScript_StatUpZMove;
break;
case Z_EFFECT_ATK_UP_2 ... Z_EFFECT_EVSN_UP_2:
SET_STATCHANGER(gBattleStruct->zmove.effect - Z_EFFECT_ATK_UP_2 + 1, 2, FALSE);
BattleScriptPush(gBattlescriptCurrInstr + Z_EFFECT_BS_LENGTH);
gBattlescriptCurrInstr = BattleScript_StatUpZMove;
break;
case Z_EFFECT_ATK_UP_3 ... Z_EFFECT_EVSN_UP_3:
SET_STATCHANGER(gBattleStruct->zmove.effect - Z_EFFECT_ATK_UP_3 + 1, 3, FALSE);
BattleScriptPush(gBattlescriptCurrInstr + Z_EFFECT_BS_LENGTH);
gBattlescriptCurrInstr = BattleScript_StatUpZMove;
break;
default:
gBattlescriptCurrInstr += 3;
break;
}
gBattleStruct->zmove.zStatusActive = FALSE;
}
static bool32 AreStatsMaxed(u8 battlerId, u8 n)
{
u32 i;
for (i = STAT_ATK; i <= n; i++)
{
if (STAT_STAGE(battlerId, i) < MAX_STAT_STAGE)
return FALSE;
}
return TRUE;
}

File diff suppressed because it is too large Load Diff

View File

@ -757,3 +757,78 @@ const u8 gMoveNames[MOVES_COUNT][MOVE_NAME_LENGTH + 1] =
[MOVE_ASTRAL_BARRAGE] = _("AstrlBarrage"),
[MOVE_EERIE_SPELL] = _("Eerie Spell"),
};
static const u8 sText_Breakneck_Blitz[] = _("Breakneck Blitz");
static const u8 sText_All_Out_Pummeling[] = _("All Out Pummeling");
static const u8 sText_Supersonic_Skystrike[] = _("Supersonic Skystrike");
static const u8 sText_Acid_Downpour[] = _("Acid Downpour");
static const u8 sText_Tectonic_Rage[] = _("Tectonic Rage");
static const u8 sText_Continental_Crush[] = _("Continental Crush");
static const u8 sText_Savage_Spin_Out[] = _("Savage Spin Out");
static const u8 sText_Never_Ending_Nightmare[] = _("Never Ending Nightmare");
static const u8 sText_Corkscrew_Crash[] = _("Corkscrew Crash");
static const u8 sText_Inferno_Overdrive[] = _("Inferno Overdrive");
static const u8 sText_Hydro_Vortex[] = _("Hydro Vortex");
static const u8 sText_Bloom_Doom[] = _("Bloom Doom");
static const u8 sText_Gigavolt_Havoc[] = _("Gigavolt Havoc");
static const u8 sText_Shattered_Psyche[] = _("Shattered Psyche");
static const u8 sText_Subzero_Slammer[] = _("Subzero Slammer");
static const u8 sText_Devastating_Drake[] = _("Devastating Drake");
static const u8 sText_Black_Hole_Eclipse[] = _("Black Hole Eclipse");
static const u8 sText_Twinkle_Tackle[] = _("Twinkle Tackle");
static const u8 sText_Catastropika[] = _("Catastropika");
static const u8 sText_10000000_Volt_Thunderbolt[] = _("10000000 Volt Thunderbolt");
static const u8 sText_Stoked_Sparksurfer[] = _("Stoked Sparksurfer");
static const u8 sText_Extreme_Evoboost[] = _("Extreme Evoboost");
static const u8 sText_Pulverizing_Pancake[] = _("Pulverizing Pancake");
static const u8 sText_Genesis_Supernova[] = _("Genesis Supernova");
static const u8 sText_Sinister_Arrow_Raid[] = _("Sinister Arrow Raid");
static const u8 sText_Malicious_Moonsault[] = _("Malicious Moonsault");
static const u8 sText_Oceanic_Operetta[] = _("Oceanic Operetta");
static const u8 sText_Splintered_Stormshards[] = _("Splintered Stormshards");
static const u8 sText_Lets_Snuggle_Forever[] = _("Let's Snuggle Forever");
static const u8 sText_Clangorous_Soulblaze[] = _("Clangorous Soulblaze");
static const u8 sText_Guardian_Of_Alola[] = _("Guardian Of Alola");
static const u8 sText_Searing_Sunraze_Smash[] = _("Searing Sunraze Smash");
static const u8 sText_Menacing_Moonraze_Maelstrom[] = _("Menacing Moonraze Maelstrom");
static const u8 sText_Light_That_Burns_The_Sky[] = _("Light That Burns The Sky");
static const u8 sText_Soul_Stealing_7_Star_Strike[] = _("Soul Stealing 7 Star Strike");
const u8 *const gZMoveNames[] =
{
[MOVE_BREAKNECK_BLITZ - FIRST_Z_MOVE] = sText_Breakneck_Blitz,
[MOVE_ALL_OUT_PUMMELING - FIRST_Z_MOVE] = sText_All_Out_Pummeling,
[MOVE_SUPERSONIC_SKYSTRIKE - FIRST_Z_MOVE] = sText_Supersonic_Skystrike,
[MOVE_ACID_DOWNPOUR - FIRST_Z_MOVE] = sText_Acid_Downpour,
[MOVE_TECTONIC_RAGE - FIRST_Z_MOVE] = sText_Tectonic_Rage,
[MOVE_CONTINENTAL_CRUSH - FIRST_Z_MOVE] = sText_Continental_Crush,
[MOVE_SAVAGE_SPIN_OUT - FIRST_Z_MOVE] = sText_Savage_Spin_Out,
[MOVE_NEVER_ENDING_NIGHTMARE - FIRST_Z_MOVE] = sText_Never_Ending_Nightmare,
[MOVE_CORKSCREW_CRASH - FIRST_Z_MOVE] = sText_Corkscrew_Crash,
[MOVE_INFERNO_OVERDRIVE - FIRST_Z_MOVE] = sText_Inferno_Overdrive,
[MOVE_HYDRO_VORTEX - FIRST_Z_MOVE] = sText_Hydro_Vortex,
[MOVE_BLOOM_DOOM - FIRST_Z_MOVE] = sText_Bloom_Doom,
[MOVE_GIGAVOLT_HAVOC - FIRST_Z_MOVE] = sText_Gigavolt_Havoc,
[MOVE_SHATTERED_PSYCHE - FIRST_Z_MOVE] = sText_Shattered_Psyche,
[MOVE_SUBZERO_SLAMMER - FIRST_Z_MOVE] = sText_Subzero_Slammer,
[MOVE_DEVASTATING_DRAKE - FIRST_Z_MOVE] = sText_Devastating_Drake,
[MOVE_BLACK_HOLE_ECLIPSE - FIRST_Z_MOVE] = sText_Black_Hole_Eclipse,
[MOVE_TWINKLE_TACKLE - FIRST_Z_MOVE] = sText_Twinkle_Tackle,
[MOVE_CATASTROPIKA - FIRST_Z_MOVE] = sText_Catastropika,
[MOVE_10000000_VOLT_THUNDERBOLT - FIRST_Z_MOVE] = sText_10000000_Volt_Thunderbolt,
[MOVE_STOKED_SPARKSURFER - FIRST_Z_MOVE] = sText_Stoked_Sparksurfer,
[MOVE_EXTREME_EVOBOOST - FIRST_Z_MOVE] = sText_Extreme_Evoboost,
[MOVE_PULVERIZING_PANCAKE - FIRST_Z_MOVE] = sText_Pulverizing_Pancake,
[MOVE_GENESIS_SUPERNOVA - FIRST_Z_MOVE] = sText_Genesis_Supernova,
[MOVE_SINISTER_ARROW_RAID - FIRST_Z_MOVE] = sText_Sinister_Arrow_Raid,
[MOVE_MALICIOUS_MOONSAULT - FIRST_Z_MOVE] = sText_Malicious_Moonsault,
[MOVE_OCEANIC_OPERETTA - FIRST_Z_MOVE] = sText_Oceanic_Operetta,
[MOVE_SPLINTERED_STORMSHARDS - FIRST_Z_MOVE] = sText_Splintered_Stormshards,
[MOVE_LETS_SNUGGLE_FOREVER - FIRST_Z_MOVE] = sText_Lets_Snuggle_Forever,
[MOVE_CLANGOROUS_SOULBLAZE - FIRST_Z_MOVE] = sText_Clangorous_Soulblaze,
[MOVE_GUARDIAN_OF_ALOLA - FIRST_Z_MOVE] = sText_Guardian_Of_Alola,
[MOVE_SEARING_SUNRAZE_SMASH - FIRST_Z_MOVE] = sText_Searing_Sunraze_Smash,
[MOVE_MENACING_MOONRAZE_MAELSTROM - FIRST_Z_MOVE] = sText_Menacing_Moonraze_Maelstrom,
[MOVE_LIGHT_THAT_BURNS_THE_SKY - FIRST_Z_MOVE] = sText_Light_That_Burns_The_Sky,
[MOVE_SOUL_STEALING_7_STAR_STRIKE - FIRST_Z_MOVE] = sText_Soul_Stealing_7_Star_Strike,
};

View File

@ -948,25 +948,6 @@ u8 ItemId_GetSecondaryId(u16 itemId)
return gItems[SanitizeItemId(itemId)].secondaryId;
}
bool32 IsPinchBerryItemEffect(u16 holdEffect)
{
switch (holdEffect)
{
case HOLD_EFFECT_ATTACK_UP:
case HOLD_EFFECT_DEFENSE_UP:
case HOLD_EFFECT_SPEED_UP:
case HOLD_EFFECT_SP_ATTACK_UP:
case HOLD_EFFECT_SP_DEFENSE_UP:
case HOLD_EFFECT_CRITICAL_UP:
case HOLD_EFFECT_RANDOM_STAT_UP:
case HOLD_EFFECT_CUSTAP_BERRY:
case HOLD_EFFECT_MICLE_BERRY:
return TRUE;
}
return FALSE;
}
u8 ItemId_GetFlingPower(u16 itemId)
{
return gItems[SanitizeItemId(itemId)].flingPower;

View File

@ -9,6 +9,7 @@
#include "battle_pyramid.h"
#include "battle_setup.h"
#include "battle_tower.h"
#include "battle_z_move.h"
#include "data.h"
#include "event_data.h"
#include "evolution_scene.h"