mirror of
https://github.com/pret/pokefirered.git
synced 2026-09-30 12:59:43 -05:00
updated battle engine
This commit is contained in:
@@ -507,9 +507,9 @@
|
||||
.byte \battler
|
||||
.endm
|
||||
|
||||
.macro trainerslidein battler:req
|
||||
.macro trainerslidein position:req
|
||||
.byte 0x53
|
||||
.byte \battler
|
||||
.byte \position
|
||||
.endm
|
||||
|
||||
.macro playse song:req
|
||||
@@ -1674,14 +1674,62 @@
|
||||
callnative BS_FickleBeamDamageCalculation
|
||||
.endm
|
||||
|
||||
@ various command changed to more readable macros
|
||||
.macro cancelmultiturnmoves battler:req
|
||||
various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES
|
||||
.macro trytarshot failInstr:req
|
||||
callnative BS_TryTarShot
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
.macro jumpifteainvulnerable battler:req, jumpInstr:req
|
||||
callnative BS_TeatimeInvul
|
||||
.byte \battler
|
||||
.4byte \jumpInstr
|
||||
.endm
|
||||
|
||||
.macro jumpifteanoberry failInstr:req
|
||||
callnative BS_TeatimeTargets
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
.macro trywindriderpower battler:req, failInstr:req
|
||||
callnative BS_TryWindRiderPower
|
||||
.byte \battler
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
.macro activateweatherchangeabilities battler:req
|
||||
callnative BS_ActivateWeatherChangeAbilities
|
||||
.byte \battler
|
||||
.endm
|
||||
|
||||
.macro activateterrainchangeabilities battler:req
|
||||
callnative BS_ActivateTerrainChangeAbilities
|
||||
.byte \battler
|
||||
.endm
|
||||
|
||||
@ Stores Healing Wish effect.
|
||||
.macro storehealingwish battler:req
|
||||
various \battler, VARIOUS_STORE_HEALING_WISH
|
||||
callnative BS_StoreHealingWish
|
||||
.byte \battler
|
||||
.endm
|
||||
|
||||
.macro hitswitchtargetfailed
|
||||
callnative BS_HitSwitchTargetFailed
|
||||
.endm
|
||||
|
||||
.macro tryrevivalblessing, failInstr:req
|
||||
callnative BS_TryRevivalBlessing
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
.macro jumpifblockedbysoundproof battler:req, failInstr:req
|
||||
callnative BS_JumpIfBlockedBySoundproof
|
||||
.byte \battler
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
@ various command changed to more readable macros
|
||||
.macro cancelmultiturnmoves battler:req
|
||||
various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES
|
||||
.endm
|
||||
|
||||
.macro setmagiccoattarget battler:req
|
||||
@@ -2210,11 +2258,6 @@
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
.macro trytarshot battler:req, failInstr:req
|
||||
various \battler, VARIOUS_TRY_TAR_SHOT
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
.macro cantarshotwork battler:req, failInstr:req
|
||||
various \battler, VARIOUS_CAN_TAR_SHOT_WORK
|
||||
.4byte \failInstr
|
||||
@@ -2230,16 +2273,6 @@
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
.macro jumpifteanoberry jumpInstr:req
|
||||
various BS_ATTACKER, VARIOUS_TEATIME_TARGETS
|
||||
.4byte \jumpInstr
|
||||
.endm
|
||||
|
||||
.macro jumpifteainvulnerable battler:req, jumpInstr:req
|
||||
various \battler, VARIOUS_TEATIME_INVUL
|
||||
.4byte \jumpInstr
|
||||
.endm
|
||||
|
||||
.macro curecertainstatuses battler:req
|
||||
various \battler, VARIOUS_CURE_CERTAIN_STATUSES
|
||||
.endm
|
||||
@@ -2284,19 +2317,6 @@
|
||||
.byte \stat
|
||||
.endm
|
||||
|
||||
.macro trywindriderpower battler:req, failInstr:req
|
||||
various \battler, VARIOUS_TRY_WIND_RIDER_POWER
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
.macro activateweatherchangeabilities battler:req
|
||||
various \battler, VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES
|
||||
.endm
|
||||
|
||||
.macro activateterrainchangeabilities battler:req
|
||||
various \battler, VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES
|
||||
.endm
|
||||
|
||||
@ various remaining from pokefirered
|
||||
.macro getbattlersforrecall
|
||||
various BS_ATTACKER, VARIOUS_GET_BATTLERS_FOR_RECALL
|
||||
@@ -2504,15 +2524,6 @@
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
.endm
|
||||
|
||||
.macro hitswitchtargetfailed
|
||||
various 0, VARIOUS_HIT_SWITCH_TARGET_FAILED
|
||||
.endm
|
||||
|
||||
.macro tryrevivalblessing, jumpInstr:req
|
||||
various 0, VARIOUS_TRY_REVIVAL_BLESSING
|
||||
.4byte \jumpInstr
|
||||
.endm
|
||||
|
||||
@ Will jump to script pointer if the specified battler has or has not fainted.
|
||||
.macro jumpiffainted battler:req, value:req, ptr:req
|
||||
getbattlerfainted \battler
|
||||
|
||||
@@ -587,7 +587,7 @@ BattleScript_EffectAttackUpUserAlly_TryAlly:
|
||||
BattleScript_EffectAttackUpUserAlly_End:
|
||||
goto BattleScript_MoveEnd
|
||||
BattleScript_EffectAttackUpUserAlly_TryAlly_:
|
||||
jumpifability BS_ATTACKER_PARTNER, ABILITY_SOUNDPROOF, BattleScript_EffectAttackUpUserAlly_TryAllyBlocked
|
||||
jumpifblockedbysoundproof BS_ATTACKER_PARTNER, BattleScript_EffectAttackUpUserAlly_TryAllyBlocked
|
||||
setstatchanger STAT_ATK, 1, FALSE
|
||||
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_EffectAttackUpUserAlly_End
|
||||
jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectAttackUpUserAlly_AllyAnim
|
||||
@@ -981,7 +981,7 @@ BattleScript_EffectTarShot::
|
||||
printfromtable gStatDownStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_TryTarShot:
|
||||
trytarshot BS_TARGET, BattleScript_MoveEnd
|
||||
trytarshot BattleScript_MoveEnd
|
||||
printstring STRINGID_PKMNBECAMEWEAKERTOFIRE
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
@@ -1836,6 +1836,8 @@ BattleScript_EffectInstruct::
|
||||
tryinstruct BattleScript_ButItFailed
|
||||
attackanimation
|
||||
waitanimation
|
||||
copybyte gBattlerAttacker, gBattlerTarget
|
||||
copybyte gBattlerTarget, gEffectBattler
|
||||
printstring STRINGID_USEDINSTRUCTEDMOVE
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
setbyte sB_ANIM_TURN, 0
|
||||
@@ -1915,7 +1917,7 @@ BattleScript_HitSwitchTargetForceRandomSwitchFailed:
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectToxicThread::
|
||||
setstatchanger STAT_SPEED, 2, TRUE
|
||||
setstatchanger STAT_SPEED, 1, TRUE
|
||||
attackcanceler
|
||||
jumpifsubstituteblocks BattleScript_FailedFromAtkString
|
||||
jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_SPEED, MIN_STAT_STAGE, BattleScript_ToxicThreadWorks
|
||||
@@ -3356,51 +3358,17 @@ BattleScript_RoarBlockedByDynamax:
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_MultiHitLoop::
|
||||
jumpifhasnohp BS_ATTACKER, BattleScript_MultiHitEnd
|
||||
jumpifhasnohp BS_TARGET, BattleScript_MultiHitPrintStrings
|
||||
jumpifhalfword CMP_EQUAL, gChosenMove, MOVE_SLEEP_TALK, BattleScript_DoMultiHit
|
||||
jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_MultiHitPrintStrings
|
||||
BattleScript_DoMultiHit::
|
||||
movevaluescleanup
|
||||
copyhword sMOVE_EFFECT, sMULTIHIT_EFFECT
|
||||
critcalc
|
||||
damagecalc
|
||||
jumpifmovehadnoeffect BattleScript_MultiHitNoMoreHits
|
||||
adjustdamage
|
||||
attackanimation
|
||||
waitanimation
|
||||
effectivenesssound
|
||||
hitanimation BS_TARGET
|
||||
waitstate
|
||||
healthbarupdate BS_TARGET
|
||||
datahpupdate BS_TARGET
|
||||
critmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
multihitresultmessage
|
||||
flushtextbox
|
||||
addbyte sMULTIHIT_STRING + 4, 1
|
||||
moveendto MOVEEND_NEXT_TARGET
|
||||
jumpifbyte CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_FOE_ENDURED, BattleScript_MultiHitPrintStrings
|
||||
decrementmultihit BattleScript_MultiHitLoop
|
||||
goto BattleScript_MultiHitPrintStrings
|
||||
BattleScript_MultiHitNoMoreHits::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
BattleScript_MultiHitPrintStrings::
|
||||
resultmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
jumpifmovehadnoeffect BattleScript_MultiHitEnd
|
||||
copyarray gBattleTextBuff1, sMULTIHIT_STRING, 6
|
||||
printstring STRINGID_HITXTIMES
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
return
|
||||
|
||||
BattleScript_MultiHitEnd::
|
||||
setadditionaleffects
|
||||
tryfaintmon BS_TARGET
|
||||
moveendcase MOVEEND_SYNCHRONIZE_TARGET
|
||||
moveendfrom MOVEEND_STATUS_IMMUNITY_ABILITIES
|
||||
end
|
||||
BattleScript_ScaleShot::
|
||||
call BattleScript_MultiHitPrintStrings
|
||||
goto BattleScript_DefDownSpeedUp
|
||||
|
||||
BattleScript_EffectConversion::
|
||||
attackcanceler
|
||||
@@ -4358,7 +4326,7 @@ BattleScript_EffectPerishSong::
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
setbyte gBattlerTarget, 0
|
||||
BattleScript_PerishSongLoop::
|
||||
jumpifability BS_TARGET, ABILITY_SOUNDPROOF, BattleScript_PerishSongBlocked
|
||||
jumpifblockedbysoundproof BS_TARGET, BattleScript_PerishSongBlocked
|
||||
jumpifpranksterblocked BS_TARGET, BattleScript_PerishSongNotAffected
|
||||
BattleScript_PerishSongLoopIncrement::
|
||||
addbyte gBattlerTarget, 1
|
||||
@@ -4801,6 +4769,9 @@ BattleScript_ButItFailed::
|
||||
resultmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
BattleScript_RestoreAttackerButItFailed:
|
||||
restoreattacker
|
||||
goto BattleScript_ButItFailed
|
||||
|
||||
BattleScript_NotAffected::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
@@ -5680,13 +5651,13 @@ BattleScript_LocalTrainerBattleWon::
|
||||
BattleScript_LocalTwoTrainersDefeated::
|
||||
printstring STRINGID_TWOENEMIESDEFEATED
|
||||
BattleScript_LocalBattleWonLoseTexts::
|
||||
trainerslidein BS_ATTACKER
|
||||
trainerslidein BS_OPPONENT1
|
||||
waitstate
|
||||
printstring STRINGID_TRAINER1LOSETEXT
|
||||
jumpifnotbattletype BATTLE_TYPE_TWO_OPPONENTS, BattleScript_LocalBattleWonReward
|
||||
trainerslideout B_POSITION_OPPONENT_LEFT
|
||||
trainerslideout BS_OPPONENT1
|
||||
waitstate
|
||||
trainerslidein BS_FAINTED
|
||||
trainerslidein BS_OPPONENT2
|
||||
waitstate
|
||||
printstring STRINGID_TRAINER2LOSETEXT
|
||||
BattleScript_LocalBattleWonReward::
|
||||
@@ -6444,12 +6415,14 @@ BattleScript_SeedSowerActivates::
|
||||
return
|
||||
|
||||
BattleScript_AngerShellActivates::
|
||||
saveattacker
|
||||
copybyte gBattlerAttacker, gBattlerTarget
|
||||
call BattleScript_AbilityPopUp
|
||||
jumpifstat BS_TARGET, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_AngerShellTryDef
|
||||
jumpifstat BS_TARGET, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_AngerShellTryDef
|
||||
jumpifstat BS_TARGET, CMP_LESS_THAN, STAT_SPEED, MAX_STAT_STAGE, BattleScript_AngerShellTryDef
|
||||
jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_DEF, MIN_STAT_STAGE, BattleScript_AngerShellTryDef
|
||||
jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPDEF, MIN_STAT_STAGE, BattleScript_ButItFailed
|
||||
jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPDEF, MIN_STAT_STAGE, BattleScript_RestoreAttackerButItFailed
|
||||
BattleScript_AngerShellTryDef::
|
||||
setbyte sSTAT_ANIM_PLAYED, FALSE
|
||||
modifybattlerstatstage BS_ATTACKER, STAT_DEF, DECREASE, 1, BattleScript_AngerShellTrySpDef, ANIM_ON
|
||||
@@ -6463,6 +6436,7 @@ BattleScript_AngerShellTrySpAtk:
|
||||
BattleScript_AngerShellTrySpeed:
|
||||
modifybattlerstatstage BS_ATTACKER, STAT_SPEED, INCREASE, 1, BattleScript_AngerShellRet, ANIM_ON
|
||||
BattleScript_AngerShellRet:
|
||||
restoreattacker
|
||||
return
|
||||
|
||||
BattleScript_WindPowerActivates::
|
||||
@@ -6979,12 +6953,12 @@ BattleScript_WishMegaEvolution::
|
||||
|
||||
BattleScript_PrimalReversion::
|
||||
call BattleScript_PrimalReversionRet
|
||||
end2
|
||||
end3
|
||||
|
||||
BattleScript_PrimalReversionRestoreAttacker::
|
||||
call BattleScript_PrimalReversionRet
|
||||
copybyte gBattlerAttacker, sSAVED_BATTLER
|
||||
end2
|
||||
end3
|
||||
|
||||
BattleScript_PrimalReversionRet::
|
||||
flushtextbox
|
||||
@@ -7693,15 +7667,11 @@ BattleScript_EmergencyExitWildNoPopUp::
|
||||
|
||||
BattleScript_TraceActivates::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
call BattleScript_AbilityPopUp
|
||||
call BattleScript_AbilityPopUpScripting
|
||||
printstring STRINGID_PKMNTRACED
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
settracedability BS_SCRIPTING
|
||||
switchinabilities BS_SCRIPTING
|
||||
return
|
||||
|
||||
BattleScript_TraceActivatesEnd3::
|
||||
call BattleScript_TraceActivates
|
||||
end3
|
||||
|
||||
BattleScript_ReceiverActivates::
|
||||
@@ -9285,6 +9255,16 @@ BattleScript_ZMoveActivateStatus::
|
||||
copybyte sSTATCHANGER, sSAVED_STAT_CHANGER
|
||||
return
|
||||
|
||||
BattleScript_ZMoveActivatePowder::
|
||||
flushtextbox
|
||||
trytrainerslidezmovemsg
|
||||
savetarget
|
||||
printstring STRINGID_ZPOWERSURROUNDS
|
||||
playanimation BS_ATTACKER, B_ANIM_ZMOVE_ACTIVATE, NULL
|
||||
setzeffect
|
||||
restoretarget
|
||||
goto BattleScript_MoveUsedPowder
|
||||
|
||||
BattleScript_ZEffectPrintString::
|
||||
printfromtable gZEffectStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
@@ -9916,7 +9896,7 @@ BattleScript_BerserkGeneRet_End:
|
||||
|
||||
BattleScript_BoosterEnergyEnd2::
|
||||
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1
|
||||
call BattleScript_AbilityPopUpTarget
|
||||
call BattleScript_AbilityPopUpScripting
|
||||
printstring STRINGID_BOOSTERENERGYACTIVATES
|
||||
waitmessage B_WAIT_TIME_MED
|
||||
printstring STRINGID_STATWASHEIGHTENED
|
||||
|
||||
@@ -705,6 +705,7 @@ struct BattleStruct
|
||||
u8 blunderPolicy:1; // should blunder policy activate
|
||||
u8 swapDamageCategory:1; // Photon Geyser, Shell Side Arm, Light That Burns the Sky
|
||||
u8 bouncedMoveIsUsed:1;
|
||||
u8 snatchedMoveIsUsed:1;
|
||||
u8 descriptionSubmenu:1; // For Move Description window in move selection screen
|
||||
u8 ackBallUseBtn:1; // Used for the last used ball feature
|
||||
u8 ballSwapped:1; // Used for the last used ball feature
|
||||
@@ -755,6 +756,8 @@ struct BattleStruct
|
||||
u8 categoryOverride; // for Z-Moves and Max Moves
|
||||
u32 stellarBoostFlags[NUM_BATTLE_SIDES]; // stored as a bitfield of flags for all types for each side
|
||||
u8 fickleBeamBoosted:1;
|
||||
u8 obedienceResult:3;
|
||||
u8 usedMicleBerry;
|
||||
|
||||
// pokefirered
|
||||
u8 field_DA; // battle tower related
|
||||
@@ -1098,6 +1101,12 @@ static inline u32 GetBattlerSide(u32 battler)
|
||||
return GetBattlerPosition(battler) & BIT_SIDE;
|
||||
}
|
||||
|
||||
static inline struct Pokemon* GetPartyBattlerData(u32 battler)
|
||||
{
|
||||
u32 index = gBattlerPartyIndexes[battler];
|
||||
return (GetBattlerSide(battler) == B_SIDE_OPPONENT) ? &gEnemyParty[index] : &gPlayerParty[index];
|
||||
}
|
||||
|
||||
static inline struct Pokemon *GetSideParty(u32 side)
|
||||
{
|
||||
return (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty;
|
||||
@@ -1108,5 +1117,10 @@ static inline struct Pokemon *GetBattlerParty(u32 battler)
|
||||
return GetSideParty(GetBattlerSide(battler));
|
||||
}
|
||||
|
||||
static inline bool32 IsDoubleBattle(void)
|
||||
{
|
||||
return gBattleTypeFlags & BATTLE_TYPE_DOUBLE;
|
||||
}
|
||||
|
||||
|
||||
#endif // GUARD_BATTLE_H
|
||||
|
||||
@@ -72,7 +72,6 @@ bool32 CanKnockOffItem(u32 battler, u32 item);
|
||||
bool32 IsAbilityOfRating(u32 ability, s8 rating);
|
||||
bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability);
|
||||
bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u32 move);
|
||||
u32 AI_GetBattlerMoveTargetType(u32 battlerId, u32 move);
|
||||
bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove);
|
||||
|
||||
// stat stage checks
|
||||
@@ -115,6 +114,7 @@ bool32 HasMoveEffectANDArg(u32 battlerId, u32 effect, u32 argument);
|
||||
bool32 HasMoveWithAdditionalEffect(u32 battlerId, u32 moveEffect);
|
||||
bool32 HasMoveWithCriticalHitChance(u32 battlerId);
|
||||
bool32 HasMoveWithMoveEffectExcept(u32 battlerId, u32 moveEffect, u32 exception);
|
||||
bool32 HasMoveThatLowersOwnStats(u32 battlerId);
|
||||
bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect);
|
||||
bool32 HasAnyKnownMove(u32 battlerId);
|
||||
bool32 IsAromaVeilProtectedMove(u32 move);
|
||||
@@ -139,6 +139,7 @@ bool32 ShouldFakeOut(u32 battlerAtk, u32 battlerDef, u32 move);
|
||||
bool32 HasThawingMove(u32 battler);
|
||||
bool32 IsStatRaisingEffect(u32 effect);
|
||||
bool32 IsStatLoweringEffect(u32 effect);
|
||||
bool32 IsSelfStatLoweringEffect(u32 effect);
|
||||
bool32 IsAttackBoostMoveEffect(u32 effect);
|
||||
bool32 IsUngroundingEffect(u32 effect);
|
||||
bool32 IsSemiInvulnerable(u32 battlerDef, u32 move);
|
||||
@@ -205,5 +206,6 @@ bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef);
|
||||
bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData);
|
||||
void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score);
|
||||
bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, struct AiLogicData *aiData);
|
||||
void IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score);
|
||||
|
||||
#endif //GUARD_BATTLE_AI_UTIL_H
|
||||
|
||||
@@ -527,7 +527,6 @@ void InitSpritePosToAnimTarget(struct Sprite *sprite, bool8 respectMonPicOffsets
|
||||
void InitSpritePosToAnimAttacker(struct Sprite *sprite, bool8 respectMonPicOffsets);
|
||||
u8 GetBattlerAtPosition(u8 position);
|
||||
bool8 IsBattlerSpritePresent(u8 battlerId);
|
||||
bool8 IsDoubleBattle(void);
|
||||
void GetBattleAnimBg1Data(struct BattleAnimBgData *animBgData);
|
||||
void GetBattleAnimBgData(struct BattleAnimBgData *animBgData, u32 bgId);
|
||||
void GetBattleAnimBgDataByPriorityRank(struct BattleAnimBgData *animBgData, u8 unused);
|
||||
|
||||
@@ -403,6 +403,7 @@ extern const u8 BattleScript_SyrupBombActivates[];
|
||||
extern const u8 BattleScript_AromaVeilProtectsRet[];
|
||||
extern const u8 BattleScript_StatUpMsg[];
|
||||
extern const u8 BattleScript_SymbiosisActivates[];
|
||||
extern const u8 BattleScript_ScaleShot[];
|
||||
extern const u8 BattleScript_OverworldStatusStarts[];
|
||||
extern const u8 BattleScript_OverworldTerrain[];
|
||||
extern const u8 BattleScript_ImposterActivates[];
|
||||
@@ -615,7 +616,6 @@ extern const u8 BattleScript_Recoil33End[];
|
||||
extern const u8 BattleScript_ItemSteal[];
|
||||
extern const u8 BattleScript_DrizzleActivates[];
|
||||
extern const u8 BattleScript_SpeedBoostActivates[];
|
||||
extern const u8 BattleScript_TraceActivatesEnd3[];
|
||||
extern const u8 BattleScript_RainDishActivates[];
|
||||
extern const u8 BattleScript_SandstreamActivates[];
|
||||
extern const u8 BattleScript_ShedSkinActivates[];
|
||||
@@ -772,6 +772,7 @@ extern const u8 BattleScript_ProteanActivates[];
|
||||
extern const u8 BattleScript_DazzlingProtected[];
|
||||
extern const u8 BattleScript_MoveUsedPsychicTerrainPrevents[];
|
||||
extern const u8 BattleScript_MoveUsedPowder[];
|
||||
extern const u8 BattleScript_ZMoveActivatePowder[];
|
||||
extern const u8 BattleScript_SelectingNotAllowedStuffCheeks[];
|
||||
extern const u8 BattleScript_SelectingNotAllowedStuffCheeksInPalace[];
|
||||
extern const u8 BattleScript_SelectingNotAllowedBelch[];
|
||||
|
||||
@@ -107,6 +107,15 @@ enum
|
||||
CANCELLER_END2,
|
||||
};
|
||||
|
||||
enum {
|
||||
OBEYS,
|
||||
DISOBEYS_LOAFS,
|
||||
DISOBEYS_HITS_SELF,
|
||||
DISOBEYS_FALL_ASLEEP,
|
||||
DISOBEYS_WHILE_ASLEEP,
|
||||
DISOBEYS_RANDOM_MOVE,
|
||||
};
|
||||
|
||||
extern const struct TypePower gNaturalGiftTable[];
|
||||
|
||||
void HandleAction_ThrowBall(void);
|
||||
@@ -172,7 +181,7 @@ void ClearVariousBattlerFlags(u32 battler);
|
||||
void HandleAction_RunBattleScript(void);
|
||||
u32 SetRandomTarget(u32 battler);
|
||||
u32 GetMoveTarget(u16 move, u8 setTarget);
|
||||
u8 IsMonDisobedient(void);
|
||||
u8 GetAttackerObedienceForAction();
|
||||
u32 GetBattlerHoldEffect(u32 battler, bool32 checkNegating);
|
||||
u32 GetBattlerHoldEffectIgnoreAbility(u32 battler, bool32 checkNegating);
|
||||
u32 GetBattlerHoldEffectInternal(u32 battler, bool32 checkNegating, bool32 checkAbility);
|
||||
@@ -248,7 +257,7 @@ bool32 MoveHasAdditionalEffectSelf(u32 move, u32 moveEffect);
|
||||
bool32 MoveHasAdditionalEffectSelfArg(u32 move, u32 moveEffect, u32 argument);
|
||||
bool32 MoveHasChargeTurnAdditionalEffect(u32 move);
|
||||
bool32 CanTargetPartner(u32 battlerAtk, u32 battlerDef);
|
||||
bool32 TargetFullyImmuneToCurrMove(u32 BattlerAtk, u32 battlerDef);
|
||||
bool32 TargetFullyImmuneToCurrMove(u32 battlerAtk, u32 battlerDef);
|
||||
|
||||
bool32 CanBeSlept(u32 battler, u32 ability);
|
||||
bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 defAbility);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef GUARD_LEVEL_CAP_H
|
||||
#define GUARD_LEVEL_CAP_H
|
||||
#ifndef GUARD_CAPS_H
|
||||
#define GUARD_CAPS_H
|
||||
|
||||
#if B_EXP_CAP_TYPE != EXP_CAP_NONE && B_EXP_CAP_TYPE != EXP_CAP_HARD && B_EXP_CAP_TYPE != EXP_CAP_SOFT
|
||||
#error "Invalid choice for B_EXP_CAP_TYPE, must be of [EXP_CAP_NONE, EXP_CAP_HARD, EXP_CAP_SOFT]"
|
||||
@@ -14,7 +14,12 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if B_EV_CAP_TYPE != EV_CAP_NONE && B_EV_CAP_TYPE != EV_CAP_FLAG_LIST && B_EV_CAP_TYPE != EV_CAP_VARIABLE && B_EV_CAP_TYPE != EV_CAP_NO_GAIN
|
||||
#error "Invalid choice for B_EV_CAP_TYPE, must be one of [EV_CAP_NONE, EV_CAP_FLAG_LIST, EV_CAP_VARIABLE, EV_CAP_NO_GAIN]"
|
||||
#endif
|
||||
|
||||
u32 GetCurrentLevelCap(void);
|
||||
u32 GetSoftLevelCapExpValue(u32 level, u32 expValue);
|
||||
u32 GetCurrentEVCap(void);
|
||||
|
||||
#endif /* GUARD_LEVEL_CAP_H */
|
||||
#endif /* GUARD_CAPS_H */
|
||||
@@ -39,7 +39,6 @@
|
||||
#define B_MULTIPLE_TARGETS_DMG GEN_LATEST // In Gen4+, damage dealt by moves that hit multiple targets at once is reduced to 75%. Before, it was 50%.
|
||||
|
||||
// Type settings
|
||||
#define B_EXPANDED_TYPE_NAMES TRUE // If TRUE, type names are increased from 6 characters to 8 characters.
|
||||
#define B_GHOSTS_ESCAPE GEN_LATEST // In Gen6+, abilities like Shadow Tag or moves like Mean Look fail on Ghost-type Pokémon. They can also escape any Wild Battle.
|
||||
#define B_PARALYZE_ELECTRIC GEN_LATEST // In Gen6+, Electric-type Pokémon can't be paralyzed.
|
||||
#define B_POWDER_GRASS GEN_LATEST // In Gen6+, Grass-type Pokémon are immune to powder and spore moves.
|
||||
@@ -121,9 +120,12 @@
|
||||
#define B_SKETCH_BANS GEN_LATEST // In Gen9+, Sketch is unable to copy more moves than in previous generations.
|
||||
#define B_KNOCK_OFF_REMOVAL GEN_LATEST // In Gen5+, Knock Off removes the foe's item instead of rendering it unusable.
|
||||
#define B_HEAL_BELL_SOUNDPROOF GEN_LATEST // In Gen5, Heal Bell affects all mons with Soundproof. In Gen6-8 it affects inactive mons, but not battlers. In Gen9 it always affects the user.
|
||||
#define B_CHARGE GEN_LATEST // In Gen8-, Charge status is lost regardless of the typing of the next move.
|
||||
#define B_POWDER_RAIN GEN_LATEST // In Gen7+, Powder doesn't damage the user of a Fire type move in heavy rain.
|
||||
#define B_AFTER_YOU_TURN_ORDER GEN_LATEST // In Gen8+, After You doesn't fail if the turn order wouldn't change after use.
|
||||
#define B_QUASH_TURN_ORDER GEN_LATEST // In Gen8+, Quash-affected battlers move according to speed order. Before Gen8, Quash-affected battlers move in the order they were affected by Quash.
|
||||
|
||||
// Ability settings
|
||||
#define B_EXPANDED_ABILITY_NAMES TRUE // If TRUE, ability names are increased from 12 characters to 16 characters.
|
||||
#define B_ABILITY_WEATHER GEN_LATEST // In Gen6+, ability-induced weather lasts 5 turns. Before, it lasted until the battle ended or until it was changed by a move or a different weather-affecting ability.
|
||||
#define B_GALE_WINGS GEN_LATEST // In Gen7+ requires full HP to trigger.
|
||||
#define B_STANCE_CHANGE_FAIL GEN_LATEST // In Gen7+, Stance Change fails if the Pokémon is unable to use a move because of confusion, paralysis, etc. In Gen6, it doesn't.
|
||||
@@ -163,7 +165,7 @@
|
||||
#define B_RESTORE_HELD_BATTLE_ITEMS GEN_LATEST // In Gen9, all non-berry items are restored after battle.
|
||||
#define B_SOUL_DEW_BOOST GEN_LATEST // In Gens3-6, Soul Dew boosts Latis' Sp. Atk and Sp. Def. In Gen7+ it boosts the power of their Psychic and Dragon type moves instead.
|
||||
#define B_NET_BALL_MODIFIER GEN_LATEST // In Gen7+, Net Ball's catch multiplier is x5 instead of x3.
|
||||
#define B_DIVE_BALL_MODIFIER GEN_LATEST // In Gen4+, Dive Ball's effectiveness increases by when Surfing or Fishing.
|
||||
#define B_DIVE_BALL_MODIFIER GEN_LATEST // In Gen4+, Dive Ball's effectiveness increases by x3.5 when Surfing or Fishing.
|
||||
#define B_NEST_BALL_MODIFIER GEN_LATEST // Nest Ball's formula varies depending on the Gen. See Cmd_handleballthrow.
|
||||
#define B_REPEAT_BALL_MODIFIER GEN_LATEST // In Gen7+, Repeat Ball's catch multiplier is x3.5 instead of x3.
|
||||
#define B_TIMER_BALL_MODIFIER GEN_LATEST // In Gen5+, Timer Ball's effectiveness increases by x0.3 per turn instead of x0.1
|
||||
@@ -204,6 +206,9 @@
|
||||
// Flag and Var settings
|
||||
#define B_RESET_FLAGS_VARS_AFTER_WHITEOUT TRUE // If TRUE, Overworld_ResetBattleFlagsAndVars will reset battle-related Flags and Vars when the player whites out.
|
||||
|
||||
// Ingame partner flag
|
||||
#define B_SHOW_PARTNER_TARGET FALSE // Shows the battler partner will target.
|
||||
|
||||
// Terrain settings
|
||||
#define B_TERRAIN_BG_CHANGE TRUE // If set to TRUE, terrain moves permanently change the default battle background until the effect fades.
|
||||
#define B_THUNDERSTORM_TERRAIN TRUE // If TRUE, overworld Thunderstorm generates Rain and Electric Terrain as in Gen 8.
|
||||
@@ -221,7 +226,6 @@
|
||||
#define B_SHOW_TARGETS TRUE // If set to TRUE, all available targets, for moves hitting 2 or 3 Pokémon, will be shown before selecting a move.
|
||||
#define B_SHOW_CATEGORY_ICON TRUE // If set to TRUE, it will show an icon in the summary and move relearner showing the move's category.
|
||||
#define B_HIDE_HEALTHBOX_IN_ANIMS TRUE // If set to TRUE, hides healthboxes during move animations.
|
||||
#define B_EXPANDED_MOVE_NAMES TRUE // If set to FALSE, move names are decreased from 16 characters to 12 characters.
|
||||
#define B_WAIT_TIME_MULTIPLIER 16 // This determines how long text pauses in battle last. Vanilla is 16. Lower values result in faster battles.
|
||||
#define B_QUICK_MOVE_CURSOR_TO_RUN FALSE // If set to TRUE, pushing B in the battle options against a wild encounter will move the cursor to the run option
|
||||
#define B_MOVE_DESCRIPTION_BUTTON L_BUTTON // If set to a button other than B_LAST_USED_BALL_BUTTON, pressing this button will open the move description menu
|
||||
@@ -278,4 +282,7 @@
|
||||
#define SHOW_TYPES_CAUGHT 2
|
||||
#define B_SHOW_TYPES SHOW_TYPES_NEVER // When defined as SHOW_TYPES_ALWAYS, after selecting "Fight" in battle, the types of all Pokemon are revealed. Whe defined as SHOW_TYPES_OWN, types are only revealed if the player owns the mon in question.
|
||||
|
||||
// Pokémon battle sprite settings
|
||||
#define B_ENEMY_MON_SHADOW_STYLE GEN_LATEST // In Gen4+, all enemy Pokemon will have a shadow drawn beneath them.
|
||||
|
||||
#endif // GUARD_CONFIG_BATTLE_H
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef GUARD_CONFIG_LEVEL_CAP_H
|
||||
#define GUARD_CONFIG_LEVEL_CAP_H
|
||||
#ifndef GUARD_CONFIG_CAPS_H
|
||||
#define GUARD_CONFIG_CAPS_H
|
||||
|
||||
// Constants
|
||||
// Level Cap Constants
|
||||
#define EXP_CAP_NONE 0 // Regular behavior, no level caps are applied
|
||||
#define EXP_CAP_HARD 1 // Pokémon with a level >= the level cap cannot gain any experience
|
||||
#define EXP_CAP_SOFT 2 // Pokémon with a level >= the level cap will gain reduced experience
|
||||
@@ -10,7 +10,7 @@
|
||||
#define LEVEL_CAP_FLAG_LIST 1 // Level cap is chosen according to the first unset flag in `sLevelCapFlagMap`
|
||||
#define LEVEL_CAP_VARIABLE 2 // Level cap is chosen according to the contents of the event variable specified by B_LEVEL_CAP_VARIABLE
|
||||
|
||||
// Configs
|
||||
// Level Cap Configs
|
||||
#define B_EXP_CAP_TYPE EXP_CAP_NONE // [EXP_CAP_NONE, EXP_CAP_HARD, EXP_CAP_SOFT] choose the type of level cap to apply
|
||||
#define B_LEVEL_CAP_TYPE LEVEL_CAP_NONE // [LEVEL_CAP_NONE, LEVEL_CAP_FLAG_LIST, LEVEL_CAP_VARIABLE] choose the method to derive the level cap
|
||||
#define B_LEVEL_CAP_VARIABLE 0 // event variable used to derive level cap if B_LEVEL_CAP_TYPE is set to LEVEL_CAP_VARIABLE
|
||||
@@ -18,4 +18,16 @@
|
||||
#define B_RARE_CANDY_CAP FALSE // If set to true, Rare Candies can't be used to go over the level cap
|
||||
#define B_LEVEL_CAP_EXP_UP FALSE // If set to true, mons under level cap will receive more experience
|
||||
|
||||
#endif /* GUARD_CONFIG_LEVEL_CAP_H */
|
||||
// EV Cap Constants
|
||||
#define EV_CAP_NONE 0 // Regular behavior, no EV caps are applied
|
||||
#define EV_CAP_FLAG_LIST 1 // EV cap is chosen according to the first unset flag in `sEVCapFlagMap`
|
||||
#define EV_CAP_VARIABLE 2 // EV cap is chosen according to the contents of the event variable specified by B_EV_CAP_VARIABLE
|
||||
#define EV_CAP_NO_GAIN 3 // No EVs can be gained
|
||||
|
||||
// EV Cap Configs
|
||||
#define B_EV_CAP_TYPE EV_CAP_NONE // [EV_CAP_NONE, EV_CAP_FLAG_LIST, EV_CAP_VARIABLE, EV_CAP_NO_GAIN] choose the type of EV cap to apply#define B_EV_CAP_VARIABLE 12 // event variable used to derive EV cap if B_EV_CAP_TYPE is set to EV_CAP_VARIABLE
|
||||
#define B_EV_CAP_VARIABLE 8 // event variable used to derive EV cap if B_EV_CAP_TYPE is set to EV_CAP_VARIABLE
|
||||
|
||||
#define B_EV_ITEMS_CAP FALSE // If set to true, EV-boosting items can't be used to go over the EV cap
|
||||
|
||||
#endif /* GUARD_CONFIG_CAPS_H */
|
||||
@@ -1,14 +1,8 @@
|
||||
#ifndef GUARD_CONFIG_TEST_H
|
||||
#define GUARD_CONFIG_TEST_H
|
||||
|
||||
#undef B_EXPANDED_MOVE_NAMES
|
||||
#define B_EXPANDED_MOVE_NAMES TRUE
|
||||
#undef I_EXPANDED_ITEM_NAMES
|
||||
#define I_EXPANDED_ITEM_NAMES TRUE
|
||||
#undef POKEMON_NAME_LENGTH
|
||||
#define POKEMON_NAME_LENGTH 12
|
||||
#undef B_EXPANDED_TYPE_NAMES
|
||||
#define B_EXPANDED_TYPE_NAMES TRUE
|
||||
|
||||
#undef P_MEGA_EVOLUTIONS
|
||||
#define P_MEGA_EVOLUTIONS TRUE
|
||||
|
||||
@@ -25,31 +25,36 @@
|
||||
#define AI_EFFECTIVENESS_x0 0
|
||||
|
||||
// AI Flags. Most run specific functions to update score, new flags are used for internal logic in other scripts
|
||||
#define AI_FLAG_CHECK_BAD_MOVE (1 << 0)
|
||||
#define AI_FLAG_TRY_TO_FAINT (1 << 1)
|
||||
#define AI_FLAG_CHECK_VIABILITY (1 << 2)
|
||||
#define AI_FLAG_SETUP_FIRST_TURN (1 << 3)
|
||||
#define AI_FLAG_RISKY (1 << 4)
|
||||
#define AI_FLAG_PREFER_STRONGEST_MOVE (1 << 5)
|
||||
#define AI_FLAG_PREFER_BATON_PASS (1 << 6)
|
||||
#define AI_FLAG_DOUBLE_BATTLE (1 << 7) // Automatically set for double battles, handles AI behaviour with partner
|
||||
#define AI_FLAG_HP_AWARE (1 << 8)
|
||||
#define AI_FLAG_POWERFUL_STATUS (1 << 9) // AI prefers moves that set up field effects or side statuses, even if the user can faint the target
|
||||
// See docs/ai_flags.md for more details.
|
||||
#define AI_FLAG_CHECK_BAD_MOVE (1 << 0) // AI will avoid using moves that are likely to fail or be ineffective in the current situation.
|
||||
#define AI_FLAG_TRY_TO_FAINT (1 << 1) // AI will prioritize KOing the player's mon if able.
|
||||
#define AI_FLAG_CHECK_VIABILITY (1 << 2) // AI damaging moves and move effects to determine the best available move in the current situation.
|
||||
#define AI_FLAG_FORCE_SETUP_FIRST_TURN (1 << 3) // AI will prioritize using setup moves on the first turn at the expensve of all else. AI_FLAG_CHECK_VIABILITY will instead do this when the AI determines it makes sense.
|
||||
#define AI_FLAG_RISKY (1 << 4) // AI will generally behave more recklessly, prioritizing damage over accuracy, explosions, etc.
|
||||
#define AI_FLAG_PREFER_STRONGEST_MOVE (1 << 5) // AI adds score bonus to any move the AI has that either OHKOs or 2HKOs the player.
|
||||
#define AI_FLAG_PREFER_BATON_PASS (1 << 6) // AI prefers raising its own stats and setting for / using Baton Pass.
|
||||
#define AI_FLAG_DOUBLE_BATTLE (1 << 7) // Automatically set for double battles, handles AI behaviour with partner.
|
||||
#define AI_FLAG_HP_AWARE (1 << 8) // AI will favour certain move effects based on how much remaining HP it and the player's mon have.
|
||||
#define AI_FLAG_POWERFUL_STATUS (1 << 9) // AI prefers moves that set up field effects or side statuses, even if the user can faint the target.
|
||||
// New, Trainer Handicap Flags
|
||||
#define AI_FLAG_NEGATE_UNAWARE (1 << 10) // AI is NOT aware of negating effects like wonder room, mold breaker, etc
|
||||
#define AI_FLAG_WILL_SUICIDE (1 << 11) // AI will use explosion / self destruct / final gambit / etc
|
||||
#define AI_FLAG_NEGATE_UNAWARE (1 << 10) // AI is NOT aware of negating effects like wonder room, mold breaker, etc.
|
||||
#define AI_FLAG_WILL_SUICIDE (1 << 11) // AI will use explosion / self destruct / final gambit / etc.
|
||||
// New, Trainer Strategy Flags
|
||||
#define AI_FLAG_PREFER_STATUS_MOVES (1 << 12) // AI gets a score bonus for status moves. Should be combined with AI_FLAG_CHECK_BAD_MOVE to prevent using only status moves
|
||||
#define AI_FLAG_STALL (1 << 13) // AI stalls battle and prefers secondary damage/trapping/etc. TODO not finished
|
||||
#define AI_FLAG_PREFER_STATUS_MOVES (1 << 12) // AI gets a score bonus for status moves. Should be combined with AI_FLAG_CHECK_BAD_MOVE to prevent using only status moves.
|
||||
#define AI_FLAG_STALL (1 << 13) // AI stalls battle and prefers secondary damage/trapping/etc. TODO not finished.
|
||||
#define AI_FLAG_SMART_SWITCHING (1 << 14) // AI includes a lot more switching checks. Automatically includes AI_FLAG_SMART_MON_CHOICES.
|
||||
#define AI_FLAG_ACE_POKEMON (1 << 15) // AI has an Ace Pokemon. The last Pokemon in the party will not be used until it's the last one remaining.
|
||||
#define AI_FLAG_OMNISCIENT (1 << 16) // AI has full knowledge of player moves, abilities, hold items
|
||||
#define AI_FLAG_OMNISCIENT (1 << 16) // AI has full knowledge of player moves, abilities, hold items.
|
||||
#define AI_FLAG_SMART_MON_CHOICES (1 << 17) // AI will make smarter decisions when choosing which mon to send out mid-battle and after a KO, which are separate decisions. Automatically included by AI_FLAG_SMART_SWITCHING.
|
||||
#define AI_FLAG_CONSERVATIVE (1 << 18) // AI assumes all moves will low roll damage
|
||||
#define AI_FLAG_SEQUENCE_SWITCHING (1 << 19) // AI switches in mons in exactly party order, and never switches mid-battle
|
||||
#define AI_FLAG_CONSERVATIVE (1 << 18) // AI assumes all moves will low roll damage.
|
||||
#define AI_FLAG_SEQUENCE_SWITCHING (1 << 19) // AI switches in mons in exactly party order, and never switches mid-battle.
|
||||
|
||||
#define AI_FLAG_COUNT 20
|
||||
|
||||
// The following options are enough to have a basic/smart trainer. Any other addtion could make the trainer worse/better depending on the flag
|
||||
#define AI_FLAG_BASIC_TRAINER (AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY)
|
||||
#define AI_FLAG_SMART_TRAINER (AI_FLAG_BASIC_TRAINER | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES)
|
||||
|
||||
// 'other' ai logic flags
|
||||
#define AI_FLAG_DYNAMIC_FUNC (1 << 28) // Create custom AI functions for specific battles via "setdynamicaifunc" cmd
|
||||
#define AI_FLAG_ROAMING (1 << 29)
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
|
||||
#include "config/general.h"
|
||||
#include "config/battle.h"
|
||||
#include "config/caps.h"
|
||||
#include "config/debug.h"
|
||||
#include "config/item.h"
|
||||
#include "config/level_caps.h"
|
||||
#include "config/pokemon.h"
|
||||
#include "config/overworld.h"
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
#define CONTEST_CATEGORIES_COUNT 5
|
||||
|
||||
// string lengths
|
||||
#define ITEM_NAME_LENGTH ((I_EXPANDED_ITEM_NAMES == TRUE) ? 20 : 14)
|
||||
#define ITEM_NAME_LENGTH 20
|
||||
#define ITEM_NAME_PLURAL_LENGTH ITEM_NAME_LENGTH + 2 // 2 is used for the instance where a word's suffix becomes y->ies
|
||||
#define POKEMON_NAME_LENGTH 12
|
||||
#define VANILLA_POKEMON_NAME_LENGTH 10
|
||||
@@ -78,14 +78,14 @@
|
||||
#define PLAYER_NAME_LENGTH 7
|
||||
#define MAIL_WORDS_COUNT 9
|
||||
#define EASY_CHAT_BATTLE_WORDS_COUNT 6
|
||||
#define MOVE_NAME_LENGTH ((B_EXPANDED_MOVE_NAMES == TRUE) ? 16 : 12)
|
||||
#define MOVE_NAME_LENGTH 16
|
||||
#define NUM_QUESTIONNAIRE_WORDS 4
|
||||
#define WONDER_CARD_TEXT_LENGTH 40
|
||||
#define WONDER_NEWS_TEXT_LENGTH 40
|
||||
#define WONDER_CARD_BODY_TEXT_LINES 4
|
||||
#define WONDER_NEWS_BODY_TEXT_LINES 10
|
||||
#define TYPE_NAME_LENGTH ((B_EXPANDED_TYPE_NAMES == TRUE) ? 8 : 6)
|
||||
#define ABILITY_NAME_LENGTH ((B_EXPANDED_ABILITY_NAMES == TRUE) ? 16 : 12)
|
||||
#define TYPE_NAME_LENGTH 8
|
||||
#define ABILITY_NAME_LENGTH 16
|
||||
#define TRAINER_NAME_LENGTH 10
|
||||
|
||||
#define MAX_STAMP_CARD_STAMPS 7
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
#define HOLD_EFFECT_EXP_SHARE 25
|
||||
#define HOLD_EFFECT_QUICK_CLAW 26
|
||||
#define HOLD_EFFECT_FRIENDSHIP_UP 27
|
||||
#define HOLD_EFFECT_CURE_ATTRACT 28
|
||||
#define HOLD_EFFECT_MENTAL_HERB HOLD_EFFECT_CURE_ATTRACT
|
||||
#define HOLD_EFFECT_MENTAL_HERB 28
|
||||
#define HOLD_EFFECT_CHOICE_BAND 29
|
||||
#define HOLD_EFFECT_FLINCH 30
|
||||
#define HOLD_EFFECT_BUG_POWER 31
|
||||
@@ -63,14 +62,12 @@
|
||||
#define HOLD_EFFECT_FIRE_POWER 58
|
||||
#define HOLD_EFFECT_DRAGON_POWER 59
|
||||
#define HOLD_EFFECT_NORMAL_POWER 60
|
||||
#define HOLD_EFFECT_UP_GRADE 61
|
||||
#define HOLD_EFFECT_UPGRADE HOLD_EFFECT_UP_GRADE
|
||||
#define HOLD_EFFECT_UPGRADE 61
|
||||
#define HOLD_EFFECT_SHELL_BELL 62
|
||||
#define HOLD_EFFECT_LUCKY_PUNCH 63
|
||||
#define HOLD_EFFECT_METAL_POWDER 64
|
||||
#define HOLD_EFFECT_THICK_CLUB 65
|
||||
#define HOLD_EFFECT_STICK 66
|
||||
#define HOLD_EFFECT_LEEK HOLD_EFFECT_STICK
|
||||
#define HOLD_EFFECT_LEEK 66
|
||||
|
||||
// Gen4 hold effects.
|
||||
#define HOLD_EFFECT_CHOICE_SCARF 67
|
||||
@@ -158,12 +155,12 @@
|
||||
// Gen9 hold effects
|
||||
#define HOLD_EFFECT_ABILITY_SHIELD 175
|
||||
#define HOLD_EFFECT_CLEAR_AMULET 176
|
||||
#define HOLD_EFFECT_MIRROR_HERB 177 // Not implemented.
|
||||
#define HOLD_EFFECT_MIRROR_HERB 177
|
||||
#define HOLD_EFFECT_PUNCHING_GLOVE 178
|
||||
#define HOLD_EFFECT_COVERT_CLOAK 179
|
||||
#define HOLD_EFFECT_LOADED_DICE 180
|
||||
#define HOLD_EFFECT_BOOSTER_ENERGY 181 // Not implemented.
|
||||
#define HOLD_EFFECT_MASK 183
|
||||
#define HOLD_EFFECT_BOOSTER_ENERGY 181
|
||||
#define HOLD_EFFECT_OGERPON_MASK 182
|
||||
|
||||
// Gen2 hold effect
|
||||
#define HOLD_EFFECT_BERSERK_GENE 184
|
||||
|
||||
@@ -162,7 +162,8 @@ enum RandomTag
|
||||
RNG_TRACE,
|
||||
RNG_FICKLE_BEAM,
|
||||
RNG_AI_ABILITY,
|
||||
RNG_AI_HASBADODDS,
|
||||
RNG_AI_SWITCH_HASBADODDS,
|
||||
RNG_AI_SWITCH_WONDER_GUARD,
|
||||
RNG_SHELL_SIDE_ARM,
|
||||
};
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ EWRAM_DATA AiScoreFunc sDynamicAiFunc = NULL;
|
||||
static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
|
||||
static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
|
||||
static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
|
||||
static s32 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
|
||||
static s32 AI_ForceSetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
|
||||
static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
|
||||
static s32 AI_PreferStrongestMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
|
||||
static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
|
||||
@@ -64,7 +64,7 @@ static s32 (*const sBattleAiFuncTable[])(u32, u32, u32, s32) =
|
||||
[0] = AI_CheckBadMove, // AI_FLAG_CHECK_BAD_MOVE
|
||||
[1] = AI_TryToFaint, // AI_FLAG_TRY_TO_FAINT
|
||||
[2] = AI_CheckViability, // AI_FLAG_CHECK_VIABILITY
|
||||
[3] = AI_SetupFirstTurn, // AI_FLAG_SETUP_FIRST_TURN
|
||||
[3] = AI_ForceSetupFirstTurn, // AI_FLAG_FORCE_SETUP_FIRST_TURN
|
||||
[4] = AI_Risky, // AI_FLAG_RISKY
|
||||
[5] = AI_PreferStrongestMove, // AI_FLAG_PREFER_STRONGEST_MOVE
|
||||
[6] = AI_PreferBatonPass, // AI_FLAG_PREFER_BATON_PASS
|
||||
@@ -196,14 +196,12 @@ void BattleAI_SetupFlags(void)
|
||||
else
|
||||
AI_THINKING_STRUCT->aiFlags[B_POSITION_PLAYER_LEFT] = 0; // player has no AI
|
||||
|
||||
#if DEBUG_OVERWORLD_MENU == TRUE
|
||||
if (gIsDebugBattle)
|
||||
if (DEBUG_OVERWORLD_MENU && gIsDebugBattle)
|
||||
{
|
||||
AI_THINKING_STRUCT->aiFlags[B_POSITION_OPPONENT_LEFT] = gDebugAIFlags;
|
||||
AI_THINKING_STRUCT->aiFlags[B_POSITION_OPPONENT_RIGHT] = gDebugAIFlags;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (IsWildMonSmart() && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_TRAINER)))
|
||||
{
|
||||
@@ -811,7 +809,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
s8 atkPriority = GetMovePriority(battlerAtk, move);
|
||||
u32 moveEffect = gMovesInfo[move].effect;
|
||||
s32 moveType;
|
||||
u32 moveTarget = AI_GetBattlerMoveTargetType(battlerAtk, move);
|
||||
u32 moveTarget = GetBattlerMoveTargetType(battlerAtk, move);
|
||||
struct AiLogicData *aiData = AI_DATA;
|
||||
u32 effectiveness = aiData->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex];
|
||||
bool32 isDoubleBattle = IsValidDoubleBattle(battlerAtk);
|
||||
@@ -854,6 +852,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
case EFFECT_COUNTER:
|
||||
case EFFECT_MIRROR_COAT:
|
||||
case EFFECT_METAL_BURST:
|
||||
case EFFECT_FINAL_GAMBIT:
|
||||
case EFFECT_GUARDIAN_OF_ALOLA:
|
||||
break;
|
||||
default:
|
||||
RETURN_SCORE_MINUS(10);
|
||||
@@ -886,7 +886,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
break;
|
||||
case ABILITY_WONDER_GUARD:
|
||||
if (effectiveness < AI_EFFECTIVENESS_x2)
|
||||
return 0;
|
||||
RETURN_SCORE_MINUS(20);
|
||||
break;
|
||||
case ABILITY_JUSTIFIED:
|
||||
if (moveType == TYPE_DARK && !IS_MOVE_STATUS(move))
|
||||
@@ -1495,7 +1495,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
break;
|
||||
case EFFECT_OHKO:
|
||||
if (B_SHEER_COLD_IMMUNITY >= GEN_7 && move == MOVE_SHEER_COLD && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE))
|
||||
return 0;
|
||||
RETURN_SCORE_MINUS(20);
|
||||
if (!ShouldTryOHKO(battlerAtk, battlerDef, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], move))
|
||||
ADJUST_SCORE(-10);
|
||||
else if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX)
|
||||
@@ -1528,6 +1528,16 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
else if (HasSubstituteIgnoringMove(battlerDef))
|
||||
ADJUST_SCORE(-8);
|
||||
break;
|
||||
case EFFECT_SHED_TAIL:
|
||||
if (CountUsablePartyMons(battlerAtk) == 0)
|
||||
ADJUST_SCORE(-10);
|
||||
if (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE || aiData->abilities[battlerDef] == ABILITY_INFILTRATOR)
|
||||
ADJUST_SCORE(-8);
|
||||
else if (aiData->hpPercents[battlerAtk] <= 50)
|
||||
ADJUST_SCORE(-10);
|
||||
else if (HasSubstituteIgnoringMove(battlerDef))
|
||||
ADJUST_SCORE(-8);
|
||||
break;
|
||||
case EFFECT_LEECH_SEED:
|
||||
if (gStatuses3[battlerDef] & STATUS3_LEECHSEED
|
||||
|| IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS)
|
||||
@@ -1815,6 +1825,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
break;
|
||||
case EFFECT_TRICK:
|
||||
case EFFECT_KNOCK_OFF:
|
||||
case EFFECT_CORROSIVE_GAS:
|
||||
if (aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD)
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
@@ -2163,6 +2174,17 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
else if (IsAbilityOfRating(aiData->abilities[battlerAtk], 5))
|
||||
ADJUST_SCORE(-4);
|
||||
break;
|
||||
case EFFECT_DOODLE: // Same as Role Play, but also check if the partner's ability should be replaced
|
||||
if (aiData->abilities[battlerAtk] == aiData->abilities[battlerDef]
|
||||
|| aiData->abilities[BATTLE_PARTNER(battlerAtk)] == aiData->abilities[battlerDef]
|
||||
|| aiData->abilities[battlerDef] == ABILITY_NONE
|
||||
|| gAbilitiesInfo[aiData->abilities[battlerAtk]].cantBeSuppressed
|
||||
|| gAbilitiesInfo[aiData->abilities[BATTLE_PARTNER(battlerAtk)]].cantBeSuppressed
|
||||
|| gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeCopied)
|
||||
ADJUST_SCORE(-10);
|
||||
else if (IsAbilityOfRating(aiData->abilities[battlerAtk], 5) || IsAbilityOfRating(aiData->abilities[BATTLE_PARTNER(battlerAtk)], 5))
|
||||
ADJUST_SCORE(-4);
|
||||
break;
|
||||
case EFFECT_WISH:
|
||||
if (gWishFutureKnock.wishCounter[battlerAtk] != 0)
|
||||
ADJUST_SCORE(-10);
|
||||
@@ -2483,7 +2505,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
|
||||
{
|
||||
if (gStatuses3[battlerDef] & STATUS3_HEAL_BLOCK)
|
||||
return 0;
|
||||
return 0; // cannot even select
|
||||
if (AtMaxHp(battlerDef))
|
||||
ADJUST_SCORE(-10);
|
||||
else if (gBattleMons[battlerDef].hp > gBattleMons[battlerDef].maxHP / 2)
|
||||
@@ -2544,7 +2566,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (AI_GetBattlerMoveTargetType(battlerDef, instructedMove) & (MOVE_TARGET_SELECTED
|
||||
if (GetBattlerMoveTargetType(battlerDef, instructedMove) & (MOVE_TARGET_SELECTED
|
||||
| MOVE_TARGET_DEPENDS
|
||||
| MOVE_TARGET_RANDOM
|
||||
| MOVE_TARGET_BOTH
|
||||
@@ -2742,7 +2764,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
// move data
|
||||
u32 moveType = gMovesInfo[move].type;
|
||||
u32 effect = gMovesInfo[move].effect;
|
||||
u32 moveTarget = AI_GetBattlerMoveTargetType(battlerAtk, move);
|
||||
u32 moveTarget = GetBattlerMoveTargetType(battlerAtk, move);
|
||||
// ally data
|
||||
u32 battlerAtkPartner = BATTLE_PARTNER(battlerAtk);
|
||||
struct AiLogicData *aiData = AI_DATA;
|
||||
@@ -2875,6 +2897,15 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
{
|
||||
switch (atkPartnerAbility)
|
||||
{
|
||||
case ABILITY_ANGER_POINT:
|
||||
if (gMovesInfo[move].alwaysCriticalHit == TRUE
|
||||
&& BattlerStatCanRise(battlerAtkPartner, atkPartnerAbility, STAT_ATK)
|
||||
&& AI_IsFaster(battlerAtk, battlerAtkPartner, move)
|
||||
&& !CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 1))
|
||||
{
|
||||
RETURN_SCORE_PLUS(GOOD_EFFECT);
|
||||
}
|
||||
break;
|
||||
case ABILITY_VOLT_ABSORB:
|
||||
if (!(AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_HP_AWARE))
|
||||
{
|
||||
@@ -3015,15 +3046,26 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
case EFFECT_SKILL_SWAP:
|
||||
if (aiData->abilities[battlerAtk] != aiData->abilities[BATTLE_PARTNER(battlerAtk)] && !attackerHasBadAbility)
|
||||
{
|
||||
// Partner abilities
|
||||
if (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_TRUANT)
|
||||
{
|
||||
RETURN_SCORE_PLUS(10);
|
||||
ADJUST_SCORE(10);
|
||||
}
|
||||
else if (aiData->abilities[battlerAtk] == ABILITY_COMPOUND_EYES
|
||||
&& HasMoveWithLowAccuracy(battlerAtkPartner, FOE(battlerAtkPartner), 90, TRUE, atkPartnerAbility, aiData->abilities[FOE(battlerAtkPartner)], atkPartnerHoldEffect, aiData->holdEffects[FOE(battlerAtkPartner)]))
|
||||
else if (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_INTIMIDATE)
|
||||
{
|
||||
RETURN_SCORE_PLUS(3);
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
// Active mon abilities
|
||||
if (aiData->abilities[battlerAtk] == ABILITY_COMPOUND_EYES
|
||||
&& HasMoveWithLowAccuracy(battlerAtkPartner, FOE(battlerAtkPartner), 90, TRUE, atkPartnerAbility, aiData->abilities[FOE(battlerAtkPartner)], atkPartnerHoldEffect, aiData->holdEffects[FOE(battlerAtkPartner)]))
|
||||
{
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
}
|
||||
else if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY && HasMoveThatLowersOwnStats(battlerAtkPartner))
|
||||
{
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
}
|
||||
return score;
|
||||
}
|
||||
break;
|
||||
case EFFECT_ROLE_PLAY:
|
||||
@@ -3064,7 +3106,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
|
||||
if (instructedMove != MOVE_NONE
|
||||
&& !IS_MOVE_STATUS(instructedMove)
|
||||
&& (AI_GetBattlerMoveTargetType(battlerAtkPartner, instructedMove) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) // Use instruct on multi-target moves
|
||||
&& (GetBattlerMoveTargetType(battlerAtkPartner, instructedMove) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) // Use instruct on multi-target moves
|
||||
{
|
||||
RETURN_SCORE_PLUS(WEAK_EFFECT);
|
||||
}
|
||||
@@ -3476,6 +3518,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
break;
|
||||
case EFFECT_MULTI_HIT:
|
||||
case EFFECT_TRIPLE_KICK:
|
||||
case EFFECT_POPULATION_BOMB:
|
||||
if (AI_MoveMakesContact(aiData->abilities[battlerAtk], aiData->holdEffects[battlerAtk], move)
|
||||
&& aiData->abilities[battlerAtk] != ABILITY_MAGIC_GUARD
|
||||
&& aiData->holdEffects[battlerDef] == HOLD_EFFECT_ROCKY_HELMET)
|
||||
@@ -3579,28 +3622,8 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
IncreaseParalyzeScore(battlerAtk, battlerDef, move, &score);
|
||||
break;
|
||||
case EFFECT_SUBSTITUTE:
|
||||
if (HasAnyKnownMove(battlerDef) && GetBestDmgFromBattler(battlerDef, battlerAtk) < gBattleMons[battlerAtk].maxHP / 4)
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
if (gStatuses3[battlerDef] & STATUS3_PERISH_SONG)
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
if (gBattleMons[battlerDef].status1 & STATUS1_SLEEP)
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
else if (gBattleMons[battlerDef].status1 & (STATUS1_BURN | STATUS1_PSN_ANY | STATUS1_FROSTBITE))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
// TODO:
|
||||
// if (IsPredictedToSwitch(battlerDef, battlerAtk)
|
||||
// ADJUST_SCORE(DECENT_EFFECT);
|
||||
if (HasMoveEffect(battlerDef, EFFECT_SLEEP)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_TOXIC)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_POISON)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_PARALYZE)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_WILL_O_WISP)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_CONFUSE)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_LEECH_SEED))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
if (!gBattleMons[battlerDef].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION && aiData->hpPercents[battlerAtk] > 70))
|
||||
ADJUST_SCORE(WEAK_EFFECT);
|
||||
break;
|
||||
case EFFECT_SHED_TAIL:
|
||||
IncreaseSubstituteMoveScore(battlerAtk, battlerDef, move, &score);
|
||||
case EFFECT_MIMIC:
|
||||
if (AI_IsFaster(battlerAtk, battlerDef, move))
|
||||
{
|
||||
@@ -3728,24 +3751,24 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score);
|
||||
break;
|
||||
case MOVE_WIDE_GUARD:
|
||||
if (predictedMove != MOVE_NONE && AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH))
|
||||
if (predictedMove != MOVE_NONE && GetBattlerMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH))
|
||||
{
|
||||
ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score);
|
||||
}
|
||||
else if (isDoubleBattle && AI_GetBattlerMoveTargetType(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) & MOVE_TARGET_FOES_AND_ALLY)
|
||||
else if (isDoubleBattle && GetBattlerMoveTargetType(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) & MOVE_TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
if (aiData->abilities[battlerAtk] != ABILITY_TELEPATHY)
|
||||
ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score);
|
||||
}
|
||||
break;
|
||||
case MOVE_CRAFTY_SHIELD:
|
||||
if (predictedMove != MOVE_NONE && IS_MOVE_STATUS(predictedMove) && !(AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER))
|
||||
if (predictedMove != MOVE_NONE && IS_MOVE_STATUS(predictedMove) && !(GetBattlerMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER))
|
||||
ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score);
|
||||
break;
|
||||
|
||||
case MOVE_MAT_BLOCK:
|
||||
if (gDisableStructs[battlerAtk].isFirstTurn && predictedMove != MOVE_NONE
|
||||
&& !IS_MOVE_STATUS(predictedMove) && !(AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER))
|
||||
&& !IS_MOVE_STATUS(predictedMove) && !(GetBattlerMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER))
|
||||
ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score);
|
||||
break;
|
||||
case MOVE_KINGS_SHIELD:
|
||||
@@ -4064,7 +4087,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
ADJUST_SCORE(DECENT_EFFECT); // Force 'em out next turn
|
||||
break;
|
||||
default:
|
||||
if (gMovesInfo[gCurrentMove].effect != EFFECT_BESTOW && aiData->items[battlerAtk] == ITEM_NONE)
|
||||
if (gMovesInfo[move].effect != EFFECT_BESTOW && aiData->items[battlerAtk] == ITEM_NONE && aiData->items[battlerDef] != ITEM_NONE)
|
||||
{
|
||||
switch (aiData->holdEffects[battlerDef])
|
||||
{
|
||||
@@ -4096,11 +4119,27 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EFFECT_CORROSIVE_GAS:
|
||||
if (CanKnockOffItem(battlerDef, aiData->items[battlerDef]))
|
||||
{
|
||||
switch (aiData->holdEffects[battlerDef])
|
||||
{
|
||||
case HOLD_EFFECT_IRON_BALL:
|
||||
if (HasMoveEffect(battlerDef, EFFECT_FLING))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case HOLD_EFFECT_LAGGING_TAIL:
|
||||
case HOLD_EFFECT_STICKY_BARB:
|
||||
break;
|
||||
default:
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EFFECT_ROLE_PLAY:
|
||||
if (!gAbilitiesInfo[aiData->abilities[battlerAtk]].cantBeSuppressed
|
||||
&& !gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeCopied
|
||||
&& !IsAbilityOfRating(aiData->abilities[battlerAtk], 5)
|
||||
&& IsAbilityOfRating(aiData->abilities[battlerDef], 5))
|
||||
case EFFECT_DOODLE:
|
||||
if (IsAbilityOfRating(aiData->abilities[battlerDef], 5))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case EFFECT_INGRAIN:
|
||||
@@ -4109,7 +4148,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
break;
|
||||
case EFFECT_MAGIC_COAT:
|
||||
if (IS_MOVE_STATUS(predictedMove) && AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_SELECTED | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH))
|
||||
if (IS_MOVE_STATUS(predictedMove) && GetBattlerMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_SELECTED | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
break;
|
||||
case EFFECT_RECYCLE:
|
||||
@@ -4788,7 +4827,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
|
||||
}
|
||||
|
||||
// Effects that are encouraged on the first turn of battle
|
||||
static s32 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
static s32 AI_ForceSetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
{
|
||||
u8 i;
|
||||
if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)
|
||||
|
||||
@@ -71,11 +71,11 @@ void GetAIPartyIndexes(u32 battler, s32 *firstId, s32 *lastId)
|
||||
static bool32 HasBadOdds(u32 battler, bool32 emitResult)
|
||||
{
|
||||
//Variable initialization
|
||||
u8 opposingPosition, atkType1, atkType2, defType1, defType2, effectiveness;
|
||||
u8 opposingPosition, atkType1, atkType2, defType1, defType2, effectiveness;
|
||||
s32 i, damageDealt = 0, maxDamageDealt = 0, damageTaken = 0, maxDamageTaken = 0;
|
||||
u32 aiMove, playerMove, aiBestMove = MOVE_NONE, aiAbility = AI_DATA->abilities[battler], opposingBattler, weather = AI_GetWeather(AI_DATA);
|
||||
bool32 getsOneShot = FALSE, hasStatusMove = FALSE, hasSuperEffectiveMove = FALSE;
|
||||
u16 typeEffectiveness = UQ_4_12(1.0), aiMoveEffect; //baseline typing damage
|
||||
u16 typeEffectiveness = UQ_4_12(1.0), aiMoveEffect; //baseline typing damage
|
||||
|
||||
// Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer
|
||||
if (!(AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_SWITCHING))
|
||||
@@ -85,14 +85,14 @@ static bool32 HasBadOdds(u32 battler, bool32 emitResult)
|
||||
if (IsDoubleBattle())
|
||||
return FALSE;
|
||||
|
||||
opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battler));
|
||||
opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battler));
|
||||
opposingBattler = GetBattlerAtPosition(opposingPosition);
|
||||
|
||||
// Gets types of player (opposingBattler) and computer (battler)
|
||||
atkType1 = gBattleMons[opposingBattler].types[0];
|
||||
atkType2 = gBattleMons[opposingBattler].types[1];
|
||||
defType1 = gBattleMons[battler].types[0];
|
||||
defType2 = gBattleMons[battler].types[1];
|
||||
atkType1 = gBattleMons[opposingBattler].types[0];
|
||||
atkType2 = gBattleMons[opposingBattler].types[1];
|
||||
defType1 = gBattleMons[battler].types[0];
|
||||
defType2 = gBattleMons[battler].types[1];
|
||||
|
||||
// Check AI moves for damage dealt
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
@@ -180,7 +180,7 @@ static bool32 HasBadOdds(u32 battler, bool32 emitResult)
|
||||
&& gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 4)))
|
||||
{
|
||||
// 50% chance to stay in regardless
|
||||
if (!RandomPercentage(RNG_AI_HASBADODDS, 50))
|
||||
if (!RandomPercentage(RNG_AI_SWITCH_HASBADODDS, 50))
|
||||
return FALSE;
|
||||
|
||||
// Switch mon out
|
||||
@@ -191,29 +191,29 @@ static bool32 HasBadOdds(u32 battler, bool32 emitResult)
|
||||
}
|
||||
|
||||
// General bad type matchups have more wiggle room
|
||||
if (typeEffectiveness >= UQ_4_12(2.0)) // If the player has at least a 2x type advantage
|
||||
{
|
||||
if (!hasSuperEffectiveMove // If the AI doesn't have a super effective move
|
||||
&& (gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 2 // And the current mon has at least 1/2 their HP, or 1/4 HP and Regenerator
|
||||
if (typeEffectiveness >= UQ_4_12(2.0)) // If the player has at least a 2x type advantage
|
||||
{
|
||||
if (!hasSuperEffectiveMove // If the AI doesn't have a super effective move
|
||||
&& (gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 2 // And the current mon has at least 1/2 their HP, or 1/4 HP and Regenerator
|
||||
|| (aiAbility == ABILITY_REGENERATOR
|
||||
&& gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 4)))
|
||||
{
|
||||
{
|
||||
// Then check if they have an important status move, which is worth using even in a bad matchup
|
||||
if (hasStatusMove)
|
||||
return FALSE;
|
||||
|
||||
// 50% chance to stay in regardless
|
||||
if (!RandomPercentage(RNG_AI_HASBADODDS, 50))
|
||||
if (!RandomPercentage(RNG_AI_SWITCH_HASBADODDS, 50))
|
||||
return FALSE;
|
||||
|
||||
// Switch mon out
|
||||
gBattleStruct->AI_monToSwitchIntoId[battler] = PARTY_SIZE;
|
||||
if (emitResult)
|
||||
gBattleStruct->AI_monToSwitchIntoId[battler] = PARTY_SIZE;
|
||||
if (emitResult)
|
||||
BtlController_EmitTwoReturnValues(battler, 1, B_ACTION_SWITCH, 0);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool32 ShouldSwitchIfAllBadMoves(u32 battler, bool32 emitResult)
|
||||
@@ -284,7 +284,7 @@ static bool32 ShouldSwitchIfWonderGuard(u32 battler, bool32 emitResult)
|
||||
move = GetMonData(&party[i], MON_DATA_MOVE1 + j);
|
||||
if (move != MOVE_NONE)
|
||||
{
|
||||
if (AI_GetTypeEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0) && Random() % 3 < 2)
|
||||
if (AI_GetTypeEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0) && (RandomPercentage(RNG_AI_SWITCH_WONDER_GUARD, 66) || ((AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_SWITCHING))))
|
||||
{
|
||||
// We found a mon.
|
||||
gBattleStruct->AI_monToSwitchIntoId[battler] = i;
|
||||
@@ -1609,8 +1609,8 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler)
|
||||
u16 maxHP = AI_DATA->switchinCandidate.battleMon.maxHP, item = AI_DATA->switchinCandidate.battleMon.item, heldItemEffect = ItemId_GetHoldEffect(item);
|
||||
u8 weatherDuration = gWishFutureKnock.weatherDuration, holdEffectParam = ItemId_GetHoldEffectParam(item);
|
||||
u32 opposingBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler)));
|
||||
u32 opposingAbility = gBattleMons[opposingBattler].ability;
|
||||
bool32 usedSingleUseHealingItem = FALSE;
|
||||
u32 opposingAbility = gBattleMons[opposingBattler].ability, ability = AI_DATA->switchinCandidate.battleMon.ability;
|
||||
bool32 usedSingleUseHealingItem = FALSE, opponentCanBreakMold = IsMoldBreakerTypeAbility(opposingBattler, opposingAbility);
|
||||
s32 currentHP = startingHP;
|
||||
|
||||
// No damage being dealt
|
||||
@@ -1631,6 +1631,10 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler)
|
||||
// Take attack damage for the turn
|
||||
currentHP = currentHP - damageTaken;
|
||||
|
||||
// One shot prevention effects
|
||||
if (damageTaken >= maxHP && currentHP == maxHP && (heldItemEffect == HOLD_EFFECT_FOCUS_SASH || (!opponentCanBreakMold && B_STURDY >= GEN_5 && ability == ABILITY_STURDY)))
|
||||
currentHP = 1;
|
||||
|
||||
// If mon is still alive, apply weather impact first, as it might KO the mon before it can heal with its item (order is weather -> item -> status)
|
||||
if (currentHP != 0)
|
||||
currentHP = currentHP - weatherImpact;
|
||||
@@ -1693,6 +1697,10 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler)
|
||||
hitsToKO++;
|
||||
}
|
||||
|
||||
// Disguise will always add an extra hit to KO
|
||||
if (opponentCanBreakMold && AI_DATA->switchinCandidate.battleMon.species == SPECIES_MIMIKYU_DISGUISED)
|
||||
hitsToKO++;
|
||||
|
||||
// If mon had a hypothetical status from TSpikes, clear it
|
||||
if (AI_DATA->switchinCandidate.hypotheticalStatus == TRUE)
|
||||
{
|
||||
@@ -2002,7 +2010,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
|
||||
}
|
||||
// If ace mon is the last available Pokemon and U-Turn/Volt Switch was used - switch to the mon.
|
||||
if (aceMonId != PARTY_SIZE
|
||||
&& (gMovesInfo[gLastUsedMove].effect == EFFECT_HIT_ESCAPE || gMovesInfo[gLastUsedMove].effect == EFFECT_PARTING_SHOT || gMovesInfo[gLastUsedMove].effect == EFFECT_BATON_PASS || gMovesInfo[gLastUsedMove].effect == EFFECT_CHILLY_RECEPTION))
|
||||
&& (gMovesInfo[gLastUsedMove].effect == EFFECT_HIT_ESCAPE || gMovesInfo[gLastUsedMove].effect == EFFECT_PARTING_SHOT || gMovesInfo[gLastUsedMove].effect == EFFECT_BATON_PASS || gMovesInfo[gLastUsedMove].effect == EFFECT_CHILLY_RECEPTION || gMovesInfo[gLastUsedMove].effect == EFFECT_SHED_TAIL))
|
||||
return aceMonId;
|
||||
|
||||
return PARTY_SIZE;
|
||||
|
||||
@@ -518,12 +518,16 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u
|
||||
{
|
||||
struct SimulatedDamage simDamage;
|
||||
s32 moveType;
|
||||
u32 moveEffect = gMovesInfo[move].effect;
|
||||
uq4_12_t effectivenessMultiplier;
|
||||
bool32 isDamageMoveUnusable = FALSE;
|
||||
bool32 toggledGimmick = FALSE;
|
||||
struct AiLogicData *aiData = AI_DATA;
|
||||
gBattleStruct->aiCalcInProgress = TRUE;
|
||||
|
||||
if (moveEffect == EFFECT_NATURE_POWER)
|
||||
move = GetNaturePowerMove(battlerAtk);
|
||||
|
||||
// Temporarily enable gimmicks for damage calcs if planned
|
||||
if (gBattleStruct->gimmick.usableGimmick[battlerAtk] && GetActiveGimmick(battlerAtk) == GIMMICK_NONE
|
||||
&& !(gBattleStruct->gimmick.usableGimmick[battlerAtk] == GIMMICK_Z_MOVE && !considerZPower))
|
||||
@@ -536,12 +540,25 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u
|
||||
SetActiveGimmick(battlerAtk, gBattleStruct->gimmick.usableGimmick[battlerAtk]);
|
||||
}
|
||||
|
||||
if (gMovesInfo[move].effect == EFFECT_PHOTON_GEYSER)
|
||||
gBattleStruct->swapDamageCategory = (GetCategoryBasedOnStats(gBattlerAttacker) != gMovesInfo[gCurrentMove].category);
|
||||
else if (gMovesInfo[move].effect == EFFECT_SHELL_SIDE_ARM)
|
||||
gBattleStruct->swapDamageCategory = (gBattleStruct->shellSideArmCategory[battlerAtk][battlerDef] != gMovesInfo[gCurrentMove].category);
|
||||
else if (gMovesInfo[move].effect == EFFECT_NATURE_POWER)
|
||||
move = GetNaturePowerMove(battlerAtk);
|
||||
moveEffect = gMovesInfo[move].effect;
|
||||
switch (moveEffect)
|
||||
{
|
||||
case EFFECT_PHOTON_GEYSER:
|
||||
gBattleStruct->swapDamageCategory = (GetCategoryBasedOnStats(battlerAtk) == DAMAGE_CATEGORY_PHYSICAL);
|
||||
break;
|
||||
case EFFECT_SHELL_SIDE_ARM:
|
||||
if (gBattleStruct->shellSideArmCategory[battlerAtk][battlerDef] == DAMAGE_CATEGORY_PHYSICAL)
|
||||
gBattleStruct->swapDamageCategory = TRUE;
|
||||
break;
|
||||
case EFFECT_TERA_BLAST:
|
||||
if (GetActiveGimmick(battlerAtk) == GIMMICK_TERA)
|
||||
gBattleStruct->swapDamageCategory = GetCategoryBasedOnStats(battlerAtk) == DAMAGE_CATEGORY_PHYSICAL;
|
||||
break;
|
||||
case EFFECT_TERA_STARSTORM:
|
||||
if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA && gBattleMons[gBattlerAttacker].species == SPECIES_TERAPAGOS_STELLAR)
|
||||
gBattleStruct->swapDamageCategory = GetCategoryBasedOnStats(battlerAtk) == DAMAGE_CATEGORY_PHYSICAL;
|
||||
break;
|
||||
}
|
||||
|
||||
gBattleStruct->dynamicMoveType = 0;
|
||||
|
||||
@@ -558,7 +575,7 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u
|
||||
|
||||
ProteanTryChangeType(battlerAtk, aiData->abilities[battlerAtk], move, moveType);
|
||||
// Certain moves like Rollout calculate damage based on values which change during the move execution, but before calling dmg calc.
|
||||
switch (gMovesInfo[move].effect)
|
||||
switch (moveEffect)
|
||||
{
|
||||
case EFFECT_ROLLOUT:
|
||||
n = gDisableStructs[battlerAtk].rolloutTimer - 1;
|
||||
@@ -605,7 +622,7 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u
|
||||
else
|
||||
{
|
||||
s32 nonCritDmg = 0;
|
||||
if (gMovesInfo[move].effect == EFFECT_TRIPLE_KICK)
|
||||
if (moveEffect == EFFECT_TRIPLE_KICK)
|
||||
{
|
||||
for (gMultiHitCounter = gMovesInfo[move].strikeCount; gMultiHitCounter > 0; gMultiHitCounter--) // The global is used to simulate actual damage done
|
||||
{
|
||||
@@ -629,7 +646,7 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u
|
||||
if (GetActiveGimmick(battlerAtk) != GIMMICK_Z_MOVE)
|
||||
{
|
||||
// Handle dynamic move damage
|
||||
switch (gMovesInfo[move].effect)
|
||||
switch (moveEffect)
|
||||
{
|
||||
case EFFECT_LEVEL_DAMAGE:
|
||||
simDamage.expected = simDamage.minimum = gBattleMons[battlerAtk].level * (aiData->abilities[battlerAtk] == ABILITY_PARENTAL_BOND ? 2 : 1);
|
||||
@@ -845,7 +862,7 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3
|
||||
case MOVE_EFFECT_SP_DEF_MINUS_2:
|
||||
case MOVE_EFFECT_ACC_MINUS_2:
|
||||
case MOVE_EFFECT_EVS_MINUS_2:
|
||||
if (ShouldLowerStat(battlerDef, abilityDef, STAT_ATK + (gMovesInfo[move].additionalEffects[i].moveEffect - MOVE_EFFECT_ATK_MINUS_1)) && noOfHitsToKo != 1)
|
||||
if (ShouldLowerStat(battlerDef, abilityDef, STAT_ATK + (gMovesInfo[move].additionalEffects[i].moveEffect - MOVE_EFFECT_ATK_MINUS_2)) && noOfHitsToKo != 1)
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
@@ -1096,6 +1113,26 @@ s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler, u32 moveConsidered)
|
||||
return AI_IS_SLOWER;
|
||||
}
|
||||
|
||||
static bool32 CanEndureHit(u32 battler, u32 battlerTarget, u32 move)
|
||||
{
|
||||
if (!BATTLER_MAX_HP(battlerTarget) || gMovesInfo[move].effect == EFFECT_MULTI_HIT)
|
||||
return FALSE;
|
||||
if (gMovesInfo[move].strikeCount > 1 && !(gMovesInfo[move].effect == EFFECT_DRAGON_DARTS && IsValidDoubleBattle(battlerTarget)))
|
||||
return FALSE;
|
||||
if (AI_DATA->holdEffects[battlerTarget] == HOLD_EFFECT_FOCUS_SASH)
|
||||
return TRUE;
|
||||
|
||||
if (!DoesBattlerIgnoreAbilityChecks(AI_DATA->abilities[battler], move))
|
||||
{
|
||||
if (B_STURDY >= GEN_5 && AI_DATA->abilities[battlerTarget] == ABILITY_STURDY)
|
||||
return TRUE;
|
||||
if (gBattleMons[battlerTarget].species == SPECIES_MIMIKYU_DISGUISED)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Check if target has means to faint ai mon.
|
||||
bool32 CanTargetFaintAi(u32 battlerDef, u32 battlerAtk)
|
||||
{
|
||||
@@ -1106,7 +1143,8 @@ bool32 CanTargetFaintAi(u32 battlerDef, u32 battlerAtk)
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(unusable & (1u << i))
|
||||
&& AI_DATA->simulatedDmg[battlerDef][battlerAtk][i].expected >= gBattleMons[battlerAtk].hp)
|
||||
&& AI_DATA->simulatedDmg[battlerDef][battlerAtk][i].expected >= gBattleMons[battlerAtk].hp
|
||||
&& !CanEndureHit(battlerDef, battlerAtk, moves[i]))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1193,7 +1231,13 @@ bool32 CanAIFaintTarget(u32 battlerAtk, u32 battlerDef, u32 numHits)
|
||||
dmg *= numHits;
|
||||
|
||||
if (gBattleMons[battlerDef].hp <= dmg)
|
||||
return TRUE;
|
||||
{
|
||||
if (numHits > 1)
|
||||
return TRUE;
|
||||
|
||||
if (!CanEndureHit(battlerAtk, battlerDef, moves[i]))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1388,14 +1432,6 @@ u32 AI_GetWeather(struct AiLogicData *aiData)
|
||||
return gBattleWeather;
|
||||
}
|
||||
|
||||
u32 AI_GetBattlerMoveTargetType(u32 battlerId, u32 move)
|
||||
{
|
||||
if (gMovesInfo[move].effect == EFFECT_EXPANDING_FORCE && AI_IsTerrainAffected(battlerId, STATUS_FIELD_PSYCHIC_TERRAIN))
|
||||
return MOVE_TARGET_BOTH;
|
||||
else
|
||||
return gMovesInfo[move].target;
|
||||
}
|
||||
|
||||
bool32 IsAromaVeilProtectedMove(u32 move)
|
||||
{
|
||||
switch (move)
|
||||
@@ -1913,13 +1949,14 @@ bool32 ShouldLowerEvasion(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|
||||
bool32 CanIndexMoveFaintTarget(u32 battlerAtk, u32 battlerDef, u32 index, u32 numHits)
|
||||
{
|
||||
s32 dmg;
|
||||
u16 *moves = gBattleMons[battlerAtk].moves;
|
||||
|
||||
if (numHits)
|
||||
dmg = AI_DATA->simulatedDmg[battlerAtk][battlerDef][index].expected * numHits;
|
||||
else
|
||||
dmg = AI_DATA->simulatedDmg[battlerAtk][battlerDef][index].minimum;
|
||||
|
||||
if (gBattleMons[battlerDef].hp <= dmg)
|
||||
if (gBattleMons[battlerDef].hp <= dmg && !CanEndureHit(battlerAtk, battlerDef, moves[index]))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
@@ -2080,6 +2117,26 @@ bool32 HasAnyKnownMove(u32 battlerId)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 HasMoveThatLowersOwnStats(u32 battlerId)
|
||||
{
|
||||
s32 i, j;
|
||||
u32 aiMove;
|
||||
u16 *moves = GetMovesArray(battlerId);
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
aiMove = moves[i];
|
||||
if (aiMove != MOVE_NONE && aiMove != MOVE_UNAVAILABLE)
|
||||
{
|
||||
for (j = 0; j < gMovesInfo[aiMove].numAdditionalEffects; j++)
|
||||
{
|
||||
if (IsSelfStatLoweringEffect(gMovesInfo[aiMove].additionalEffects[j].moveEffect) && gMovesInfo[aiMove].additionalEffects[j].self)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect)
|
||||
{
|
||||
s32 i;
|
||||
@@ -2096,7 +2153,7 @@ bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool
|
||||
if (ignoreStatus && IS_MOVE_STATUS(moves[i]))
|
||||
continue;
|
||||
else if ((!IS_MOVE_STATUS(moves[i]) && gMovesInfo[moves[i]].accuracy == 0)
|
||||
|| AI_GetBattlerMoveTargetType(battlerAtk, moves[i]) & (MOVE_TARGET_USER | MOVE_TARGET_OPPONENTS_FIELD))
|
||||
|| GetBattlerMoveTargetType(battlerAtk, moves[i]) & (MOVE_TARGET_USER | MOVE_TARGET_OPPONENTS_FIELD))
|
||||
continue;
|
||||
|
||||
if (AI_DATA->moveAccuracy[battlerAtk][battlerDef][i] <= accCheck)
|
||||
@@ -2196,7 +2253,7 @@ bool32 IsAttackBoostMoveEffect(u32 effect)
|
||||
switch (effect)
|
||||
{
|
||||
case EFFECT_ATTACK_UP:
|
||||
case EFFECT_ATTACK_UP_2:
|
||||
case EFFECT_ATTACK_UP_2:
|
||||
case EFFECT_ATTACK_ACCURACY_UP:
|
||||
case EFFECT_ATTACK_SPATK_UP:
|
||||
case EFFECT_DRAGON_DANCE:
|
||||
@@ -2216,34 +2273,34 @@ bool32 IsStatRaisingEffect(u32 effect)
|
||||
switch (effect)
|
||||
{
|
||||
case EFFECT_ATTACK_UP:
|
||||
case EFFECT_ATTACK_UP_2:
|
||||
case EFFECT_DEFENSE_UP:
|
||||
case EFFECT_DEFENSE_UP_2:
|
||||
case EFFECT_ATTACK_UP_2:
|
||||
case EFFECT_DEFENSE_UP:
|
||||
case EFFECT_DEFENSE_UP_2:
|
||||
case EFFECT_DEFENSE_UP_3:
|
||||
case EFFECT_SPEED_UP:
|
||||
case EFFECT_SPEED_UP_2:
|
||||
case EFFECT_SPECIAL_ATTACK_UP:
|
||||
case EFFECT_SPECIAL_ATTACK_UP_2:
|
||||
case EFFECT_SPEED_UP:
|
||||
case EFFECT_SPEED_UP_2:
|
||||
case EFFECT_SPECIAL_ATTACK_UP:
|
||||
case EFFECT_SPECIAL_ATTACK_UP_2:
|
||||
case EFFECT_SPECIAL_ATTACK_UP_3:
|
||||
case EFFECT_SPECIAL_DEFENSE_UP:
|
||||
case EFFECT_SPECIAL_DEFENSE_UP_2:
|
||||
case EFFECT_SPECIAL_DEFENSE_UP:
|
||||
case EFFECT_SPECIAL_DEFENSE_UP_2:
|
||||
case EFFECT_ACCURACY_UP:
|
||||
case EFFECT_ACCURACY_UP_2:
|
||||
case EFFECT_EVASION_UP:
|
||||
case EFFECT_EVASION_UP_2:
|
||||
case EFFECT_MINIMIZE:
|
||||
case EFFECT_DEFENSE_CURL:
|
||||
case EFFECT_CALM_MIND:
|
||||
case EFFECT_CALM_MIND:
|
||||
case EFFECT_COSMIC_POWER:
|
||||
case EFFECT_DRAGON_DANCE:
|
||||
case EFFECT_ACUPRESSURE:
|
||||
case EFFECT_SHELL_SMASH:
|
||||
case EFFECT_SHIFT_GEAR:
|
||||
case EFFECT_ATTACK_ACCURACY_UP:
|
||||
case EFFECT_ATTACK_SPATK_UP:
|
||||
case EFFECT_GROWTH:
|
||||
case EFFECT_COIL:
|
||||
case EFFECT_QUIVER_DANCE:
|
||||
case EFFECT_DRAGON_DANCE:
|
||||
case EFFECT_ACUPRESSURE:
|
||||
case EFFECT_SHELL_SMASH:
|
||||
case EFFECT_SHIFT_GEAR:
|
||||
case EFFECT_ATTACK_ACCURACY_UP:
|
||||
case EFFECT_ATTACK_SPATK_UP:
|
||||
case EFFECT_GROWTH:
|
||||
case EFFECT_COIL:
|
||||
case EFFECT_QUIVER_DANCE:
|
||||
case EFFECT_BULK_UP:
|
||||
case EFFECT_GEOMANCY:
|
||||
case EFFECT_STOCKPILE:
|
||||
@@ -2285,6 +2342,34 @@ bool32 IsStatLoweringEffect(u32 effect)
|
||||
}
|
||||
}
|
||||
|
||||
bool32 IsSelfStatLoweringEffect(u32 effect)
|
||||
{
|
||||
// Self stat lowering moves like Overheart, Superpower etc.
|
||||
switch (effect)
|
||||
{
|
||||
case MOVE_EFFECT_ATK_MINUS_1:
|
||||
case MOVE_EFFECT_DEF_MINUS_1:
|
||||
case MOVE_EFFECT_SPD_MINUS_1:
|
||||
case MOVE_EFFECT_SP_ATK_MINUS_1:
|
||||
case MOVE_EFFECT_SP_DEF_MINUS_1:
|
||||
case MOVE_EFFECT_EVS_MINUS_1:
|
||||
case MOVE_EFFECT_ACC_MINUS_1:
|
||||
case MOVE_EFFECT_ATK_MINUS_2:
|
||||
case MOVE_EFFECT_DEF_MINUS_2:
|
||||
case MOVE_EFFECT_SPD_MINUS_2:
|
||||
case MOVE_EFFECT_SP_ATK_MINUS_2:
|
||||
case MOVE_EFFECT_SP_DEF_MINUS_2:
|
||||
case MOVE_EFFECT_EVS_MINUS_2:
|
||||
case MOVE_EFFECT_ACC_MINUS_2:
|
||||
case MOVE_EFFECT_V_CREATE:
|
||||
case MOVE_EFFECT_ATK_DEF_DOWN:
|
||||
case MOVE_EFFECT_DEF_SPDEF_DOWN:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
bool32 HasDamagingMove(u32 battlerId)
|
||||
{
|
||||
u32 i;
|
||||
@@ -3735,11 +3820,14 @@ void IncreaseBurnScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score)
|
||||
|
||||
if (AI_CanBurn(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, AI_DATA->partnerMove))
|
||||
{
|
||||
ADJUST_SCORE_PTR(WEAK_EFFECT); // burning is good
|
||||
if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL))
|
||||
if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL)
|
||||
|| (!(AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_OMNISCIENT) // Not Omniscient but expects physical attacker
|
||||
&& gSpeciesInfo[gBattleMons[battlerDef].species].baseAttack >= gSpeciesInfo[gBattleMons[battlerDef].species].baseSpAttack + 10))
|
||||
{
|
||||
if (CanTargetFaintAi(battlerDef, battlerAtk))
|
||||
ADJUST_SCORE_PTR(DECENT_EFFECT); // burning the target to stay alive is cool
|
||||
if (gMovesInfo[GetBestDmgMoveFromBattler(battlerDef, battlerAtk)].category == DAMAGE_CATEGORY_PHYSICAL)
|
||||
ADJUST_SCORE_PTR(DECENT_EFFECT);
|
||||
else
|
||||
ADJUST_SCORE_PTR(WEAK_EFFECT);
|
||||
}
|
||||
|
||||
if (HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_BURN)
|
||||
@@ -3816,11 +3904,14 @@ void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score
|
||||
|
||||
if (AI_CanGiveFrostbite(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, AI_DATA->partnerMove))
|
||||
{
|
||||
ADJUST_SCORE_PTR(WEAK_EFFECT); // frostbite is good
|
||||
if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL))
|
||||
if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL)
|
||||
|| (!(AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_OMNISCIENT) // Not Omniscient but expects special attacker
|
||||
&& gSpeciesInfo[gBattleMons[battlerDef].species].baseSpAttack >= gSpeciesInfo[gBattleMons[battlerDef].species].baseAttack + 10))
|
||||
{
|
||||
if (CanTargetFaintAi(battlerDef, battlerAtk))
|
||||
ADJUST_SCORE_PTR(DECENT_EFFECT); // frostbiting the target to stay alive is cool
|
||||
if (gMovesInfo[GetBestDmgMoveFromBattler(battlerDef, battlerAtk)].category == DAMAGE_CATEGORY_SPECIAL)
|
||||
ADJUST_SCORE_PTR(DECENT_EFFECT);
|
||||
else
|
||||
ADJUST_SCORE_PTR(WEAK_EFFECT);
|
||||
}
|
||||
|
||||
if (HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_FROSTBITE)
|
||||
@@ -3987,3 +4078,42 @@ bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, st
|
||||
&& AI_IsFaster(battlerAtk, battlerAtkPartner, TRUE)
|
||||
&& HasMoveWithCategory(battlerAtkPartner, DAMAGE_CATEGORY_PHYSICAL));
|
||||
}
|
||||
|
||||
void IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score)
|
||||
{
|
||||
if (gMovesInfo[move].effect == EFFECT_SUBSTITUTE) // Substitute specific
|
||||
{
|
||||
if (HasAnyKnownMove(battlerDef) && GetBestDmgFromBattler(battlerDef, battlerAtk) < gBattleMons[battlerAtk].maxHP / 4)
|
||||
ADJUST_SCORE_PTR(GOOD_EFFECT);
|
||||
}
|
||||
else if (gMovesInfo[move].effect == EFFECT_SHED_TAIL) // Shed Tail specific
|
||||
{
|
||||
if ((ShouldPivot(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], move, AI_THINKING_STRUCT->movesetIndex))
|
||||
&& (HasAnyKnownMove(battlerDef) && (GetBestDmgFromBattler(battlerDef, battlerAtk) < gBattleMons[battlerAtk].maxHP / 2)))
|
||||
ADJUST_SCORE_PTR(BEST_EFFECT);
|
||||
}
|
||||
|
||||
if (gStatuses3[battlerDef] & STATUS3_PERISH_SONG)
|
||||
ADJUST_SCORE_PTR(GOOD_EFFECT);
|
||||
|
||||
if (gBattleMons[battlerDef].status1 & STATUS1_SLEEP)
|
||||
ADJUST_SCORE_PTR(GOOD_EFFECT);
|
||||
else if (gBattleMons[battlerDef].status1 & (STATUS1_BURN | STATUS1_PSN_ANY | STATUS1_FROSTBITE))
|
||||
ADJUST_SCORE_PTR(DECENT_EFFECT);
|
||||
|
||||
// TODO:
|
||||
// if (IsPredictedToSwitch(battlerDef, battlerAtk)
|
||||
// ADJUST_SCORE_PTR(DECENT_EFFECT);
|
||||
|
||||
if (HasMoveEffect(battlerDef, EFFECT_SLEEP)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_TOXIC)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_POISON)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_PARALYZE)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_WILL_O_WISP)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_CONFUSE)
|
||||
|| HasMoveEffect(battlerDef, EFFECT_LEECH_SEED))
|
||||
ADJUST_SCORE_PTR(GOOD_EFFECT);
|
||||
|
||||
if (AI_DATA->hpPercents[battlerAtk] > 70)
|
||||
ADJUST_SCORE_PTR(WEAK_EFFECT);
|
||||
}
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
#include "util.h"
|
||||
#include "constants/battle_anim.h"
|
||||
|
||||
#define IS_DOUBLE_BATTLE() (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
|
||||
static u8 GetBattlerSpriteFinal_Y(u8 battlerId, u16 species, bool8 a3);
|
||||
static void PlayerThrowBall_AnimTranslateLinear_WithFollowup(struct Sprite *sprite);
|
||||
static void AnimFastTranslateLinearWaitEnd(struct Sprite *sprite);
|
||||
@@ -738,11 +736,6 @@ bool8 IsBattlerSpritePresent(u8 battlerId)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool8 IsDoubleBattle(void)
|
||||
{
|
||||
return IS_DOUBLE_BATTLE();
|
||||
}
|
||||
|
||||
#define BG_ANIM_PAL_1 8
|
||||
#define BG_ANIM_PAL_2 9
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "bg.h"
|
||||
#include "string_util.h"
|
||||
#include "pokemon_icon.h"
|
||||
#include "level_caps.h"
|
||||
#include "caps.h"
|
||||
#include "m4a.h"
|
||||
#include "mail.h"
|
||||
#include "event_data.h"
|
||||
@@ -1144,10 +1144,10 @@ static void Cmd_attackcanceler(void)
|
||||
}
|
||||
|
||||
if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_OFF
|
||||
&& GetBattlerAbility(gBattlerAttacker) == ABILITY_PARENTAL_BOND
|
||||
&& IsMoveAffectedByParentalBond(gCurrentMove, gBattlerAttacker)
|
||||
&& !(gAbsentBattlerFlags & (1u << gBattlerTarget))
|
||||
&& GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE)
|
||||
&& GetBattlerAbility(gBattlerAttacker) == ABILITY_PARENTAL_BOND
|
||||
&& IsMoveAffectedByParentalBond(gCurrentMove, gBattlerAttacker)
|
||||
&& !(gAbsentBattlerFlags & (1u << gBattlerTarget))
|
||||
&& GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE)
|
||||
{
|
||||
gSpecialStatuses[gBattlerAttacker].parentalBondState = PARENTAL_BOND_1ST_HIT;
|
||||
gMultiHitCounter = 2;
|
||||
@@ -1188,16 +1188,40 @@ static void Cmd_attackcanceler(void)
|
||||
|
||||
if (!(gHitMarker & HITMARKER_OBEYS) && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))
|
||||
{
|
||||
switch (IsMonDisobedient())
|
||||
switch (gBattleStruct->obedienceResult)
|
||||
{
|
||||
case 0:
|
||||
case OBEYS:
|
||||
break;
|
||||
case 2:
|
||||
case DISOBEYS_LOAFS:
|
||||
// Randomly select, then print a disobedient string
|
||||
// B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = MOD(Random(), NUM_LOAF_STRINGS);
|
||||
gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround;
|
||||
gMoveResultFlags |= MOVE_RESULT_MISSED;
|
||||
return;
|
||||
case DISOBEYS_HITS_SELF:
|
||||
gBattlerTarget = gBattlerAttacker;
|
||||
gBattleMoveDamage = CalculateMoveDamage(MOVE_NONE, gBattlerAttacker, gBattlerAttacker, TYPE_MYSTERY, 40, FALSE, FALSE, TRUE);
|
||||
gBattlescriptCurrInstr = BattleScript_IgnoresAndHitsItself;
|
||||
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
|
||||
gHitMarker |= HITMARKER_OBEYS;
|
||||
return;
|
||||
default:
|
||||
case DISOBEYS_FALL_ASLEEP:
|
||||
gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep;
|
||||
gMoveResultFlags |= MOVE_RESULT_MISSED;
|
||||
return;
|
||||
case DISOBEYS_WHILE_ASLEEP:
|
||||
gBattlescriptCurrInstr = BattleScript_IgnoresWhileAsleep;
|
||||
gMoveResultFlags |= MOVE_RESULT_MISSED;
|
||||
return;
|
||||
case DISOBEYS_RANDOM_MOVE:
|
||||
gCalledMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos];
|
||||
SetAtkCancellerForCalledMove();
|
||||
gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove;
|
||||
gBattlerTarget = GetMoveTarget(gCalledMove, NO_TARGET_OVERRIDE);
|
||||
gHitMarker |= HITMARKER_DISOBEDIENT_MOVE;
|
||||
gHitMarker |= HITMARKER_OBEYS;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1281,6 +1305,7 @@ static void Cmd_attackcanceler(void)
|
||||
if ((gProtectStructs[gBattlerByTurnOrder[i]].stealMove) && gMovesInfo[gCurrentMove].snatchAffected)
|
||||
{
|
||||
gProtectStructs[gBattlerByTurnOrder[i]].stealMove = FALSE;
|
||||
gBattleStruct->snatchedMoveIsUsed = TRUE;
|
||||
gBattleScripting.battler = gBattlerByTurnOrder[i];
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_SnatchedMove;
|
||||
@@ -1569,9 +1594,8 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u
|
||||
break;
|
||||
}
|
||||
|
||||
if (gProtectStructs[battlerAtk].usedMicleBerry)
|
||||
if (gBattleStruct->usedMicleBerry & 1u << battlerAtk)
|
||||
{
|
||||
gProtectStructs[battlerAtk].usedMicleBerry = FALSE;
|
||||
if (atkAbility == ABILITY_RIPEN)
|
||||
calc = (calc * 140) / 100; // ripen gives 40% acc boost
|
||||
else
|
||||
@@ -1623,6 +1647,13 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u
|
||||
gBattlescriptCurrInstr = failInstr;
|
||||
else if (!JumpIfMoveAffectedByProtect(gCurrentMove))
|
||||
gBattlescriptCurrInstr = nextInstr;
|
||||
if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_DYNAMAX)
|
||||
{
|
||||
if (gProtectStructs[gBattlerTarget].maxGuarded)
|
||||
gBattlescriptCurrInstr = nextInstr;
|
||||
else
|
||||
AbilityBattleEffects(ABILITYEFFECT_ABSORBING, gBattlerTarget, 0, 0, gCurrentMove);
|
||||
}
|
||||
}
|
||||
else if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_2ND_HIT
|
||||
|| (gSpecialStatuses[gBattlerAttacker].multiHitOn
|
||||
@@ -4505,7 +4536,8 @@ static void MoveValuesCleanUp(void)
|
||||
gIsCriticalHit = FALSE;
|
||||
gBattleScripting.moveEffect = 0;
|
||||
gBattleCommunication[MISS_TYPE] = 0;
|
||||
gHitMarker &= ~HITMARKER_DESTINYBOND;
|
||||
if (!gMultiHitCounter)
|
||||
gHitMarker &= ~HITMARKER_DESTINYBOND;
|
||||
gHitMarker &= ~HITMARKER_SYNCHRONISE_EFFECT;
|
||||
}
|
||||
|
||||
@@ -5267,7 +5299,9 @@ static void Cmd_moveend(void)
|
||||
case MOVEEND_PROTECT_LIKE_EFFECT:
|
||||
if (gProtectStructs[gBattlerAttacker].touchedProtectLike)
|
||||
{
|
||||
if (gProtectStructs[gBattlerTarget].spikyShielded && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD)
|
||||
if (gProtectStructs[gBattlerTarget].spikyShielded
|
||||
&& gMovesInfo[gCurrentMove].effect != EFFECT_COUNTER
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD)
|
||||
{
|
||||
gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE;
|
||||
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 8;
|
||||
@@ -5842,17 +5876,18 @@ static void Cmd_moveend(void)
|
||||
&& gMultiHitCounter
|
||||
&& !(gMovesInfo[gCurrentMove].effect == EFFECT_PRESENT && gBattleStruct->presentBasePower == 0)) // Silly edge case
|
||||
{
|
||||
gBattleScripting.multihitString[4]++;
|
||||
if (--gMultiHitCounter == 0)
|
||||
{
|
||||
if (gMovesInfo[gCurrentMove].argument == MOVE_EFFECT_SCALE_SHOT && !NoAliveMonsForEitherParty())
|
||||
{
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_DefDownSpeedUp;
|
||||
}
|
||||
gMultiHitCounter--;
|
||||
if (!IsBattlerAlive(gBattlerTarget) && gMovesInfo[gCurrentMove].effect != EFFECT_DRAGON_DARTS)
|
||||
gMultiHitCounter = 0;
|
||||
|
||||
gBattleScripting.multihitString[4]++;
|
||||
if (gMultiHitCounter == 0)
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_MultiHitPrintStrings;
|
||||
if (gMovesInfo[gCurrentMove].argument == MOVE_EFFECT_SCALE_SHOT && !NoAliveMonsForEitherParty())
|
||||
gBattlescriptCurrInstr = BattleScript_ScaleShot;
|
||||
else
|
||||
gBattlescriptCurrInstr = BattleScript_MultiHitPrintStrings;
|
||||
effect = TRUE;
|
||||
}
|
||||
else
|
||||
@@ -5864,9 +5899,9 @@ static void Cmd_moveend(void)
|
||||
gBattlerTarget = BATTLE_PARTNER(gBattlerTarget); // Target the partner in doubles for second hit.
|
||||
|
||||
if (gBattleMons[gBattlerAttacker].hp
|
||||
&& gBattleMons[gBattlerTarget].hp
|
||||
&& (gChosenMove == MOVE_SLEEP_TALK || !(gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP))
|
||||
&& !(gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE))
|
||||
&& gBattleMons[gBattlerTarget].hp
|
||||
&& (gChosenMove == MOVE_SLEEP_TALK || (gChosenMove == MOVE_SNORE) || !(gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP))
|
||||
&& !(gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE))
|
||||
{
|
||||
if (gSpecialStatuses[gBattlerAttacker].parentalBondState)
|
||||
gSpecialStatuses[gBattlerAttacker].parentalBondState--;
|
||||
@@ -6103,22 +6138,23 @@ static void Cmd_moveend(void)
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_DANCER: // Special case because it's so annoying
|
||||
if (gMovesInfo[gCurrentMove].danceMove)
|
||||
if (gMovesInfo[gCurrentMove].danceMove && !gBattleStruct->snatchedMoveIsUsed)
|
||||
{
|
||||
u32 battler, nextDancer = 0;
|
||||
bool32 turnOnHitmarker = FALSE;
|
||||
bool32 hasDancerTriggered = FALSE;
|
||||
|
||||
for (battler = 0; battler < gBattlersCount; battler++)
|
||||
{
|
||||
if (gSpecialStatuses[battler].dancerUsedMove)
|
||||
{
|
||||
// in case a battler fails to act on a Dancer-called move
|
||||
turnOnHitmarker = TRUE;
|
||||
hasDancerTriggered = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(gMoveResultFlags & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE)
|
||||
|| (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE && !hasDancerTriggered)
|
||||
|| (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove && gBattleStruct->bouncedMoveIsUsed)))
|
||||
{ // Dance move succeeds
|
||||
// Set target for other Dancer mons; set bit so that mon cannot activate Dancer off of its own move
|
||||
@@ -6132,8 +6168,6 @@ static void Cmd_moveend(void)
|
||||
{
|
||||
if (GetBattlerAbility(battler) == ABILITY_DANCER && !gSpecialStatuses[battler].dancerUsedMove)
|
||||
{
|
||||
if (turnOnHitmarker)
|
||||
gHitMarker |= HITMARKER_ATTACKSTRING_PRINTED;
|
||||
if (!nextDancer || (gBattleMons[battler].speed < gBattleMons[nextDancer & 0x3].speed))
|
||||
nextDancer = battler | 0x4;
|
||||
}
|
||||
@@ -6233,11 +6267,10 @@ static void Cmd_moveend(void)
|
||||
DebugPrintfLevel(MGBA_LOG_WARN, "savedTargetCount is greater than 0! More calls to SaveBattlerTarget than RestoreBattlerTarget!");
|
||||
// #endif
|
||||
}
|
||||
|
||||
gBattleStruct->targetsDone[gBattlerAttacker] = 0;
|
||||
gProtectStructs[gBattlerAttacker].targetAffected = FALSE;
|
||||
gProtectStructs[gBattlerAttacker].shellTrap = FALSE;
|
||||
gBattleStruct->ateBoost[gBattlerAttacker] = 0;
|
||||
gBattleStruct->ateBoost[gBattlerAttacker] = FALSE;
|
||||
gStatuses3[gBattlerAttacker] &= ~STATUS3_ME_FIRST;
|
||||
gSpecialStatuses[gBattlerAttacker].gemBoost = FALSE;
|
||||
gSpecialStatuses[gBattlerAttacker].damagedMons = 0;
|
||||
@@ -6249,13 +6282,19 @@ static void Cmd_moveend(void)
|
||||
gBattleStruct->swapDamageCategory = FALSE;
|
||||
gBattleStruct->categoryOverride = FALSE;
|
||||
gBattleStruct->bouncedMoveIsUsed = FALSE;
|
||||
gBattleStruct->snatchedMoveIsUsed = FALSE;
|
||||
gBattleStruct->enduredDamage = 0;
|
||||
gBattleStruct->additionalEffectsCounter = 0;
|
||||
gBattleStruct->poisonPuppeteerConfusion = FALSE;
|
||||
gBattleStruct->fickleBeamBoosted = FALSE;
|
||||
gBattleStruct->distortedTypeMatchups = 0;
|
||||
gBattleStruct->usedMicleBerry &= ~(1u << gBattlerAttacker);
|
||||
if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
gBattleStruct->pledgeMove = FALSE;
|
||||
if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE)
|
||||
SetActiveGimmick(gBattlerAttacker, GIMMICK_NONE);
|
||||
gBattleStruct->distortedTypeMatchups = 0;
|
||||
if (B_CHARGE <= GEN_8 || moveType == TYPE_ELECTRIC)
|
||||
gStatuses3[gBattlerAttacker] &= ~(STATUS3_CHARGED_UP);
|
||||
memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts));
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
@@ -7014,7 +7053,7 @@ static void UpdateSentMonFlags(u32 battler)
|
||||
|
||||
static bool32 DoSwitchInEffectsForBattler(u32 battler)
|
||||
{
|
||||
u32 i;
|
||||
u32 i = 0;
|
||||
// Neutralizing Gas announces itself before hazards
|
||||
if (gBattleMons[battler].ability == ABILITY_NEUTRALIZING_GAS && gSpecialStatuses[battler].announceNeutralizingGas == 0)
|
||||
{
|
||||
@@ -7082,9 +7121,11 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler)
|
||||
}
|
||||
else if (IsBattlerAffectedByHazards(battler, TRUE))
|
||||
{
|
||||
i = GetBattlerAbility(battler);
|
||||
if (!(gBattleMons[battler].status1 & STATUS1_ANY)
|
||||
&& !IS_BATTLER_OF_TYPE(battler, TYPE_STEEL)
|
||||
&& GetBattlerAbility(battler) != ABILITY_IMMUNITY
|
||||
&& i != ABILITY_IMMUNITY
|
||||
&& i != ABILITY_PURIFYING_SALT
|
||||
&& !IsAbilityOnSide(battler, ABILITY_PASTEL_VEIL)
|
||||
&& !(gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD)
|
||||
&& !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN))
|
||||
@@ -7253,9 +7294,9 @@ static void Cmd_switchineffects(void)
|
||||
|
||||
static void Cmd_trainerslidein(void)
|
||||
{
|
||||
CMD_ARGS(u8 battler);
|
||||
CMD_ARGS(u8 position);
|
||||
|
||||
u32 battler = GetBattlerAtPosition(cmd->battler);
|
||||
u32 battler = GetBattlerForBattleScript(cmd->position);
|
||||
BtlController_EmitTrainerSlide(battler, BUFFER_A);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
|
||||
@@ -8462,6 +8503,10 @@ static void RemoveAllTerrains(void)
|
||||
BattleScriptPushCursor(); \
|
||||
gBattlescriptCurrInstr = battlescript; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
gBattlerAttacker = saveBattler; \
|
||||
} \
|
||||
return TRUE; \
|
||||
} \
|
||||
}
|
||||
@@ -8476,9 +8521,9 @@ static bool32 TryDefogClear(u32 battlerAtk, bool32 clear)
|
||||
struct SideTimer *sideTimer = &gSideTimers[i];
|
||||
u32 *sideStatuses = &gSideStatuses[i];
|
||||
|
||||
gBattlerAttacker = i; // For correct battle string. Ally's / Foe's
|
||||
if (GetBattlerSide(battlerAtk) != i)
|
||||
{
|
||||
gBattlerAttacker = i; // For correct battle string. Ally's / Foe's
|
||||
DEFOG_CLEAR(SIDE_STATUS_REFLECT, reflectTimer, BattleScript_SideStatusWoreOffReturn, MOVE_REFLECT);
|
||||
DEFOG_CLEAR(SIDE_STATUS_LIGHTSCREEN, lightscreenTimer, BattleScript_SideStatusWoreOffReturn, MOVE_LIGHT_SCREEN);
|
||||
DEFOG_CLEAR(SIDE_STATUS_MIST, mistTimer, BattleScript_SideStatusWoreOffReturn, MOVE_MIST);
|
||||
@@ -8487,6 +8532,7 @@ static bool32 TryDefogClear(u32 battlerAtk, bool32 clear)
|
||||
}
|
||||
if (B_DEFOG_EFFECT_CLEARING >= GEN_6)
|
||||
{
|
||||
gBattlerAttacker = i; // For correct battle string. Ally's / Foe's
|
||||
DEFOG_CLEAR(SIDE_STATUS_SPIKES, spikesAmount, BattleScript_SpikesDefog, 0);
|
||||
DEFOG_CLEAR(SIDE_STATUS_STEALTH_ROCK, stealthRockAmount, BattleScript_StealthRockDefog, 0);
|
||||
DEFOG_CLEAR(SIDE_STATUS_TOXIC_SPIKES, toxicSpikesAmount, BattleScript_ToxicSpikesDefog, 0);
|
||||
@@ -8747,29 +8793,40 @@ static bool32 ChangeOrderTargetAfterAttacker(void)
|
||||
{
|
||||
u32 i;
|
||||
u8 data[MAX_BATTLERS_COUNT];
|
||||
u8 actionsData[MAX_BATTLERS_COUNT];
|
||||
|
||||
if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)
|
||||
|| GetBattlerTurnOrderNum(gBattlerAttacker) + 1 == GetBattlerTurnOrderNum(gBattlerTarget))
|
||||
if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget))
|
||||
return FALSE;
|
||||
if (GetBattlerTurnOrderNum(gBattlerAttacker) + 1 == GetBattlerTurnOrderNum(gBattlerTarget))
|
||||
return B_AFTER_YOU_TURN_ORDER >= GEN_8;
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
|
||||
{
|
||||
data[i] = gBattlerByTurnOrder[i];
|
||||
actionsData[i] = gActionsByTurnOrder[i];
|
||||
}
|
||||
if (GetBattlerTurnOrderNum(gBattlerAttacker) == 0 && GetBattlerTurnOrderNum(gBattlerTarget) == 2)
|
||||
{
|
||||
gBattlerByTurnOrder[1] = gBattlerTarget;
|
||||
gActionsByTurnOrder[1] = actionsData[2];
|
||||
gBattlerByTurnOrder[2] = data[1];
|
||||
gBattlerByTurnOrder[3] = data[3];
|
||||
gActionsByTurnOrder[2] = actionsData[1];
|
||||
}
|
||||
else if (GetBattlerTurnOrderNum(gBattlerAttacker) == 0 && GetBattlerTurnOrderNum(gBattlerTarget) == 3)
|
||||
{
|
||||
gBattlerByTurnOrder[1] = gBattlerTarget;
|
||||
gActionsByTurnOrder[1] = actionsData[3];
|
||||
gBattlerByTurnOrder[2] = data[1];
|
||||
gActionsByTurnOrder[2] = actionsData[1];
|
||||
gBattlerByTurnOrder[3] = data[2];
|
||||
gActionsByTurnOrder[3] = actionsData[2];
|
||||
}
|
||||
else // Attacker == 1, Target == 3
|
||||
{
|
||||
gBattlerByTurnOrder[2] = gBattlerTarget;
|
||||
gActionsByTurnOrder[2] = actionsData[3];
|
||||
gBattlerByTurnOrder[3] = data[2];
|
||||
gActionsByTurnOrder[3] = actionsData[2];
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -9612,10 +9669,7 @@ static void Cmd_various(void)
|
||||
case VARIOUS_HANDLE_FORM_CHANGE:
|
||||
{
|
||||
VARIOUS_ARGS(u8 case_);
|
||||
if (GetBattlerSide(battler) == B_SIDE_OPPONENT)
|
||||
mon = &gEnemyParty[gBattlerPartyIndexes[battler]];
|
||||
else
|
||||
mon = &gPlayerParty[gBattlerPartyIndexes[battler]];
|
||||
mon = GetPartyBattlerData(battler);
|
||||
|
||||
// Change species.
|
||||
if (cmd->case_ == 0)
|
||||
@@ -9703,23 +9757,23 @@ static void Cmd_various(void)
|
||||
else
|
||||
{
|
||||
gSpecialStatuses[gBattlerTarget].instructedChosenTarget = *(gBattleStruct->moveTarget + gBattlerTarget) | 0x4;
|
||||
gBattlerAttacker = gBattlerTarget;
|
||||
gCalledMove = move;
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (gBattleMons[gBattlerAttacker].moves[i] == gCalledMove)
|
||||
if (gBattleMons[gBattlerTarget].moves[i] == gCalledMove)
|
||||
{
|
||||
gCurrMovePos = i;
|
||||
i = 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != 4 || gBattleMons[gBattlerAttacker].pp[gCurrMovePos] == 0)
|
||||
if (i != 4 || gBattleMons[gBattlerTarget].pp[gCurrMovePos] == 0)
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
else
|
||||
{
|
||||
gBattlerTarget = gBattleStruct->lastMoveTarget[gBattlerAttacker];
|
||||
gEffectBattler = gBattleStruct->lastMoveTarget[gBattlerTarget];
|
||||
gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED;
|
||||
gBattleStruct->atkCancellerTracker = 0;
|
||||
PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, battler, gBattlerPartyIndexes[battler]);
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
@@ -9855,7 +9909,6 @@ static void Cmd_various(void)
|
||||
{
|
||||
// Save sprite IDs, because trainer slide in will overwrite gBattlerSpriteIds variable.
|
||||
gBattleScripting.savedDmg = (gBattlerSpriteIds[battler] & 0xFF) | (gBattlerSpriteIds[BATTLE_PARTNER(battler)] << 8);
|
||||
HideBattlerShadowSprite(battler);
|
||||
}
|
||||
else if (cmd->case_ == 1)
|
||||
{
|
||||
@@ -10454,20 +10507,6 @@ static void Cmd_various(void)
|
||||
}
|
||||
return;
|
||||
}
|
||||
case VARIOUS_TRY_TAR_SHOT:
|
||||
{
|
||||
VARIOUS_ARGS(const u8 *failInstr);
|
||||
if (gDisableStructs[battler].tarShot)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
gDisableStructs[battler].tarShot = TRUE;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
case VARIOUS_CAN_TAR_SHOT_WORK:
|
||||
{
|
||||
VARIOUS_ARGS(const u8 *failInstr);
|
||||
@@ -10615,123 +10654,6 @@ static void Cmd_various(void)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
return;
|
||||
}
|
||||
case VARIOUS_TEATIME_TARGETS:
|
||||
{
|
||||
VARIOUS_ARGS(const u8 *jumpInstr);
|
||||
u32 count = 0;
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (IsTeatimeAffected(i))
|
||||
count++;
|
||||
}
|
||||
if (count == 0)
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr; // Teatime fails
|
||||
else
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
return;
|
||||
}
|
||||
case VARIOUS_TEATIME_INVUL:
|
||||
{
|
||||
VARIOUS_ARGS(const u8 *jumpInstr);
|
||||
if (ItemId_GetPocket(gBattleMons[battler].item) == POCKET_BERRIES && !(gStatuses3[gBattlerTarget] & (STATUS3_SEMI_INVULNERABLE)))
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
else
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
return;
|
||||
}
|
||||
case VARIOUS_TRY_WIND_RIDER_POWER:
|
||||
{
|
||||
VARIOUS_ARGS(const u8 *failInstr);
|
||||
u16 ability = GetBattlerAbility(battler);
|
||||
if (GetBattlerSide(battler) == GetBattlerSide(gBattlerAttacker)
|
||||
&& (ability == ABILITY_WIND_RIDER || ability == ABILITY_WIND_POWER))
|
||||
{
|
||||
gLastUsedAbility = ability;
|
||||
RecordAbilityBattle(battler, gLastUsedAbility);
|
||||
gBattlerAbility = gBattleScripting.battler = battler;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
case VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES:
|
||||
{
|
||||
VARIOUS_ARGS();
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
case VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES:
|
||||
{
|
||||
VARIOUS_ARGS();
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
case VARIOUS_STORE_HEALING_WISH:
|
||||
{
|
||||
VARIOUS_ARGS();
|
||||
if (gCurrentMove == MOVE_LUNAR_DANCE)
|
||||
gBattleStruct->storedLunarDance |= 1u << battler;
|
||||
else
|
||||
gBattleStruct->storedHealingWish |= 1u << battler;
|
||||
break;
|
||||
}
|
||||
case VARIOUS_HIT_SWITCH_TARGET_FAILED:
|
||||
{
|
||||
VARIOUS_ARGS();
|
||||
gBattleStruct->hitSwitchTargetFailed = TRUE;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
return;
|
||||
}
|
||||
case VARIOUS_TRY_REVIVAL_BLESSING:
|
||||
{
|
||||
VARIOUS_ARGS(const u8 *failInstr);
|
||||
u32 side = GetBattlerSide(gBattlerAttacker);
|
||||
u8 index = GetFirstFaintedPartyIndex(gBattlerAttacker);
|
||||
|
||||
// Move fails if there are no battlers to revive.
|
||||
if (index == PARTY_SIZE)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
return;
|
||||
}
|
||||
|
||||
// Battler selected! Revive and go to next instruction.
|
||||
if (gSelectedMonPartyId != PARTY_SIZE)
|
||||
{
|
||||
struct Pokemon *party = GetSideParty(side);
|
||||
|
||||
u16 hp = GetMonData(&party[gSelectedMonPartyId], MON_DATA_MAX_HP) / 2;
|
||||
BtlController_EmitSetMonData(gBattlerAttacker, BUFFER_A, REQUEST_HP_BATTLE, 1u << gSelectedMonPartyId, sizeof(hp), &hp);
|
||||
MarkBattlerForControllerExec(gBattlerAttacker);
|
||||
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gSelectedMonPartyId], MON_DATA_SPECIES));
|
||||
|
||||
// If an on-field battler is revived, it needs to be sent out again.
|
||||
if (IsDoubleBattle() &&
|
||||
gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)] == gSelectedMonPartyId)
|
||||
{
|
||||
gBattleScripting.battler = BATTLE_PARTNER(gBattlerAttacker);
|
||||
gBattleCommunication[MULTIUSE_STATE] = TRUE;
|
||||
}
|
||||
|
||||
gSelectedMonPartyId = PARTY_SIZE;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
return;
|
||||
}
|
||||
|
||||
// Open party menu, wait to go to next instruction.
|
||||
else
|
||||
{
|
||||
BtlController_EmitChoosePokemon(gBattlerAttacker, BUFFER_A, PARTY_ACTION_CHOOSE_FAINTED_MON, PARTY_SIZE, ABILITY_NONE, gBattleStruct->battlerPartyOrders[gBattlerAttacker]);
|
||||
MarkBattlerForControllerExec(gBattlerAttacker);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case VARIOUS_GET_BATTLERS_FOR_RECALL:
|
||||
{
|
||||
battler = 1;
|
||||
@@ -11227,7 +11149,7 @@ static void Cmd_jumpifnotfirstturn(void)
|
||||
|
||||
const u8 *jumpInstr = cmd->jumpInstr;
|
||||
|
||||
if (gDisableStructs[gBattlerAttacker].isFirstTurn)
|
||||
if (gDisableStructs[gBattlerAttacker].isFirstTurn && !(gSpecialStatuses[gBattlerAttacker].instructedChosenTarget))
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
else
|
||||
gBattlescriptCurrInstr = jumpInstr;
|
||||
@@ -11346,7 +11268,7 @@ static void Cmd_stockpiletohpheal(void)
|
||||
|
||||
const u8 *failInstr = cmd->failInstr;
|
||||
|
||||
if (gDisableStructs[gBattlerAttacker].stockpileCounter == 0)
|
||||
if (gDisableStructs[gBattlerAttacker].stockpileCounter == 0 && !gBattleStruct->snatchedMoveIsUsed)
|
||||
{
|
||||
gBattlescriptCurrInstr = failInstr;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWALLOW_FAILED;
|
||||
@@ -11362,14 +11284,22 @@ static void Cmd_stockpiletohpheal(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / (1 << (3 - gDisableStructs[gBattlerAttacker].stockpileCounter));
|
||||
if (gDisableStructs[gBattlerAttacker].stockpileCounter > 0)
|
||||
{
|
||||
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / (1 << (3 - gDisableStructs[gBattlerAttacker].stockpileCounter));
|
||||
gBattleScripting.animTurn = gDisableStructs[gBattlerAttacker].stockpileCounter;
|
||||
gBattleStruct->moveEffect2 = MOVE_EFFECT_STOCKPILE_WORE_OFF;
|
||||
}
|
||||
else // Snatched move
|
||||
{
|
||||
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 4;
|
||||
gBattleScripting.animTurn = 1;
|
||||
}
|
||||
|
||||
if (gBattleMoveDamage == 0)
|
||||
gBattleMoveDamage = 1;
|
||||
gBattleMoveDamage *= -1;
|
||||
|
||||
gBattleScripting.animTurn = gDisableStructs[gBattlerAttacker].stockpileCounter;
|
||||
gBattleStruct->moveEffect2 = MOVE_EFFECT_STOCKPILE_WORE_OFF;
|
||||
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
gBattlerTarget = gBattlerAttacker;
|
||||
}
|
||||
@@ -13831,7 +13761,10 @@ static void Cmd_setcharge(void)
|
||||
|
||||
u8 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
gStatuses3[battler] |= STATUS3_CHARGED_UP;
|
||||
gDisableStructs[battler].chargeTimer = 2;
|
||||
if (B_CHARGE < GEN_9)
|
||||
gDisableStructs[battler].chargeTimer = 2;
|
||||
else
|
||||
gDisableStructs[battler].chargeTimer = 0;
|
||||
gBattlescriptCurrInstr++;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
@@ -15463,7 +15396,7 @@ static void Cmd_trainerslideout(void)
|
||||
{
|
||||
CMD_ARGS(u8 position);
|
||||
|
||||
u32 battler = GetBattlerAtPosition(cmd->position);
|
||||
u32 battler = GetBattlerForBattleScript(cmd->position);
|
||||
BtlController_EmitTrainerSlideBack(battler, BUFFER_A);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
|
||||
@@ -15936,7 +15869,6 @@ static void TryUpdateRoundTurnOrder(void)
|
||||
for (i = 0; roundUsers[i] != 0xFF && i < 3; i++)
|
||||
{
|
||||
gBattlerByTurnOrder[currRounder] = roundUsers[i];
|
||||
gActionsByTurnOrder[currRounder] = gActionsByTurnOrder[roundUsers[i]];
|
||||
gProtectStructs[roundUsers[i]].quash = TRUE; // Make it so their turn order can't be changed again
|
||||
currRounder++;
|
||||
}
|
||||
@@ -15945,7 +15877,6 @@ static void TryUpdateRoundTurnOrder(void)
|
||||
for (i = 0; nonRoundUsers[i] != 0xFF && i < 3; i++)
|
||||
{
|
||||
gBattlerByTurnOrder[currRounder] = nonRoundUsers[i];
|
||||
gActionsByTurnOrder[currRounder] = gActionsByTurnOrder[nonRoundUsers[i]];
|
||||
currRounder++;
|
||||
}
|
||||
}
|
||||
@@ -15999,7 +15930,7 @@ void ApplyExperienceMultipliers(s32 *expAmount, u8 expGetterMonId, u8 faintedBat
|
||||
*expAmount = (*expAmount * 150) / 100;
|
||||
if (B_UNEVOLVED_EXP_MULTIPLIER >= GEN_6 && IsMonPastEvolutionLevel(&gPlayerParty[expGetterMonId]))
|
||||
*expAmount = (*expAmount * 4915) / 4096;
|
||||
if (B_AFFECTION_MECHANICS == TRUE && GetBattlerAffectionHearts(expGetterMonId) >= AFFECTION_FOUR_HEARTS)
|
||||
if (B_AFFECTION_MECHANICS == TRUE && GetMonAffectionHearts(&gPlayerParty[expGetterMonId]) >= AFFECTION_FOUR_HEARTS)
|
||||
*expAmount = (*expAmount * 4915) / 4096;
|
||||
if (CheckBagHasItem(ITEM_EXP_CHARM, 1)) //is also for other exp boosting Powers if/when implemented
|
||||
*expAmount = (*expAmount * 150) / 100;
|
||||
@@ -16476,7 +16407,7 @@ void BS_SetPledge(void)
|
||||
u32 i = 0;
|
||||
u32 k = 0;
|
||||
|
||||
if (gBattleStruct->pledgeMove)
|
||||
if (gBattleStruct->pledgeMove && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE))
|
||||
{
|
||||
PrepareStringBattle(STRINGID_USEDMOVE, gBattlerAttacker);
|
||||
gHitMarker |= HITMARKER_ATTACKSTRING_PRINTED;
|
||||
@@ -16505,6 +16436,8 @@ void BS_SetPledge(void)
|
||||
else if ((gChosenActionByBattler[partner] == B_ACTION_USE_MOVE)
|
||||
&& IsDoubleBattle()
|
||||
&& IsBattlerAlive(partner)
|
||||
&& GetBattlerTurnOrderNum(gBattlerAttacker) < GetBattlerTurnOrderNum(partner)
|
||||
&& !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
&& gCurrentMove != partnerMove
|
||||
&& gMovesInfo[partnerMove].effect == EFFECT_PLEDGE)
|
||||
{
|
||||
@@ -16543,8 +16476,8 @@ void BS_SetPledge(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleStruct->pledgeMove = FALSE;
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16914,7 +16847,7 @@ void BS_TryActivateGulpMissile(void)
|
||||
void BS_TryQuash(void)
|
||||
{
|
||||
NATIVE_ARGS(const u8 *failInstr);
|
||||
u32 i;
|
||||
u32 i, j;
|
||||
|
||||
// It's true if foe is faster, has a bigger priority, or switches
|
||||
if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget))
|
||||
@@ -16925,20 +16858,18 @@ void BS_TryQuash(void)
|
||||
|
||||
// If the above condition is not true, it means we are faster than the foe, so we can set the quash bit
|
||||
gProtectStructs[gBattlerTarget].quash = TRUE;
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
|
||||
// this implementation assumes turn order is correct when using Quash
|
||||
i = GetBattlerTurnOrderNum(gBattlerTarget);
|
||||
for (j = i + 1; j < gBattlersCount; j++)
|
||||
{
|
||||
gBattlerByTurnOrder[i] = i;
|
||||
}
|
||||
for (i = 0; i < gBattlersCount - 1; i++)
|
||||
{
|
||||
s32 j;
|
||||
for (j = i + 1; j < gBattlersCount; j++)
|
||||
{
|
||||
if (!gProtectStructs[i].quash
|
||||
&& !gProtectStructs[j].quash
|
||||
&& GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], FALSE) == -1)
|
||||
SwapTurnOrder(i, j);
|
||||
}
|
||||
// Gen 7- config makes target go last so that the order of quash targets is kept for the correct turn order
|
||||
// Gen 8+ config alters Turn Order of the target according to speed, dynamic speed should handle the rest
|
||||
if (B_QUASH_TURN_ORDER < GEN_8 || GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], FALSE) == -1)
|
||||
SwapTurnOrder(i, j);
|
||||
else
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
@@ -17017,3 +16948,160 @@ void BS_FickleBeamDamageCalculation(void)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
}
|
||||
|
||||
void BS_TryTarShot(void)
|
||||
{
|
||||
NATIVE_ARGS(const u8 *failInstr);
|
||||
if (gDisableStructs[gBattlerTarget].tarShot || GetActiveGimmick(gBattlerTarget) == GIMMICK_TERA)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
gDisableStructs[gBattlerTarget].tarShot = TRUE;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
}
|
||||
|
||||
void BS_JumpIfBlockedBySoundproof(void)
|
||||
{
|
||||
NATIVE_ARGS(u8 battler, const u8 *jumpInstr);
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
if (gMovesInfo[gCurrentMove].soundMove && GetBattlerAbility(battler) == ABILITY_SOUNDPROOF)
|
||||
{
|
||||
gLastUsedAbility = ABILITY_SOUNDPROOF;
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
RecordAbilityBattle(battler, gLastUsedAbility);
|
||||
gBattlerAbility = battler;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
}
|
||||
|
||||
void BS_TeatimeInvul(void)
|
||||
{
|
||||
NATIVE_ARGS(u8 battler, const u8 *jumpInstr);
|
||||
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
if (ItemId_GetPocket(gBattleMons[battler].item) == POCKET_BERRIES && !(gStatuses3[gBattlerTarget] & (STATUS3_SEMI_INVULNERABLE)))
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
else
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
}
|
||||
|
||||
void BS_TeatimeTargets(void)
|
||||
{
|
||||
NATIVE_ARGS(const u8 *failInstr);
|
||||
u32 count = 0, i;
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (IsTeatimeAffected(i))
|
||||
count++;
|
||||
}
|
||||
if (count == 0)
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
else
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
void BS_TryWindRiderPower(void)
|
||||
{
|
||||
NATIVE_ARGS(u8 battler, const u8 *failInstr);
|
||||
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
u16 ability = GetBattlerAbility(battler);
|
||||
if (GetBattlerSide(battler) == GetBattlerSide(gBattlerAttacker)
|
||||
&& (ability == ABILITY_WIND_RIDER || ability == ABILITY_WIND_POWER))
|
||||
{
|
||||
gLastUsedAbility = ability;
|
||||
RecordAbilityBattle(battler, gLastUsedAbility);
|
||||
gBattlerAbility = gBattleScripting.battler = battler;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
}
|
||||
|
||||
void BS_ActivateWeatherChangeAbilities(void)
|
||||
{
|
||||
NATIVE_ARGS(u8 battler);
|
||||
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0);
|
||||
}
|
||||
|
||||
void BS_ActivateTerrainChangeAbilities(void)
|
||||
{
|
||||
NATIVE_ARGS(u8 battler);
|
||||
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0);
|
||||
}
|
||||
|
||||
void BS_StoreHealingWish(void)
|
||||
{
|
||||
NATIVE_ARGS(u8 battler);
|
||||
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
if (gCurrentMove == MOVE_LUNAR_DANCE)
|
||||
gBattleStruct->storedLunarDance |= 1u << battler;
|
||||
else
|
||||
gBattleStruct->storedHealingWish |= 1u << battler;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
void BS_HitSwitchTargetFailed(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
gBattleStruct->hitSwitchTargetFailed = TRUE;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
void BS_TryRevivalBlessing(void)
|
||||
{
|
||||
NATIVE_ARGS(const u8 *failInstr);
|
||||
u32 side = GetBattlerSide(gBattlerAttacker);
|
||||
u8 index = GetFirstFaintedPartyIndex(gBattlerAttacker);
|
||||
|
||||
// Move fails if there are no battlers to revive.
|
||||
if (index == PARTY_SIZE)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
return;
|
||||
}
|
||||
|
||||
// Battler selected! Revive and go to next instruction.
|
||||
if (gSelectedMonPartyId != PARTY_SIZE)
|
||||
{
|
||||
struct Pokemon *party = GetSideParty(side);
|
||||
|
||||
u16 hp = GetMonData(&party[gSelectedMonPartyId], MON_DATA_MAX_HP) / 2;
|
||||
BtlController_EmitSetMonData(gBattlerAttacker, BUFFER_A, REQUEST_HP_BATTLE, 1u << gSelectedMonPartyId, sizeof(hp), &hp);
|
||||
MarkBattlerForControllerExec(gBattlerAttacker);
|
||||
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gSelectedMonPartyId], MON_DATA_SPECIES));
|
||||
|
||||
// If an on-field battler is revived, it needs to be sent out again.
|
||||
if (IsDoubleBattle() &&
|
||||
gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)] == gSelectedMonPartyId)
|
||||
{
|
||||
gBattleScripting.battler = BATTLE_PARTNER(gBattlerAttacker);
|
||||
gBattleCommunication[MULTIUSE_STATE] = TRUE;
|
||||
}
|
||||
|
||||
gSelectedMonPartyId = PARTY_SIZE;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Open party menu, wait to go to next instruction.
|
||||
BtlController_EmitChoosePokemon(gBattlerAttacker, BUFFER_A, PARTY_ACTION_CHOOSE_FAINTED_MON, PARTY_SIZE, ABILITY_NONE, gBattleStruct->battlerPartyOrders[gBattlerAttacker]);
|
||||
MarkBattlerForControllerExec(gBattlerAttacker);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +122,8 @@ void HandleAction_UseMove(void)
|
||||
gBattleScripting.savedMoveEffect = 0;
|
||||
gCurrMovePos = gChosenMovePos = *(gBattleStruct->chosenMovePositions + gBattlerAttacker);
|
||||
|
||||
gBattleStruct->obedienceResult = GetAttackerObedienceForAction();
|
||||
|
||||
// choose move
|
||||
if (gProtectStructs[gBattlerAttacker].noValidMoves)
|
||||
{
|
||||
@@ -325,7 +327,7 @@ void HandleAction_UseMove(void)
|
||||
else
|
||||
{
|
||||
gBattlerTarget = *(gBattleStruct->moveTarget + gBattlerAttacker);
|
||||
if (!IsBattlerAlive(gBattlerTarget))
|
||||
if (!IsBattlerAlive(gBattlerTarget) && moveTarget != MOVE_TARGET_OPPONENTS_FIELD)
|
||||
{
|
||||
if (GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget))
|
||||
{
|
||||
@@ -1212,15 +1214,15 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler)
|
||||
{
|
||||
gBattleScripting.battler = battler;
|
||||
gCurrentMove = move;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingDisabledMove;
|
||||
limitations++;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingDisabledMove;
|
||||
limitations++;
|
||||
}
|
||||
|
||||
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && move == gLastMoves[battler] && move != MOVE_STRUGGLE && (gBattleMons[battler].status2 & STATUS2_TORMENT))
|
||||
{
|
||||
CancelMultiTurnMoves(battler);
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingTormentedMove;
|
||||
limitations++;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingTormentedMove;
|
||||
limitations++;
|
||||
}
|
||||
|
||||
if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[battler].tauntTimer != 0 && IS_MOVE_STATUS(move))
|
||||
@@ -1229,58 +1231,58 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler)
|
||||
gCurrentMove = MOVE_MAX_GUARD;
|
||||
else
|
||||
gCurrentMove = move;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedMoveTaunt;
|
||||
limitations++;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedMoveTaunt;
|
||||
limitations++;
|
||||
}
|
||||
|
||||
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[battler].throatChopTimer != 0 && gMovesInfo[move].soundMove)
|
||||
{
|
||||
gCurrentMove = move;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedMoveThroatChop;
|
||||
limitations++;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedMoveThroatChop;
|
||||
limitations++;
|
||||
}
|
||||
|
||||
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && GetImprisonedMovesCount(battler, move))
|
||||
{
|
||||
gCurrentMove = move;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingImprisonedMove;
|
||||
limitations++;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingImprisonedMove;
|
||||
limitations++;
|
||||
}
|
||||
|
||||
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && IsGravityPreventingMove(move))
|
||||
{
|
||||
gCurrentMove = move;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedMoveGravity;
|
||||
limitations++;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedMoveGravity;
|
||||
limitations++;
|
||||
}
|
||||
|
||||
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && IsHealBlockPreventingMove(battler, move))
|
||||
{
|
||||
gCurrentMove = move;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedMoveHealBlock;
|
||||
limitations++;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedMoveHealBlock;
|
||||
limitations++;
|
||||
}
|
||||
|
||||
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && IsBelchPreventingMove(battler, move))
|
||||
{
|
||||
gCurrentMove = move;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedBelch;
|
||||
limitations++;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedBelch;
|
||||
limitations++;
|
||||
}
|
||||
|
||||
if (DYNAMAX_BYPASS_CHECK && gMovesInfo[move].effect == EFFECT_STUFF_CHEEKS && ItemId_GetPocket(gBattleMons[battler].item) != POCKET_BERRIES)
|
||||
{
|
||||
gCurrentMove = move;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedStuffCheeks;
|
||||
limitations++;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedStuffCheeks;
|
||||
limitations++;
|
||||
}
|
||||
|
||||
if (gMovesInfo[move].cantUseTwice && move == gLastResultingMoves[battler])
|
||||
{
|
||||
gCurrentMove = move;
|
||||
PREPARE_MOVE_BUFFER(gBattleTextBuff1, gCurrentMove);
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedCurrentMove;
|
||||
limitations++;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedCurrentMove;
|
||||
limitations++;
|
||||
}
|
||||
|
||||
gPotentialItemEffectBattler = battler;
|
||||
@@ -1288,8 +1290,8 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler)
|
||||
{
|
||||
gCurrentMove = *choicedMove;
|
||||
gLastUsedItem = gBattleMons[battler].item;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedMoveChoiceItem;
|
||||
limitations++;
|
||||
gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedMoveChoiceItem;
|
||||
limitations++;
|
||||
}
|
||||
else if (holdEffect == HOLD_EFFECT_ASSAULT_VEST && IS_MOVE_STATUS(move) && gMovesInfo[move].effect != EFFECT_ME_FIRST)
|
||||
{
|
||||
@@ -2127,8 +2129,8 @@ enum
|
||||
ENDTURN_HEALBLOCK,
|
||||
ENDTURN_EMBARGO,
|
||||
ENDTURN_LOCK_ON,
|
||||
ENDTURN_CHARGE,
|
||||
ENDTURN_LASER_FOCUS,
|
||||
ENDTURN_CHARGE,
|
||||
ENDTURN_TAUNT,
|
||||
ENDTURN_YAWN,
|
||||
ENDTURN_ITEMS2,
|
||||
@@ -2145,6 +2147,7 @@ enum
|
||||
ENDTURN_DYNAMAX,
|
||||
ENDTURN_GMAX_MOVE_RESIDUAL_DAMAGE,
|
||||
ENDTURN_SEA_OF_FIRE_DAMAGE,
|
||||
ENDTURN_ITEMS3,
|
||||
ENDTURN_BATTLER_COUNT
|
||||
};
|
||||
|
||||
@@ -2277,6 +2280,15 @@ u8 DoBattlerEndTurnEffects(void)
|
||||
effect++;
|
||||
gBattleStruct->turnEffectsTracker++;
|
||||
break;
|
||||
case ENDTURN_ITEMS3: // berry effects
|
||||
if (gItemsInfo[gBattleMons[battler].item].pocket == POCKET_BERRIES
|
||||
|| GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_RESTORE_HP) // Edge case for Berry Juice
|
||||
{
|
||||
if (ItemBattleEffects(ITEMEFFECT_NORMAL, battler, FALSE))
|
||||
effect++;
|
||||
}
|
||||
gBattleStruct->turnEffectsTracker++;
|
||||
break;
|
||||
case ENDTURN_ORBS:
|
||||
if (IsBattlerAlive(battler) && ItemBattleEffects(ITEMEFFECT_ORBS, battler, FALSE))
|
||||
effect++;
|
||||
@@ -2591,7 +2603,7 @@ u8 DoBattlerEndTurnEffects(void)
|
||||
gBattleStruct->turnEffectsTracker++;
|
||||
break;
|
||||
case ENDTURN_CHARGE: // charge
|
||||
if (gDisableStructs[battler].chargeTimer && --gDisableStructs[battler].chargeTimer == 0)
|
||||
if (gDisableStructs[battler].chargeTimer > 0 && --gDisableStructs[battler].chargeTimer == 0)
|
||||
gStatuses3[battler] &= ~STATUS3_CHARGED_UP;
|
||||
gBattleStruct->turnEffectsTracker++;
|
||||
break;
|
||||
@@ -2708,9 +2720,11 @@ u8 DoBattlerEndTurnEffects(void)
|
||||
case ENDTURN_ELECTRIFY:
|
||||
gStatuses4[battler] &= ~STATUS4_ELECTRIFIED;
|
||||
gBattleStruct->turnEffectsTracker++;
|
||||
break;
|
||||
case ENDTURN_POWDER:
|
||||
gBattleMons[battler].status2 &= ~STATUS2_POWDER;
|
||||
gBattleStruct->turnEffectsTracker++;
|
||||
break;
|
||||
case ENDTURN_THROAT_CHOP:
|
||||
if (gDisableStructs[battler].throatChopTimer && --gDisableStructs[battler].throatChopTimer == 0)
|
||||
{
|
||||
@@ -2778,7 +2792,7 @@ u8 DoBattlerEndTurnEffects(void)
|
||||
&& --gBattleStruct->dynamax.dynamaxTurns[battler] == 0)
|
||||
{
|
||||
gBattleScripting.battler = battler;
|
||||
UndoDynamax(battler);
|
||||
UndoDynamax(battler);
|
||||
BattleScriptExecute(BattleScript_DynamaxEnds);
|
||||
effect++;
|
||||
}
|
||||
@@ -3041,7 +3055,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
|
||||
case CANCELLER_FLAGS: // flags clear
|
||||
gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_DESTINY_BOND;
|
||||
gStatuses3[gBattlerAttacker] &= ~STATUS3_GRUDGE;
|
||||
gStatuses4[gBattlerAttacker] &= ~ STATUS4_GLAIVE_RUSH;
|
||||
gStatuses4[gBattlerAttacker] &= ~STATUS4_GLAIVE_RUSH;
|
||||
gBattleStruct->atkCancellerTracker++;
|
||||
break;
|
||||
case CANCELLER_SKY_DROP:
|
||||
@@ -3104,7 +3118,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
|
||||
if (!RandomPercentage(RNG_FROZEN, 20))
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_MoveUsedIsFrozen;
|
||||
gHitMarker |= HITMARKER_NO_ATTACKSTRING;
|
||||
gHitMarker |= (HITMARKER_NO_ATTACKSTRING | HITMARKER_UNABLE_TO_USE_MOVE);
|
||||
}
|
||||
else // unfreeze
|
||||
{
|
||||
@@ -3366,11 +3380,21 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
|
||||
case CANCELLER_POWDER_STATUS:
|
||||
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_POWDER)
|
||||
{
|
||||
if (moveType == TYPE_FIRE)
|
||||
u32 partnerMove = gBattleMons[BATTLE_PARTNER(gBattlerAttacker)].moves[gBattleStruct->chosenMovePositions[BATTLE_PARTNER(gBattlerAttacker)]];
|
||||
if ((moveType == TYPE_FIRE && !gBattleStruct->pledgeMove)
|
||||
|| (gCurrentMove == MOVE_FIRE_PLEDGE && partnerMove == MOVE_GRASS_PLEDGE)
|
||||
|| (gCurrentMove == MOVE_GRASS_PLEDGE && partnerMove == MOVE_FIRE_PLEDGE && gBattleStruct->pledgeMove))
|
||||
{
|
||||
gProtectStructs[gBattlerAttacker].powderSelfDmg = TRUE;
|
||||
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 4;
|
||||
gBattlescriptCurrInstr = BattleScript_MoveUsedPowder;
|
||||
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD
|
||||
&& (B_POWDER_RAIN < GEN_7 || !IsBattlerWeatherAffected(gBattlerAttacker, B_WEATHER_RAIN_PRIMAL)))
|
||||
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 4;
|
||||
|
||||
if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE
|
||||
|| gBattleStruct->obedienceResult != OBEYS
|
||||
|| HasTrainerUsedGimmick(gBattlerAttacker, GIMMICK_Z_MOVE))
|
||||
gBattlescriptCurrInstr = BattleScript_MoveUsedPowder;
|
||||
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
|
||||
effect = 1;
|
||||
}
|
||||
}
|
||||
@@ -3388,7 +3412,8 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
|
||||
gBattleStruct->atkCancellerTracker++;
|
||||
break;
|
||||
case CANCELLER_Z_MOVES:
|
||||
if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE)
|
||||
if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE
|
||||
&& gBattleStruct->obedienceResult == OBEYS)
|
||||
{
|
||||
// For Z-Mirror Move, so it doesn't play the animation twice.
|
||||
bool32 alreadyUsed = HasTrainerUsedGimmick(gBattlerAttacker, GIMMICK_Z_MOVE);
|
||||
@@ -3398,7 +3423,15 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
|
||||
SetGimmickAsActivated(gBattlerAttacker, GIMMICK_Z_MOVE);
|
||||
|
||||
gBattleScripting.battler = gBattlerAttacker;
|
||||
if (gMovesInfo[gCurrentMove].category == DAMAGE_CATEGORY_STATUS)
|
||||
if (gProtectStructs[gBattlerAttacker].powderSelfDmg)
|
||||
{
|
||||
if (!alreadyUsed)
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_ZMoveActivatePowder;
|
||||
}
|
||||
}
|
||||
else if (gMovesInfo[gCurrentMove].category == DAMAGE_CATEGORY_STATUS)
|
||||
{
|
||||
if (!alreadyUsed)
|
||||
{
|
||||
@@ -4157,13 +4190,10 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
|
||||
if (gSpecialStatuses[battler].switchInAbilityDone)
|
||||
break;
|
||||
if (gBattleResources->flags->flags[battler] & RESOURCE_FLAG_TRACED)
|
||||
break;
|
||||
|
||||
side = (BATTLE_OPPOSITE(GetBattlerPosition(battler))) & BIT_SIDE;
|
||||
target1 = GetBattlerAtPosition(side);
|
||||
target2 = GetBattlerAtPosition(side + BIT_FLANK);
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
if (IsDoubleBattle())
|
||||
{
|
||||
if (!gAbilitiesInfo[gBattleMons[target1].ability].cantBeTraced && gBattleMons[target1].hp != 0
|
||||
@@ -4182,11 +4212,10 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
|
||||
if (effect != 0)
|
||||
{
|
||||
BattleScriptPushCursorAndCallback(BattleScript_TraceActivatesEnd3);
|
||||
gBattleResources->flags->flags[battler] &= ~RESOURCE_FLAG_TRACED;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_TraceActivates);
|
||||
gBattleStruct->tracedAbility[battler] = gLastUsedAbility = gBattleMons[chosenTarget].ability;
|
||||
RecordAbilityBattle(chosenTarget, gLastUsedAbility); // Record the opposing battler has this ability
|
||||
battler = gBattlerAbility = gBattleScripting.battler = battler;
|
||||
gBattlerAbility = battler;
|
||||
|
||||
PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, chosenTarget, gBattlerPartyIndexes[chosenTarget])
|
||||
PREPARE_ABILITY_BUFFER(gBattleTextBuff2, gLastUsedAbility)
|
||||
@@ -5003,7 +5032,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
break;
|
||||
case ABILITY_GOOD_AS_GOLD:
|
||||
if (IS_MOVE_STATUS(gCurrentMove)
|
||||
&& !(moveTarget & MOVE_TARGET_USER)
|
||||
&& !(moveTarget & MOVE_TARGET_OPPONENTS_FIELD)
|
||||
&& !(moveTarget & MOVE_TARGET_ALL_BATTLERS))
|
||||
effect = 3;
|
||||
@@ -5119,6 +5147,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
}
|
||||
if (caseID == ABILITYEFFECT_WOULD_ABSORB)
|
||||
{
|
||||
gBattleStruct->pledgeMove = FALSE;
|
||||
if (effect && gLastUsedAbility != 0xFFFF)
|
||||
RecordAbilityBattle(battler, gLastUsedAbility);
|
||||
|
||||
@@ -5126,6 +5155,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
}
|
||||
else if (effect == 1) // Drain Hp ability.
|
||||
{
|
||||
gBattleStruct->pledgeMove = FALSE;
|
||||
if (BATTLER_MAX_HP(battler) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battler] & STATUS3_HEAL_BLOCK))
|
||||
{
|
||||
if ((gProtectStructs[gBattlerAttacker].notFirstStrike))
|
||||
@@ -5148,6 +5178,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
}
|
||||
else if (effect == 2) // Boost Stat ability;
|
||||
{
|
||||
gBattleStruct->pledgeMove = FALSE;
|
||||
if (!CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
if ((gProtectStructs[gBattlerAttacker].notFirstStrike))
|
||||
@@ -5169,6 +5200,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
}
|
||||
else if (effect == 3)
|
||||
{
|
||||
gBattleStruct->pledgeMove = FALSE;
|
||||
if (!(gBattleResources->flags->flags[battler] & RESOURCE_FLAG_FLASH_FIRE))
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_BOOST;
|
||||
@@ -5739,7 +5771,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& HadMoreThanHalfHpNowDoesnt(gBattlerTarget)
|
||||
&& !(TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove)))
|
||||
{
|
||||
gBattlerAttacker = gBattlerTarget;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_AngerShellActivates;
|
||||
effect++;
|
||||
@@ -5860,7 +5891,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (IsBattlerAlive(battler)
|
||||
&& (gMovesInfo[gCurrentMove].danceMove)
|
||||
&& !gSpecialStatuses[battler].dancerUsedMove
|
||||
&& (gHitMarker & HITMARKER_ATTACKSTRING_PRINTED)
|
||||
&& gBattlerAttacker != battler)
|
||||
{
|
||||
// Set bit and save Dancer mon's original target
|
||||
@@ -6174,14 +6204,14 @@ bool32 TryPrimalReversion(u32 battler)
|
||||
{
|
||||
if (gBattlerAttacker == battler)
|
||||
{
|
||||
BattleScriptExecute(BattleScript_PrimalReversion);
|
||||
BattleScriptPushCursorAndCallback(BattleScript_PrimalReversion);
|
||||
}
|
||||
else
|
||||
{
|
||||
// edge case for scenarios like a switch-in after activated eject button
|
||||
gBattleScripting.savedBattler = gBattlerAttacker;
|
||||
gBattlerAttacker = battler;
|
||||
BattleScriptExecute(BattleScript_PrimalReversionRestoreAttacker);
|
||||
BattleScriptPushCursorAndCallback(BattleScript_PrimalReversionRestoreAttacker);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -6611,8 +6641,7 @@ static u8 TrySetMicleBerry(u32 battler, u32 itemId, bool32 end2)
|
||||
{
|
||||
if (HasEnoughHpToEatBerry(battler, 4, itemId))
|
||||
{
|
||||
gProtectStructs[battler].usedMicleBerry = TRUE; // battler's next attack has increased accuracy
|
||||
|
||||
gBattleStruct->usedMicleBerry |= 1u << battler;
|
||||
if (end2)
|
||||
{
|
||||
BattleScriptExecute(BattleScript_MicleBerryActivateEnd2);
|
||||
@@ -8120,11 +8149,13 @@ u32 GetMoveTarget(u16 move, u8 setTarget)
|
||||
case MOVE_TARGET_DEPENDS:
|
||||
case MOVE_TARGET_BOTH:
|
||||
case MOVE_TARGET_FOES_AND_ALLY:
|
||||
case MOVE_TARGET_OPPONENTS_FIELD:
|
||||
targetBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker)));
|
||||
if (!IsBattlerAlive(targetBattler))
|
||||
targetBattler ^= BIT_FLANK;
|
||||
break;
|
||||
case MOVE_TARGET_OPPONENTS_FIELD:
|
||||
targetBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker)));
|
||||
break;
|
||||
case MOVE_TARGET_RANDOM:
|
||||
side = BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker));
|
||||
if (IsAffectedByFollowMe(gBattlerAttacker, side, move))
|
||||
@@ -8152,12 +8183,7 @@ u32 GetMoveTarget(u16 move, u8 setTarget)
|
||||
return targetBattler;
|
||||
}
|
||||
|
||||
static bool32 IsBattlerModernFatefulEncounter(u32 battler)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
u8 IsMonDisobedient(void)
|
||||
u8 GetAttackerObedienceForAction()
|
||||
{
|
||||
s32 rnd;
|
||||
s32 calc;
|
||||
@@ -8165,34 +8191,31 @@ u8 IsMonDisobedient(void)
|
||||
u8 levelReferenced;
|
||||
|
||||
if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK))
|
||||
return 0;
|
||||
return OBEYS;
|
||||
if (BattlerHasAi(gBattlerAttacker))
|
||||
return 0;
|
||||
return OBEYS;
|
||||
if ((gBattleTypeFlags & (BATTLE_TYPE_POKEDUDE)))
|
||||
return 0;
|
||||
return OBEYS;
|
||||
|
||||
if (IsBattlerModernFatefulEncounter(gBattlerAttacker)) // only false if illegal Mew or Deoxys
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && GetBattlerPosition(gBattlerAttacker) == B_POSITION_PLAYER_RIGHT)
|
||||
return 0;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
|
||||
return 0;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
||||
return 0;
|
||||
if (B_OBEDIENCE_MECHANICS < GEN_8 && !IsOtherTrainer(gBattleMons[gBattlerAttacker].otId, gBattleMons[gBattlerAttacker].otName))
|
||||
return 0;
|
||||
if (FlagGet(FLAG_BADGE08_GET)) // Rain Badge, ignore obedience altogether
|
||||
return 0;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && GetBattlerPosition(gBattlerAttacker) == B_POSITION_PLAYER_RIGHT)
|
||||
return OBEYS;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
|
||||
return OBEYS;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
||||
return OBEYS;
|
||||
if (B_OBEDIENCE_MECHANICS < GEN_8 && !IsOtherTrainer(gBattleMons[gBattlerAttacker].otId, gBattleMons[gBattlerAttacker].otName))
|
||||
return OBEYS;
|
||||
if (FlagGet(FLAG_BADGE08_GET)) // Rain Badge, ignore obedience altogether
|
||||
return OBEYS;
|
||||
|
||||
obedienceLevel = 10;
|
||||
obedienceLevel = 10;
|
||||
|
||||
if (FlagGet(FLAG_BADGE02_GET))
|
||||
obedienceLevel = 30;
|
||||
if (FlagGet(FLAG_BADGE04_GET))
|
||||
obedienceLevel = 50;
|
||||
if (FlagGet(FLAG_BADGE06_GET))
|
||||
obedienceLevel = 70;
|
||||
}
|
||||
if (FlagGet(FLAG_BADGE02_GET))
|
||||
obedienceLevel = 30;
|
||||
if (FlagGet(FLAG_BADGE04_GET))
|
||||
obedienceLevel = 50;
|
||||
if (FlagGet(FLAG_BADGE06_GET))
|
||||
obedienceLevel = 70;
|
||||
|
||||
if (B_OBEDIENCE_MECHANICS >= GEN_8
|
||||
&& !IsOtherTrainer(gBattleMons[gBattlerAttacker].otId, gBattleMons[gBattlerAttacker].otName))
|
||||
@@ -8201,86 +8224,58 @@ u8 IsMonDisobedient(void)
|
||||
levelReferenced = gBattleMons[gBattlerAttacker].level;
|
||||
|
||||
if (levelReferenced <= obedienceLevel)
|
||||
return 0;
|
||||
rnd = (Random() & 255);
|
||||
calc = (levelReferenced + obedienceLevel) * rnd >> 8;
|
||||
return OBEYS;
|
||||
|
||||
rnd = Random();
|
||||
calc = (levelReferenced + obedienceLevel) * (rnd & 255) >> 8;
|
||||
if (calc < obedienceLevel)
|
||||
return 0;
|
||||
return OBEYS;
|
||||
|
||||
// Clear the Z-Move flags if the battler is disobedient as to not waste the Z-Move
|
||||
if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE)
|
||||
{
|
||||
gBattleStruct->gimmick.activated[gBattlerAttacker][GIMMICK_Z_MOVE] = FALSE;
|
||||
gBattleStruct->gimmick.activeGimmick[GetBattlerSide(gBattlerAttacker)][gBattlerPartyIndexes[gBattlerAttacker]] = GIMMICK_NONE;
|
||||
}
|
||||
|
||||
// is not obedient
|
||||
if (gCurrentMove == MOVE_RAGE)
|
||||
gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_RAGE;
|
||||
if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP && (gMovesInfo[gCurrentMove].effect == EFFECT_SNORE || gMovesInfo[gCurrentMove].effect == EFFECT_SLEEP_TALK))
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_IgnoresWhileAsleep;
|
||||
return 1;
|
||||
}
|
||||
return DISOBEYS_WHILE_ASLEEP;
|
||||
|
||||
rnd = (Random() & 255);
|
||||
calc = (levelReferenced + obedienceLevel) * rnd >> 8;
|
||||
calc = (levelReferenced + obedienceLevel) * ((rnd >> 8) & 255) >> 8;
|
||||
if (calc < obedienceLevel)
|
||||
{
|
||||
calc = CheckMoveLimitations(gBattlerAttacker, 1u << gCurrMovePos, MOVE_LIMITATIONS_ALL);
|
||||
if (calc == ALL_MOVES_MASK) // all moves cannot be used
|
||||
{
|
||||
// Randomly select, then print a disobedient string
|
||||
// B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = MOD(Random(), NUM_LOAF_STRINGS);
|
||||
gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround;
|
||||
return 1;
|
||||
}
|
||||
return DISOBEYS_LOAFS;
|
||||
else // use a random move
|
||||
{
|
||||
do
|
||||
{
|
||||
gCurrMovePos = gChosenMovePos = MOD(Random(), MAX_MON_MOVES);
|
||||
} while ((1u << gCurrMovePos) & calc);
|
||||
|
||||
gCalledMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos];
|
||||
SetAtkCancellerForCalledMove();
|
||||
gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove;
|
||||
gBattlerTarget = GetMoveTarget(gCalledMove, NO_TARGET_OVERRIDE);
|
||||
gHitMarker |= HITMARKER_DISOBEDIENT_MOVE;
|
||||
return 2;
|
||||
}
|
||||
while ((1u << gCurrMovePos) & calc);
|
||||
return DISOBEYS_RANDOM_MOVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
obedienceLevel = levelReferenced - obedienceLevel;
|
||||
|
||||
calc = (Random() & 255);
|
||||
calc = ((rnd >> 16) & 255);
|
||||
if (calc < obedienceLevel && CanBeSlept(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)))
|
||||
{
|
||||
// try putting asleep
|
||||
int i;
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (gBattleMons[i].status2 & STATUS2_UPROAR)
|
||||
break;
|
||||
}
|
||||
if (i == gBattlersCount)
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep;
|
||||
return 1;
|
||||
}
|
||||
return DISOBEYS_FALL_ASLEEP;
|
||||
}
|
||||
calc -= obedienceLevel;
|
||||
if (calc < obedienceLevel)
|
||||
{
|
||||
gBattleMoveDamage = CalculateMoveDamage(MOVE_NONE, gBattlerAttacker, gBattlerAttacker, TYPE_MYSTERY, 40, FALSE, FALSE, TRUE);
|
||||
gBattlerTarget = gBattlerAttacker;
|
||||
gBattlescriptCurrInstr = BattleScript_IgnoresAndHitsItself;
|
||||
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
|
||||
return 2;
|
||||
}
|
||||
return DISOBEYS_HITS_SELF;
|
||||
else
|
||||
{
|
||||
// Randomly select, then print a disobedient string
|
||||
// B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = MOD(Random(), NUM_LOAF_STRINGS);
|
||||
gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround;
|
||||
return 1;
|
||||
}
|
||||
return DISOBEYS_LOAFS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8373,13 +8368,9 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
if (gProtectStructs[battlerDef].maxGuarded && IsMoveBlockedByMaxGuard(move))
|
||||
return TRUE;
|
||||
|
||||
// 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
|
||||
&& (gMovesInfo[move].makesContact
|
||||
|| (gMovesInfo[move].effect == EFFECT_SHELL_SIDE_ARM
|
||||
&& gBattleStruct->shellSideArmCategory[battlerAtk][battlerDef] == DAMAGE_CATEGORY_PHYSICAL))
|
||||
&& !gProtectStructs[battlerDef].maxGuarded) // Max Guard cannot be bypassed by Unseen Fist
|
||||
if (!gProtectStructs[battlerDef].maxGuarded // Max Guard cannot be bypassed by Unseen Fist
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker)
|
||||
&& GetBattlerAbility(gBattlerAttacker) == ABILITY_UNSEEN_FIST)
|
||||
return FALSE;
|
||||
else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_CRAFTY_SHIELD
|
||||
&& IS_MOVE_STATUS(move))
|
||||
@@ -8520,7 +8511,7 @@ u32 CountBattlerStatIncreases(u32 battler, bool32 countEvasionAcc)
|
||||
|
||||
u32 GetMoveTargetCount(u32 move, u32 battlerAtk, u32 battlerDef)
|
||||
{
|
||||
switch (GetBattlerMoveTargetType(gBattlerAttacker, move))
|
||||
switch (GetBattlerMoveTargetType(battlerAtk, move))
|
||||
{
|
||||
case MOVE_TARGET_BOTH:
|
||||
return !(gAbsentBattlerFlags & (1u << battlerDef))
|
||||
@@ -8666,6 +8657,9 @@ static inline u32 CalcMoveBasePower(u32 move, u32 battlerAtk, u32 battlerDef, u3
|
||||
if (GetActiveGimmick(battlerAtk) == GIMMICK_Z_MOVE)
|
||||
return GetZMovePower(gBattleStruct->zmove.baseMoves[battlerAtk]);
|
||||
|
||||
if (GetActiveGimmick(battlerAtk) == GIMMICK_DYNAMAX)
|
||||
return GetMaxMovePower(move);
|
||||
|
||||
switch (gMovesInfo[move].effect)
|
||||
{
|
||||
case EFFECT_PLEDGE:
|
||||
@@ -9265,6 +9259,10 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32
|
||||
if (gMovesInfo[move].punchingMove)
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(1.1));
|
||||
break;
|
||||
case HOLD_EFFECT_OGERPON_MASK:
|
||||
if (GET_BASE_SPECIES_ID(gBattleMons[battlerAtk].species) == SPECIES_OGERPON)
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(1.2));
|
||||
break;
|
||||
}
|
||||
|
||||
// Terastallization boosts weak, non-priority, non-multi hit moves after modifiers to 60 BP.
|
||||
@@ -11267,14 +11265,11 @@ bool32 IsBattlerWeatherAffected(u32 battler, u32 weatherFlags)
|
||||
// Possible return values are defined in battle.h following MOVE_TARGET_SELECTED
|
||||
u32 GetBattlerMoveTargetType(u32 battler, u32 move)
|
||||
{
|
||||
if (move == MOVE_CURSE
|
||||
&& !IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
|
||||
if (move == MOVE_CURSE && !IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
|
||||
return MOVE_TARGET_USER;
|
||||
else if (gMovesInfo[move].effect == EFFECT_EXPANDING_FORCE
|
||||
&& IsBattlerTerrainAffected(battler, STATUS_FIELD_PSYCHIC_TERRAIN))
|
||||
if (gMovesInfo[move].effect == EFFECT_EXPANDING_FORCE && IsBattlerTerrainAffected(battler, STATUS_FIELD_PSYCHIC_TERRAIN))
|
||||
return MOVE_TARGET_BOTH;
|
||||
else if (gMovesInfo[move].effect == EFFECT_TERA_STARSTORM
|
||||
&& gBattleMons[battler].species == SPECIES_TERAPAGOS_STELLAR)
|
||||
if (gMovesInfo[move].effect == EFFECT_TERA_STARSTORM && gBattleMons[battler].species == SPECIES_TERAPAGOS_STELLAR)
|
||||
return MOVE_TARGET_BOTH;
|
||||
|
||||
return gMovesInfo[move].target;
|
||||
@@ -11617,23 +11612,28 @@ bool32 CanTargetPartner(u32 battlerAtk, u32 battlerDef)
|
||||
&& battlerDef != BATTLE_PARTNER(battlerAtk));
|
||||
}
|
||||
|
||||
static inline bool32 DoesCurrentTargetHaveAbilityImmunity(void)
|
||||
static inline bool32 DoesBattlerHaveAbilityImmunity(u32 battlerDef)
|
||||
{
|
||||
return (AbilityBattleEffects(ABILITYEFFECT_WOULD_BLOCK, gBattlerTarget, 0, 0, 0)
|
||||
|| AbilityBattleEffects(ABILITYEFFECT_WOULD_ABSORB, gBattlerTarget, 0, 0, 0));
|
||||
return (AbilityBattleEffects(ABILITYEFFECT_WOULD_BLOCK, battlerDef, 0, 0, 0)
|
||||
|| AbilityBattleEffects(ABILITYEFFECT_WOULD_ABSORB, battlerDef, 0, 0, 0));
|
||||
}
|
||||
|
||||
bool32 TargetFullyImmuneToCurrMove(u32 BattlerAtk, u32 battlerDef)
|
||||
bool32 TargetFullyImmuneToCurrMove(u32 battlerAtk, u32 battlerDef)
|
||||
{
|
||||
return ((CalcTypeEffectivenessMultiplier(gCurrentMove, GetMoveType(gCurrentMove), BattlerAtk, battlerDef, GetBattlerAbility(battlerDef), FALSE) == UQ_4_12(0.0))
|
||||
|| IsBattlerProtected(BattlerAtk, battlerDef, gCurrentMove)
|
||||
return ((CalcTypeEffectivenessMultiplier(gCurrentMove, GetMoveType(gCurrentMove), battlerAtk, battlerDef, GetBattlerAbility(battlerDef), FALSE) == UQ_4_12(0.0))
|
||||
|| IsBattlerProtected(battlerAtk, battlerDef, gCurrentMove)
|
||||
|| IsSemiInvulnerable(battlerDef, gCurrentMove)
|
||||
|| DoesCurrentTargetHaveAbilityImmunity());
|
||||
|| DoesBattlerHaveAbilityImmunity(battlerDef));
|
||||
}
|
||||
|
||||
u32 GetMoveType(u32 move)
|
||||
{
|
||||
if (gMain.inBattle && gBattleStruct->dynamicMoveType)
|
||||
return gBattleStruct->dynamicMoveType & DYNAMIC_TYPE_MASK;
|
||||
else if (B_UPDATED_MOVE_TYPES < GEN_5
|
||||
&& (move == MOVE_BEAT_UP
|
||||
|| move == MOVE_FUTURE_SIGHT
|
||||
|| move == MOVE_DOOM_DESIRE))
|
||||
return TYPE_MYSTERY;
|
||||
return gMovesInfo[move].type;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "global.h"
|
||||
#include "battle.h"
|
||||
#include "event_data.h"
|
||||
#include "level_caps.h"
|
||||
#include "caps.h"
|
||||
#include "pokemon.h"
|
||||
|
||||
|
||||
@@ -81,3 +81,39 @@ u32 GetSoftLevelCapExpValue(u32 level, u32 expValue)
|
||||
return expValue;
|
||||
}
|
||||
}
|
||||
|
||||
u32 GetCurrentEVCap(void)
|
||||
{
|
||||
|
||||
static const u16 sEvCapFlagMap[][2] = {
|
||||
// Define EV caps for each milestone
|
||||
{FLAG_BADGE01_GET, 30},
|
||||
{FLAG_BADGE02_GET, 90},
|
||||
{FLAG_BADGE03_GET, 150},
|
||||
{FLAG_BADGE04_GET, 210},
|
||||
{FLAG_BADGE05_GET, 270},
|
||||
{FLAG_BADGE06_GET, 330},
|
||||
{FLAG_BADGE07_GET, 390},
|
||||
{FLAG_BADGE08_GET, 450},
|
||||
{FLAG_SYS_GAME_CLEAR, MAX_TOTAL_EVS},
|
||||
};
|
||||
|
||||
if (B_EV_CAP_TYPE == EV_CAP_FLAG_LIST)
|
||||
{
|
||||
for (u32 evCap = 0; evCap < ARRAY_COUNT(sEvCapFlagMap); evCap++)
|
||||
{
|
||||
if (!FlagGet(sEvCapFlagMap[evCap][0]))
|
||||
return sEvCapFlagMap[evCap][1];
|
||||
}
|
||||
}
|
||||
else if (B_EV_CAP_TYPE == EV_CAP_VARIABLE)
|
||||
{
|
||||
return VarGet(B_EV_CAP_VARIABLE);
|
||||
}
|
||||
else if (B_EV_CAP_TYPE == EV_CAP_NO_GAIN)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return MAX_TOTAL_EVS;
|
||||
}
|
||||
@@ -110,11 +110,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_COMPOUND_EYES] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Compound Eyes"),
|
||||
#else
|
||||
.name = _("CompoundEyes"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Raises accuracy."),
|
||||
.aiRating = 7,
|
||||
},
|
||||
@@ -244,11 +240,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_LIGHTNING_ROD] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Lightning Rod"),
|
||||
#else
|
||||
.name = _("LightningRod"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Draws electrical moves."),
|
||||
.aiRating = 7,
|
||||
.breakable = TRUE,
|
||||
@@ -1324,11 +1316,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_STANCE_CHANGE] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Stance Change"),
|
||||
#else
|
||||
.name = _("StanceChange"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Transforms as it battles."),
|
||||
.aiRating = 10,
|
||||
.cantBeCopied = TRUE,
|
||||
@@ -1347,11 +1335,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_MEGA_LAUNCHER] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Mega Launcher"),
|
||||
#else
|
||||
.name = _("MegaLauncher"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Boosts pulse moves."),
|
||||
.aiRating = 7,
|
||||
},
|
||||
@@ -1401,11 +1385,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_PARENTAL_BOND] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Parental Bond"),
|
||||
#else
|
||||
.name = _("ParentalBond"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Moves hit twice."),
|
||||
.aiRating = 10,
|
||||
},
|
||||
@@ -1433,22 +1413,14 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_PRIMORDIAL_SEA] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Primordial Sea"),
|
||||
#else
|
||||
.name = _("PrimrdialSea"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Summons heavy rain."),
|
||||
.aiRating = 10,
|
||||
},
|
||||
|
||||
[ABILITY_DESOLATE_LAND] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Desolate Land"),
|
||||
#else
|
||||
.name = _("DesolateLand"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Summons intense sunlight."),
|
||||
.aiRating = 10,
|
||||
},
|
||||
@@ -1476,22 +1448,14 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_EMERGENCY_EXIT] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Emergency Exit"),
|
||||
#else
|
||||
.name = _("EmergncyExit"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Flees at half HP."),
|
||||
.aiRating = 3,
|
||||
},
|
||||
|
||||
[ABILITY_WATER_COMPACTION] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Water Compaction"),
|
||||
#else
|
||||
.name = _("WtrCmpaction"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Water boosts Defense."),
|
||||
.aiRating = 4,
|
||||
},
|
||||
@@ -1625,11 +1589,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_POWER_CONSTRUCT] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Power Construct"),
|
||||
#else
|
||||
.name = _("PwrConstruct"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Cells aid it when weakened."),
|
||||
.aiRating = 10,
|
||||
.cantBeCopied = TRUE,
|
||||
@@ -1660,11 +1620,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_QUEENLY_MAJESTY] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Queenly Majesty"),
|
||||
#else
|
||||
.name = _("QueenlyMjsty"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Protects from priority."),
|
||||
.aiRating = 6,
|
||||
.breakable = TRUE,
|
||||
@@ -1716,11 +1672,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_TANGLING_HAIR] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Tangling Hair"),
|
||||
#else
|
||||
.name = _("TanglingHair"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Lowers Speed on contact."),
|
||||
.aiRating = 5,
|
||||
},
|
||||
@@ -1736,11 +1688,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_POWER_OF_ALCHEMY] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Power Of Alchemy"),
|
||||
#else
|
||||
.name = _("PwrOfAlchemy"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Copies ally's ability."),
|
||||
.aiRating = 0,
|
||||
.cantBeCopied = TRUE,
|
||||
@@ -1768,22 +1716,14 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_ELECTRIC_SURGE] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Electric Surge"),
|
||||
#else
|
||||
.name = _("ElectrcSurge"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Field becomes Electric."),
|
||||
.aiRating = 8,
|
||||
},
|
||||
|
||||
[ABILITY_PSYCHIC_SURGE] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Psychic Surge"),
|
||||
#else
|
||||
.name = _("PsychicSurge"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Field becomes weird."),
|
||||
.aiRating = 8,
|
||||
},
|
||||
@@ -1804,22 +1744,14 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_FULL_METAL_BODY] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Full Metal Body"),
|
||||
#else
|
||||
.name = _("FullMetalBdy"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Prevents stat reduction."),
|
||||
.aiRating = 4,
|
||||
},
|
||||
|
||||
[ABILITY_SHADOW_SHIELD] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Shadow Shield"),
|
||||
#else
|
||||
.name = _("ShadowShield"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Halves damage at full HP."),
|
||||
.aiRating = 8,
|
||||
},
|
||||
@@ -1840,22 +1772,14 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_INTREPID_SWORD] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Intrepid Sword"),
|
||||
#else
|
||||
.name = _("IntrepidSwrd"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Ups Attack on entry."),
|
||||
.aiRating = 3,
|
||||
},
|
||||
|
||||
[ABILITY_DAUNTLESS_SHIELD] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Dauntless Shield"),
|
||||
#else
|
||||
.name = _("DauntlssShld"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Ups Defense on entry."),
|
||||
.aiRating = 3,
|
||||
},
|
||||
@@ -1882,11 +1806,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_PROPELLER_TAIL] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Propeller Tail"),
|
||||
#else
|
||||
.name = _("PropellrTail"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Ignores foe's redirection."),
|
||||
.aiRating = 2,
|
||||
},
|
||||
@@ -1984,22 +1904,14 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_SCREEN_CLEANER] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Screen Cleaner"),
|
||||
#else
|
||||
.name = _("ScreenCleanr"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Removes walls of light."),
|
||||
.aiRating = 3,
|
||||
},
|
||||
|
||||
[ABILITY_STEELY_SPIRIT] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Steely Spirit"),
|
||||
#else
|
||||
.name = _("SteelySpirit"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Boosts ally's Steel moves."),
|
||||
.aiRating = 2,
|
||||
},
|
||||
@@ -2013,33 +1925,21 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_WANDERING_SPIRIT] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Wandering Spirit"),
|
||||
#else
|
||||
.name = _("WandrngSprit"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Trade abilities on contact."),
|
||||
.aiRating = 2,
|
||||
},
|
||||
|
||||
[ABILITY_GORILLA_TACTICS] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Gorilla Tactics"),
|
||||
#else
|
||||
.name = _("GorillaTacti"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Ups Attack and locks move."),
|
||||
.aiRating = 4,
|
||||
},
|
||||
|
||||
[ABILITY_NEUTRALIZING_GAS] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Neutralizing Gas"),
|
||||
#else
|
||||
.name = _("NeutrlzngGas"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("All Abilities are nullified."),
|
||||
.aiRating = 5,
|
||||
.cantBeCopied = TRUE,
|
||||
@@ -2058,11 +1958,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_HUNGER_SWITCH] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Hunger Switch"),
|
||||
#else
|
||||
.name = _("HungerSwitch"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Changes form each turn."),
|
||||
.aiRating = 2,
|
||||
.cantBeCopied = TRUE,
|
||||
@@ -2087,11 +1983,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_CURIOUS_MEDICINE] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Curious Medicine"),
|
||||
#else
|
||||
.name = _("CuriusMedicn"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Remove ally's stat changes."),
|
||||
.aiRating = 3,
|
||||
},
|
||||
@@ -2112,11 +2004,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_CHILLING_NEIGH] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Chilling Neigh"),
|
||||
#else
|
||||
.name = _("ChillngNeigh"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("KOs boost Attack stat."),
|
||||
.aiRating = 7,
|
||||
},
|
||||
@@ -2154,11 +2042,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_LINGERING_AROMA] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Lingering Aroma"),
|
||||
#else
|
||||
.name = _("LngerngAroma"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Spreads with contact."),
|
||||
.aiRating = 5,
|
||||
},
|
||||
@@ -2172,11 +2056,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_THERMAL_EXCHANGE] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Thermal Exchange"),
|
||||
#else
|
||||
.name = _("ThrmlExchnge"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Fire hits up Attack."),
|
||||
.aiRating = 4,
|
||||
.breakable = TRUE,
|
||||
@@ -2191,11 +2071,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_PURIFYING_SALT] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Purifying Salt"),
|
||||
#else
|
||||
.name = _("PurfyingSalt"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Protected by pure salts."),
|
||||
.aiRating = 6,
|
||||
.breakable = TRUE,
|
||||
@@ -2203,11 +2079,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_WELL_BAKED_BODY] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Well-Baked Body"),
|
||||
#else
|
||||
.name = _("WellBakedBdy"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Strengthened by Fire."),
|
||||
.aiRating = 5,
|
||||
.breakable = TRUE,
|
||||
@@ -2231,11 +2103,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_ROCKY_PAYLOAD] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Rocky Payload"),
|
||||
#else
|
||||
.name = _("RockyPayload"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Powers up Rock moves."),
|
||||
.aiRating = 6,
|
||||
},
|
||||
@@ -2273,22 +2141,14 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_ELECTROMORPHOSIS] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Electromorphosis"),
|
||||
#else
|
||||
.name = _("Elecmrphosis"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Gets Charged when hit."),
|
||||
.aiRating = 5,
|
||||
},
|
||||
|
||||
[ABILITY_PROTOSYNTHESIS] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Protosynthesis"),
|
||||
#else
|
||||
.name = _("Protosnthsis"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Sun boosts best stat."),
|
||||
.aiRating = 7,
|
||||
.cantBeCopied = TRUE,
|
||||
@@ -2318,11 +2178,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_VESSEL_OF_RUIN] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Vessel of Ruin"),
|
||||
#else
|
||||
.name = _("VesselOfRuin"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Lowers foes' sp. damage."),
|
||||
.aiRating = 5,
|
||||
.breakable = TRUE,
|
||||
@@ -2330,11 +2186,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_SWORD_OF_RUIN] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Sword of Ruin"),
|
||||
#else
|
||||
.name = _("SwordOfRuin"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Lowers foes' Defense."),
|
||||
.aiRating = 5,
|
||||
.breakable = TRUE,
|
||||
@@ -2342,11 +2194,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_TABLETS_OF_RUIN] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Tablets of Ruin"),
|
||||
#else
|
||||
.name = _("TabltsOfRuin"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Lowers foes' damage."),
|
||||
.aiRating = 5,
|
||||
.breakable = TRUE,
|
||||
@@ -2354,11 +2202,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_BEADS_OF_RUIN] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Beads of Ruin"),
|
||||
#else
|
||||
.name = _("BeadsOfRuin"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Lowers foes' Sp. Defense."),
|
||||
.aiRating = 5,
|
||||
.breakable = TRUE,
|
||||
@@ -2366,22 +2210,14 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_ORICHALCUM_PULSE] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Orichalcum Pulse"),
|
||||
#else
|
||||
.name = _("OrchlcumPlse"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Summons sunlight in battle."),
|
||||
.aiRating = 8,
|
||||
},
|
||||
|
||||
[ABILITY_HADRON_ENGINE] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Hadron Engine"),
|
||||
#else
|
||||
.name = _("HadronEngine"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Field becomes Electric."),
|
||||
.aiRating = 8,
|
||||
},
|
||||
@@ -2409,11 +2245,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_SUPREME_OVERLORD] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Supreme Overlord"),
|
||||
#else
|
||||
.name = _("SuprmeOvrlrd"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Inherits fallen's strength."),
|
||||
.aiRating = 6,
|
||||
},
|
||||
@@ -2450,11 +2282,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_MYCELIUM_MIGHT] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Mycelium Might"),
|
||||
#else
|
||||
.name = _("MceliumMight"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Status moves never fail."),
|
||||
.aiRating = 2,
|
||||
},
|
||||
@@ -2476,11 +2304,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_EMBODY_ASPECT_TEAL_MASK] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Embody Aspect"),
|
||||
#else
|
||||
.name = _("EmbodyAspect"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Raises Speed."),
|
||||
.aiRating = 6,
|
||||
.cantBeCopied = TRUE,
|
||||
@@ -2491,11 +2315,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Embody Aspect"),
|
||||
#else
|
||||
.name = _("EmbodyAspect"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Raises Attack."),
|
||||
.aiRating = 6,
|
||||
.cantBeCopied = TRUE,
|
||||
@@ -2506,11 +2326,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_EMBODY_ASPECT_WELLSPRING_MASK] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Embody Aspect"),
|
||||
#else
|
||||
.name = _("EmbodyAspect"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Raises Sp. Def."),
|
||||
.aiRating = 6,
|
||||
.cantBeCopied = TRUE,
|
||||
@@ -2521,11 +2337,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Embody Aspect"),
|
||||
#else
|
||||
.name = _("EmbodyAspect"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Raises Defense."),
|
||||
.aiRating = 6,
|
||||
.cantBeCopied = TRUE,
|
||||
@@ -2543,11 +2355,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_SUPERSWEET_SYRUP] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Supersweet Syrup"),
|
||||
#else
|
||||
.name = _("SuprswtSyrup"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Lowers the foe's Speed."),
|
||||
.aiRating = 5,
|
||||
},
|
||||
@@ -2578,11 +2386,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_TERAFORM_ZERO] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Teraform Zero"),
|
||||
#else
|
||||
.name = _("TeraformZero"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Removes weather and terrain."),
|
||||
.aiRating = 10,
|
||||
.cantBeCopied = TRUE,
|
||||
@@ -2592,11 +2396,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] =
|
||||
|
||||
[ABILITY_POISON_PUPPETEER] =
|
||||
{
|
||||
#if B_EXPANDED_ABILITY_NAMES == TRUE
|
||||
.name = _("Poison Puppeteer"),
|
||||
#else
|
||||
.name = _("PoisnPuppter"),
|
||||
#endif
|
||||
.description = COMPOUND_STRING("Confuses poisoned foes."),
|
||||
.aiRating = 8,
|
||||
.cantBeCopied = TRUE,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -40,12 +40,6 @@ const uq4_12_t gTypeEffectivenessTable[NUMBER_OF_MON_TYPES][NUMBER_OF_MON_TYPES]
|
||||
#undef ______
|
||||
#undef X
|
||||
|
||||
#if B_EXPANDED_TYPE_NAMES == TRUE
|
||||
#define HANDLE_EXPANDED_TYPE_NAME(_name, ...) _(DEFAULT(_name, __VA_ARGS__))
|
||||
#else
|
||||
#define HANDLE_EXPANDED_TYPE_NAME(_name, ...) _(_name)
|
||||
#endif
|
||||
|
||||
// .generic is large enough that the text for TYPE_ELECTRIC will exceed TEXT_BUFF_ARRAY_COUNT.
|
||||
// In this array there's commented-out data such as references to type-resist berries that would otherwise would go unused.
|
||||
// However, we figured this information would be useful for users that want to add their own types as a reminder of
|
||||
@@ -60,6 +54,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB_WHITE,
|
||||
.damageCategory = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.paletteTMHM = gItemIconPalette_NormalTMHM,
|
||||
.useSecondTypeIconPalette = FALSE,
|
||||
.isSpecialCaseType = TRUE,
|
||||
},
|
||||
[TYPE_NORMAL] =
|
||||
{
|
||||
@@ -71,6 +67,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB_WHITE, // custom
|
||||
.damageCategory = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.paletteTMHM = gItemIconPalette_NormalTMHM,
|
||||
.useSecondTypeIconPalette = FALSE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_SILK_SCARF,
|
||||
//.berry = ITEM_CHILAN_BERRY,
|
||||
//.gem = ITEM_NORMAL_GEM,
|
||||
@@ -80,7 +78,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
},
|
||||
[TYPE_FIGHTING] =
|
||||
{
|
||||
.name = HANDLE_EXPANDED_TYPE_NAME("Fight", "Fighting"),
|
||||
.name = _("Fighting"),
|
||||
.generic = _("a FIGHTING move"),
|
||||
.palette = 13,
|
||||
.zMove = MOVE_ALL_OUT_PUMMELING,
|
||||
@@ -88,6 +86,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(26, 8, 14),
|
||||
.damageCategory = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.paletteTMHM = gItemIconPalette_FightingTMHM,
|
||||
.useSecondTypeIconPalette = FALSE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_BLACK_BELT,
|
||||
//.berry = ITEM_CHOPLE_BERRY,
|
||||
//.gem = ITEM_FIGHTING_GEM,
|
||||
@@ -107,6 +107,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(31, 26, 7),
|
||||
.damageCategory = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.paletteTMHM = gItemIconPalette_FlyingTMHM,
|
||||
.useSecondTypeIconPalette = FALSE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_SHARP_BEAK,
|
||||
//.berry = ITEM_COBA_BERRY,
|
||||
//.gem = ITEM_FLYING_GEM,
|
||||
@@ -126,6 +128,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(26, 10, 25), // custom
|
||||
.damageCategory = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.paletteTMHM = gItemIconPalette_PoisonTMHM,
|
||||
.useSecondTypeIconPalette = FALSE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_POISON_BARB,
|
||||
//.berry = ITEM_KEBIA_BERRY,
|
||||
//.gem = ITEM_POISON_GEM,
|
||||
@@ -145,6 +149,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(25, 23, 18),
|
||||
.damageCategory = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.paletteTMHM = gItemIconPalette_GroundTMHM,
|
||||
.useSecondTypeIconPalette = FALSE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_SOFT_SAND,
|
||||
//.berry = ITEM_SHUCA_BERRY,
|
||||
//.gem = ITEM_GROUND_GEM,
|
||||
@@ -164,6 +170,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(18, 16, 8), // custom
|
||||
.damageCategory = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.paletteTMHM = gItemIconPalette_RockTMHM,
|
||||
.useSecondTypeIconPalette = FALSE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_HARD_STONE,
|
||||
//.berry = ITEM_CHARTI_BERRY,
|
||||
//.gem = ITEM_ROCK_GEM,
|
||||
@@ -183,6 +191,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(18, 24, 6),
|
||||
.damageCategory = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.paletteTMHM = gItemIconPalette_BugTMHM,
|
||||
.useSecondTypeIconPalette = FALSE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_SILVER_POWDER,
|
||||
//.berry = ITEM_TANGA_BERRY,
|
||||
//.gem = ITEM_BUG_GEM,
|
||||
@@ -202,6 +212,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(12, 10, 16),
|
||||
.damageCategory = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.paletteTMHM = gItemIconPalette_GhostTMHM,
|
||||
.useSecondTypeIconPalette = FALSE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_SPELL_TAG,
|
||||
//.berry = ITEM_KASIB_BERRY,
|
||||
//.gem = ITEM_GHOST_GEM,
|
||||
@@ -221,6 +233,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(19, 19, 20),
|
||||
.damageCategory = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.paletteTMHM = gItemIconPalette_SteelTMHM,
|
||||
.useSecondTypeIconPalette = FALSE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_METAL_COAT,
|
||||
//.berry = ITEM_BABIRI_BERRY,
|
||||
//.gem = ITEM_STEEL_GEM,
|
||||
@@ -237,6 +251,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.palette = 15,
|
||||
.teraTypeRGBValue = RGB_WHITE,
|
||||
.damageCategory = DAMAGE_CATEGORY_SPECIAL,
|
||||
.useSecondTypeIconPalette = FALSE,
|
||||
.isSpecialCaseType = TRUE,
|
||||
},
|
||||
[TYPE_FIRE] =
|
||||
{
|
||||
@@ -248,6 +264,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(31, 20, 11),
|
||||
.damageCategory = DAMAGE_CATEGORY_SPECIAL,
|
||||
.paletteTMHM = gItemIconPalette_FireTMHM,
|
||||
.useSecondTypeIconPalette = TRUE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_CHARCOAL,
|
||||
//.berry = ITEM_OCCA_BERRY,
|
||||
//.gem = ITEM_FIRE_GEM,
|
||||
@@ -267,6 +285,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(10, 18, 27),
|
||||
.damageCategory = DAMAGE_CATEGORY_SPECIAL,
|
||||
.paletteTMHM = gItemIconPalette_WaterTMHM,
|
||||
.useSecondTypeIconPalette = TRUE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_MYSTIC_WATER,
|
||||
//.berry = ITEM_PASSHO_BERRY,
|
||||
//.gem = ITEM_WATER_GEM,
|
||||
@@ -286,6 +306,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(12, 24, 11),
|
||||
.damageCategory = DAMAGE_CATEGORY_SPECIAL,
|
||||
.paletteTMHM = gItemIconPalette_GrassTMHM,
|
||||
.useSecondTypeIconPalette = TRUE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_MIRACLE_SEED,
|
||||
//.berry = ITEM_RINDO_BERRY,
|
||||
//.gem = ITEM_GRASS_GEM,
|
||||
@@ -297,7 +319,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
},
|
||||
[TYPE_ELECTRIC] =
|
||||
{
|
||||
.name = HANDLE_EXPANDED_TYPE_NAME("Electr", "Electric"),
|
||||
.name = _("Electric"),
|
||||
.generic = _("an ELECTRIC move"),
|
||||
.palette = 13,
|
||||
.zMove = MOVE_GIGAVOLT_HAVOC,
|
||||
@@ -305,6 +327,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(30, 26, 7),
|
||||
.damageCategory = DAMAGE_CATEGORY_SPECIAL,
|
||||
.paletteTMHM = gItemIconPalette_ElectricTMHM,
|
||||
.useSecondTypeIconPalette = TRUE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_MAGNET,
|
||||
//.berry = ITEM_WACAN_BERRY,
|
||||
//.gem = ITEM_ELECTRIC_GEM,
|
||||
@@ -316,7 +340,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
},
|
||||
[TYPE_PSYCHIC] =
|
||||
{
|
||||
.name = HANDLE_EXPANDED_TYPE_NAME("Psychc", "Psychic"),
|
||||
.name = _("Psychic"),
|
||||
.generic = _("a PSYCHIC move"),
|
||||
.palette = 14,
|
||||
.zMove = MOVE_SHATTERED_PSYCHE,
|
||||
@@ -324,6 +348,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(31, 14, 15),
|
||||
.damageCategory = DAMAGE_CATEGORY_SPECIAL,
|
||||
.paletteTMHM = gItemIconPalette_PsychicTMHM,
|
||||
.useSecondTypeIconPalette = TRUE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_TWISTED_SPOON,
|
||||
//.berry = ITEM_PAYAPA_BERRY,
|
||||
//.gem = ITEM_PSYCHIC_GEM,
|
||||
@@ -343,6 +369,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(14, 26, 25),
|
||||
.damageCategory = DAMAGE_CATEGORY_SPECIAL,
|
||||
.paletteTMHM = gItemIconPalette_IceTMHM,
|
||||
.useSecondTypeIconPalette = TRUE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_NEVER_MELT_ICE,
|
||||
//.berry = ITEM_YACHE_BERRY,
|
||||
//.gem = ITEM_ICE_GEM,
|
||||
@@ -362,6 +390,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(10, 18, 27),
|
||||
.damageCategory = DAMAGE_CATEGORY_SPECIAL,
|
||||
.paletteTMHM = gItemIconPalette_DragonTMHM,
|
||||
.useSecondTypeIconPalette = TRUE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_DRAGON_FANG,
|
||||
//.berry = ITEM_HABAN_BERRY,
|
||||
//.gem = ITEM_DRAGON_GEM,
|
||||
@@ -381,6 +411,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(6, 5, 8),
|
||||
.damageCategory = DAMAGE_CATEGORY_SPECIAL,
|
||||
.paletteTMHM = gItemIconPalette_DarkTMHM,
|
||||
.useSecondTypeIconPalette = TRUE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_BLACK_GLASSES,
|
||||
//.berry = ITEM_COLBUR_BERRY,
|
||||
//.gem = ITEM_DARK_GEM,
|
||||
@@ -400,6 +432,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
.teraTypeRGBValue = RGB(31, 15, 21),
|
||||
.damageCategory = DAMAGE_CATEGORY_SPECIAL,
|
||||
.paletteTMHM = gItemIconPalette_FairyTMHM,
|
||||
.useSecondTypeIconPalette = TRUE,
|
||||
.isSpecialCaseType = FALSE,
|
||||
//.enhanceItem = ITEM_FAIRY_FEATHER,
|
||||
//.berry = ITEM_ROSELI_BERRY,
|
||||
//.gem = ITEM_FAIRY_GEM,
|
||||
@@ -411,13 +445,15 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] =
|
||||
},
|
||||
[TYPE_STELLAR] =
|
||||
{
|
||||
.name = HANDLE_EXPANDED_TYPE_NAME("Stellr", "Stellar"),
|
||||
.name = _("Stellar"),
|
||||
.generic = _("a STELLAR move"),
|
||||
.palette = 15,
|
||||
.zMove = MOVE_BREAKNECK_BLITZ,
|
||||
.maxMove = MOVE_MAX_STRIKE,
|
||||
.teraTypeRGBValue = RGB(10, 18, 27),
|
||||
.paletteTMHM = gItemIconPalette_NormalTMHM, // failsafe
|
||||
.useSecondTypeIconPalette = FALSE,
|
||||
.isSpecialCaseType = TRUE,
|
||||
// .teraShard = ITEM_STELLAR_TERA_SHARD,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "event_data.h"
|
||||
#include "random.h"
|
||||
#include "constants/moves.h"
|
||||
#include "level_caps.h"
|
||||
#include "caps.h"
|
||||
#include "menu.h"
|
||||
#include "script.h"
|
||||
#include "strings.h"
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "item.h"
|
||||
#include "item_menu.h"
|
||||
#include "item_use.h"
|
||||
#include "level_caps.h"
|
||||
#include "caps.h"
|
||||
#include "link.h"
|
||||
#include "link_rfu.h"
|
||||
#include "load_save.h"
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "battle_message.h"
|
||||
#include "battle_util.h"
|
||||
#include "link.h"
|
||||
#include "level_caps.h"
|
||||
#include "caps.h"
|
||||
#include "pokemon_animation.h"
|
||||
#include "m4a.h"
|
||||
#include "pokedex.h"
|
||||
|
||||
Reference in New Issue
Block a user