updated battle engine to 0bb43626afe2cdc6f9bdd7c246e2dca7198ddab3

This commit is contained in:
cawtds
2024-08-27 21:05:49 +02:00
parent 6ecdf45e8b
commit 435f8ebda4
20 changed files with 803 additions and 750 deletions

View File

@@ -1670,6 +1670,10 @@
callnative BS_DamageToQuarterTargetHP
.endm
.macro ficklebeamdamagecalculation
callnative BS_FickleBeamDamageCalculation
.endm
@ various command changed to more readable macros
.macro cancelmultiturnmoves battler:req
various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES
@@ -2519,5 +2523,3 @@
printstring STRINGID_EMPTYSTRING3
waitmessage 1
.endm

View File

@@ -22,62 +22,6 @@
.section script_data, "aw", %progbits
.align 2
BattleScript_LocalTrainerBattleWon::
jumpifbattletype BATTLE_TYPE_TWO_OPPONENTS, BattleScript_LocalTwoTrainersDefeated
printstring STRINGID_PLAYERDEFEATEDTRAINER1
goto BattleScript_LocalBattleWonLoseTexts
BattleScript_LocalTwoTrainersDefeated::
printstring STRINGID_TWOENEMIESDEFEATED
BattleScript_LocalBattleWonLoseTexts::
trainerslidein BS_ATTACKER
waitstate
printstring STRINGID_TRAINER1LOSETEXT
jumpifnotbattletype BATTLE_TYPE_TWO_OPPONENTS, BattleScript_LocalTrainerBattleWonGotMoney
trainerslideout B_POSITION_OPPONENT_LEFT
waitstate
trainerslidein BS_FAINTED
waitstate
printstring STRINGID_TRAINER2LOSETEXT
BattleScript_LocalTrainerBattleWonGotMoney::
getmoneyreward
printstring STRINGID_PLAYERGOTMONEY
waitmessage B_WAIT_TIME_LONG
BattleScript_PayDayMoneyAndPickUpItems::
givepaydaymoney
pickup
end2
BattleScript_LocalBattleLost::
jumpifbattletype BATTLE_TYPE_INGAME_PARTNER, BattleScript_LocalBattleLostPrintWhiteOut
jumpifbattletype BATTLE_TYPE_TRAINER_TOWER, BattleScript_BattleTowerLost
jumpifbattletype BATTLE_TYPE_EREADER_TRAINER, BattleScript_LocalBattleLostEnd
jumpifhalfword CMP_EQUAL, gTrainerBattleOpponent_A, TRAINER_SECRET_BASE, BattleScript_LocalBattleLostEnd
jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, 0, BattleScript_RivalBattleLost
BattleScript_LocalBattleLostPrintWhiteOut::
.if B_WHITEOUT_MONEY >= GEN_4
jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_LocalBattleLostEnd
printstring STRINGID_PLAYERWHITEOUT
waitmessage B_WAIT_TIME_LONG
getmoneyreward
printstring STRINGID_PLAYERWHITEOUT2
waitmessage B_WAIT_TIME_LONG
end2
BattleScript_LocalBattleLostEnd::
printstring STRINGID_PLAYERLOSTAGAINSTENEMYTRAINER
waitmessage B_WAIT_TIME_LONG
getmoneyreward
printstring STRINGID_PLAYERPAIDPRIZEMONEY
waitmessage B_WAIT_TIME_LONG
end2
.else
printstring STRINGID_PLAYERWHITEOUT
waitmessage B_WAIT_TIME_LONG
printstring STRINGID_PLAYERWHITEOUT2
waitmessage B_WAIT_TIME_LONG
BattleScript_LocalBattleLostEnd::
end2
.endif
BattleScript_RivalBattleLost::
jumpifhasnohp BS_ATTACKER, BattleScript_RivalBattleLostSkipMonRecall
printstring STRINGID_TRAINER1MON1COMEBACK
@@ -128,11 +72,6 @@ BattleScript_BattleTowerEtcTrainerBattleWonSkipText::
pickup
end2
BattleScript_PrintCantRunFromTrainer::
jumpifbattletype BATTLE_TYPE_FIRST_BATTLE, BattleScript_LeftoverBirchString
printstring STRINGID_NORUNNINGFROMTRAINERS
end2
BattleScript_LeftoverBirchString::
printstring STRINGID_DONTLEAVEBIRCH
end2
@@ -170,6 +109,19 @@ BattleScript_DamageToQuarterTargetHP::
damagetoquartertargethp
goto BattleScript_HitFromAtkAnimation
BattleScript_EffectFickleBeam::
attackcanceler
attackstring
ppreduce
accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE
ficklebeamdamagecalculation
goto BattleScript_HitFromCritCalc
BattleScript_FickleBeamDoubled::
pause B_WAIT_TIME_SHORTEST
printstring STRINGID_FICKLEBEAMDOUBLED
waitmessage B_WAIT_TIME_LONG
goto BattleScript_HitFromCritCalc
BattleScript_Terastallization::
@ TODO: no string prints in S/V, but right now this helps with clarity
printstring STRINGID_PKMNSTORINGENERGY
@@ -283,6 +235,7 @@ BattleScript_EffectShedTail::
ppreduce
waitstate
jumpifstatus2 BS_ATTACKER, STATUS2_SUBSTITUTE, BattleScript_AlreadyHasSubstitute
jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_ButItFailed
jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_ButItFailed
setsubstitute
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_SUBSTITUTE_FAILED, BattleScript_SubstituteString
@@ -415,6 +368,7 @@ BattleScript_EffectChillyReceptionBlockedByStrongWinds:
call BattleScript_MysteriousAirCurrentBlowsOnRet
goto BattleScript_MoveSwitch
BattleScript_EffectChillyReceptionTrySwitchWeatherFailed:
jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_FailedFromAtkString
jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_FailedFromAtkString
call BattleScript_EffectChillyReceptionPlayAnimation
return
@@ -426,6 +380,7 @@ BattleScript_CheckPrimalWeather:
return
BattleScript_MoveSwitch:
jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_MoveSwitchEnd
jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_MoveSwitchEnd
printstring STRINGID_PKMNWENTBACK
waitmessage B_WAIT_TIME_SHORT
@@ -702,7 +657,7 @@ BattleScript_Teatimerod:
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_TeatimeBuffer
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_TeatimeBuffer
printfromtable gStatUpStringIds
waitmessage 0x40
waitmessage B_WAIT_TIME_LONG
moveendto MOVEEND_NEXT_TARGET
jumpifnexttargetvalid BattleScript_TeatimeLoop
moveendcase MOVEEND_CLEAR_BITS
@@ -714,7 +669,7 @@ BattleScript_Teatimemotor:
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_TeatimeBuffer
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_TeatimeBuffer
printfromtable gStatUpStringIds
waitmessage 0x40
waitmessage B_WAIT_TIME_LONG
moveendto MOVEEND_NEXT_TARGET
jumpifnexttargetvalid BattleScript_TeatimeLoop
moveendcase MOVEEND_CLEAR_BITS
@@ -1002,6 +957,7 @@ BattleScript_OctlockTurnDmgEnd:
BattleScript_EffectPoltergeist::
attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
ppreduce
checkpoltergeist BS_TARGET, BattleScript_ButItFailed
@@ -1051,19 +1007,10 @@ BattleScript_BothCanNoLongerEscape::
return
BattleScript_EffectHyperspaceFury::
jumpifspecies BS_ATTACKER, SPECIES_HOOPA_UNBOUND, BattleScript_EffectHyperspaceFuryUnbound
jumpifspecies BS_ATTACKER, SPECIES_HOOPA_UNBOUND, BattleScript_EffectHit
jumpifspecies BS_ATTACKER, SPECIES_HOOPA_CONFINED, BattleScript_ButHoopaCantUseIt
goto BattleScript_PokemonCantUseTheMove
BattleScript_EffectHyperspaceFuryUnbound::
attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
pause B_WAIT_TIME_LONG
ppreduce
seteffectprimary MOVE_EFFECT_FEINT
goto BattleScript_HitFromCritCalc
BattleScript_ButHoopaCantUseIt:
printstring STRINGID_BUTHOOPACANTUSEIT
waitmessage B_WAIT_TIME_LONG
@@ -3401,6 +3348,7 @@ BattleScript_EffectRoar::
jumpiftargetdynamaxed BattleScript_RoarBlockedByDynamax
accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON
accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE
jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_ButItFailed
forcerandomswitch BattleScript_ButItFailed
BattleScript_RoarBlockedByDynamax:
@@ -4553,6 +4501,7 @@ BattleScript_EffectBatonPass::
attackcanceler
attackstring
ppreduce
jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_ButItFailed
jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_ButItFailed
attackanimation
waitanimation
@@ -5724,6 +5673,62 @@ BattleScript_HandleFaintedMonMultipleEnd::
switchineffects BS_FAINTED_MULTIPLE_2
end2
BattleScript_LocalTrainerBattleWon::
jumpifbattletype BATTLE_TYPE_TWO_OPPONENTS, BattleScript_LocalTwoTrainersDefeated
printstring STRINGID_PLAYERDEFEATEDTRAINER1
goto BattleScript_LocalBattleWonLoseTexts
BattleScript_LocalTwoTrainersDefeated::
printstring STRINGID_TWOENEMIESDEFEATED
BattleScript_LocalBattleWonLoseTexts::
trainerslidein BS_ATTACKER
waitstate
printstring STRINGID_TRAINER1LOSETEXT
jumpifnotbattletype BATTLE_TYPE_TWO_OPPONENTS, BattleScript_LocalBattleWonReward
trainerslideout B_POSITION_OPPONENT_LEFT
waitstate
trainerslidein BS_FAINTED
waitstate
printstring STRINGID_TRAINER2LOSETEXT
BattleScript_LocalBattleWonReward::
getmoneyreward
printstring STRINGID_PLAYERGOTMONEY
waitmessage B_WAIT_TIME_LONG
BattleScript_PayDayMoneyAndPickUpItems::
givepaydaymoney
pickup
end2
BattleScript_LocalBattleLost::
jumpifbattletype BATTLE_TYPE_INGAME_PARTNER, BattleScript_LocalBattleLostPrintWhiteOut
jumpifbattletype BATTLE_TYPE_TRAINER_TOWER, BattleScript_BattleTowerLost
jumpifbattletype BATTLE_TYPE_EREADER_TRAINER, BattleScript_LocalBattleLostEnd
jumpifhalfword CMP_EQUAL, gTrainerBattleOpponent_A, TRAINER_SECRET_BASE, BattleScript_LocalBattleLostEnd
jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, 0, BattleScript_RivalBattleLost
BattleScript_LocalBattleLostPrintWhiteOut::
.if B_WHITEOUT_MONEY >= GEN_4
jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_LocalBattleLostEnd
printstring STRINGID_PLAYERWHITEOUT
waitmessage B_WAIT_TIME_LONG
getmoneyreward
printstring STRINGID_PLAYERWHITEOUT2
waitmessage B_WAIT_TIME_LONG
end2
BattleScript_LocalBattleLostEnd::
printstring STRINGID_PLAYERLOSTAGAINSTENEMYTRAINER
waitmessage B_WAIT_TIME_LONG
getmoneyreward
printstring STRINGID_PLAYERPAIDPRIZEMONEY
waitmessage B_WAIT_TIME_LONG
end2
.else
printstring STRINGID_PLAYERWHITEOUT
waitmessage B_WAIT_TIME_LONG
printstring STRINGID_PLAYERWHITEOUT2
waitmessage B_WAIT_TIME_LONG
BattleScript_LocalBattleLostEnd::
end2
.endif
BattleScript_SmokeBallEscape::
playanimation BS_ATTACKER, B_ANIM_SMOKEBALL_ESCAPE
printstring STRINGID_PKMNFLEDUSINGITS
@@ -5745,6 +5750,10 @@ BattleScript_WildMonFled::
waitmessage B_WAIT_TIME_LONG
end2
BattleScript_PrintCantRunFromTrainer::
printstring STRINGID_NORUNNINGFROMTRAINERS
end2
BattleScript_PrintFailedToRunString::
printfromtable gNoEscapeStringIds
waitmessage B_WAIT_TIME_LONG
@@ -7118,7 +7127,7 @@ BattleScript_TargetFormChangeWithStringNoPopup::
BattleScript_BattlerFormChangeWithStringEnd3::
pause 5
call BattleScript_AbilityPopUp
call BattleScript_AbilityPopUpScripting
flushtextbox
handleformchange BS_SCRIPTING, 0
handleformchange BS_SCRIPTING, 1
@@ -7722,6 +7731,15 @@ BattleScript_CheekPouchActivates::
copybyte gBattlerAttacker, sSAVED_BATTLER
return
BattleScript_PickupActivates::
pause 5
tryrecycleitem BattleScript_PickupActivatesEnd
call BattleScript_AbilityPopUp
printstring STRINGID_XFOUNDONEY
waitmessage B_WAIT_TIME_LONG
BattleScript_PickupActivatesEnd:
end3
BattleScript_HarvestActivates::
pause 5
tryrecycleitem BattleScript_HarvestActivatesEnd
@@ -7969,7 +7987,7 @@ BattleScript_DeltaStreamActivates::
end3
BattleScript_ProtosynthesisActivates::
call BattleScript_AbilityPopUp
call BattleScript_AbilityPopUpScripting
printstring STRINGID_SUNLIGHTACTIVATEDABILITY
waitmessage B_WAIT_TIME_MED
printstring STRINGID_STATWASHEIGHTENED

View File

@@ -574,12 +574,10 @@ struct LostItem
u16 stolen:1;
};
#if HQ_RANDOM == TRUE
struct BattleVideo {
u32 battleTypeFlags;
rng_value_t rngSeed;
};
#endif
struct BattleStruct
{
@@ -645,17 +643,13 @@ struct BattleStruct
u16 chosenItem[MAX_BATTLERS_COUNT];
u16 choicedMove[MAX_BATTLERS_COUNT];
u16 changedItems[MAX_BATTLERS_COUNT];
u8 canPickupItem;
u8 switchInBattlerCounter;
u8 turnSideTracker;
u16 lastTakenMoveFrom[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT]; // a 2-D array [target][attacker]
union {
struct LinkBattlerHeader linkBattlerHeader;
#if HQ_RANDOM == FALSE
u32 battleVideo[2];
#else
struct BattleVideo battleVideo;
#endif
} multiBuffer;
u8 wishPerishSongState;
u8 wishPerishSongBattlerId;
@@ -724,7 +718,6 @@ struct BattleStruct
bool8 effectsBeforeUsingMoveDone:1; // Mega Evo and Focus Punch/Shell Trap effects.
u8 targetsDone[MAX_BATTLERS_COUNT]; // Each battler as a bit.
u16 overwrittenAbilities[MAX_BATTLERS_COUNT]; // abilities overwritten during battle (keep separate from battle history in case of switching)
bool8 allowedToChangeFormInWeather[PARTY_SIZE][NUM_BATTLE_SIDES]; // For each party member and side, used by Ice Face.
u8 battleBondTransformed[NUM_BATTLE_SIDES]; // Bitfield for each party.
u8 storedHealingWish:4; // Each battler as a bit.
u8 storedLunarDance:4; // Each battler as a bit.
@@ -761,6 +754,7 @@ struct BattleStruct
u8 distortedTypeMatchups;
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;
// pokefirered
u8 field_DA; // battle tower related

View File

@@ -31,8 +31,8 @@ bool32 NoAliveMonsForPlayer(void);
bool32 NoAliveMonsForEitherParty(void);
void SetMoveEffect(bool32 primary, bool32 certain);
bool32 CanBattlerSwitch(u32 battlerId);
void BattleDestroyYesNoCursorAt(void);
void BattleCreateYesNoCursorAt(void);
void BattleDestroyYesNoCursorAt(u8 cursorPosition);
void BattleCreateYesNoCursorAt(u8 cursorPosition);
void BufferMoveToLearnIntoBattleTextBuff2(void);
void HandleBattleWindow(u8 xStart, u8 yStart, u8 xEnd, u8 yEnd, u8 flags);
bool8 UproarWakeUpCheck(u8 battlerId);

View File

@@ -737,6 +737,7 @@ extern const u8 BattleScript_WeakArmorActivates[];
extern const u8 BattleScript_FellStingerRaisesStat[];
extern const u8 BattleScript_SnowWarningActivatesHail[];
extern const u8 BattleScript_SnowWarningActivatesSnow[];
extern const u8 BattleScript_PickupActivates[];
extern const u8 BattleScript_HarvestActivates[];
extern const u8 BattleScript_ImposterActivates[];
extern const u8 BattleScript_SelectingNotAllowedMoveAssaultVest[];
@@ -1274,6 +1275,8 @@ extern const u8 BattleScript_EffectUpperHand[];
extern const u8 BattleScript_EffectTidyUp[];
extern const u8 BattleScript_EffectSpicyExtract[];
extern const u8 BattleScript_DamageToQuarterTargetHP[];
extern const u8 BattleScript_EffectFickleBeam[];
extern const u8 BattleScript_FickleBeamDoubled[];
#endif // GUARD_BATTLE_SCRIPTS_H

View File

@@ -232,6 +232,8 @@ bool32 TryRoomService(u32 battler);
void BufferStatChange(u32 battler, u8 statId, u8 stringId);
bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 checkTarget);
u16 GetUsedHeldItem(u32 battler);
bool32 PickupHasValidTarget(u32 battler);
bool32 CantPickupItem(u32 battler);
bool32 IsBattlerWeatherAffected(u32 battler, u32 weatherFlags);
u32 GetBattlerMoveTargetType(u32 battler, u32 move);
bool32 CanTargetBattler(u32 battlerAtk, u32 battlerDef, u16 move);

View File

@@ -110,7 +110,7 @@
#define B_BURN_HIT_THAW GEN_LATEST // In Gen6+, damaging moves with a chance of burn will thaw the target, regardless if they're fire-type moves or not.
#define B_HEALING_WISH_SWITCH GEN_LATEST // In Gen5+, the mon receiving Healing Wish is sent out at the end of the turn.
// Additionally, in gen8+ the Healing Wish's effect will be stored until the user switches into a statused or hurt mon.
#define B_DEFOG_CLEARS_TERRAIN GEN_LATEST // In Gen8+, Defog also clears active Terrain.
#define B_DEFOG_EFFECT_CLEARING GEN_LATEST // In Gen6+, Defog clears Spikes, Toxic Spikes, Stealth Rock and Sticky Web from both sides. In Gen8+, Defog also clears active Terrain.
#define B_STOCKPILE_RAISES_DEFS GEN_LATEST // In Gen4+, Stockpile also raises Defense and Sp. Defense stats. Once Spit Up / Swallow is used, these stat changes are lost.
#define B_TRANSFORM_SHINY GEN_LATEST // In Gen4+, Transform will copy the shiny state of the opponent instead of maintaining its own shiny state.
#define B_TRANSFORM_FORM_CHANGES GEN_LATEST // In Gen5+, Transformed Pokemon cannot change forms.
@@ -219,7 +219,7 @@
#define B_FAST_HP_DRAIN TRUE // If set to TRUE, HP bars will move faster.
#define B_FAST_EXP_GROW TRUE // If set to TRUE, EXP bars will move faster.
#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 showing the move's category.
#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.
@@ -251,26 +251,31 @@
#define B_TRY_CATCH_TRAINER_BALL GEN_LATEST // In Gen4+, trying to catch a Trainer's Pokémon does not consume the Poké Ball.
// Animation Settings
#define B_NEW_SWORD_PARTICLE TRUE // If set to TRUE, it updates Swords Dance's particle.
#define B_NEW_LEECH_SEED_PARTICLE TRUE // If set to TRUE, it updates Leech Seed's animation particle.
#define B_NEW_HORN_ATTACK_PARTICLE TRUE // If set to TRUE, it updates Horn Attack's horn particle.
#define B_NEW_ROCKS_PARTICLE TRUE // If set to TRUE, it updates rock particles.
#define B_NEW_LEAF_PARTICLE TRUE // If set to TRUE, it updates leaf particle.
#define B_NEW_EMBER_PARTICLES TRUE // If set to TRUE, it updates Ember's fire particle.
#define B_NEW_MEAN_LOOK_PARTICLE TRUE // If set to TRUE, it updates Mean Look's eye particle.
#define B_NEW_TEETH_PARTICLE TRUE // If set to TRUE, it updates Bite/Crunch teeth particle.
#define B_NEW_HANDS_FEET_PARTICLE TRUE // If set to TRUE, it updates chop/kick/punch particles.
#define B_NEW_SPIKES_PARTICLE TRUE // If set to TRUE, it updates Spikes particle.
#define B_NEW_FLY_BUBBLE_PARTICLE TRUE // If set to TRUE, it updates Fly's 'bubble' particle.
#define B_NEW_CURSE_NAIL_PARTICLE TRUE // If set to TRUE, it updates Curse's nail.
#define B_NEW_BATON_PASS_BALL_PARTICLE TRUE // If set to TRUE, it updates Baton Pass' Poké Ball sprite.
#define B_NEW_MORNING_SUN_STAR_PARTICLE TRUE // If set to TRUE, it updates Morning Sun's star particles.
#define B_NEW_IMPACT_PALETTE TRUE // If set to TRUE, it updates the basic 'hit' palette.
#define B_NEW_SURF_PARTICLE_PALETTE TRUE // If set to TRUE, it updates Surf's wave palette.
#define B_NEW_SWORD_PARTICLE FALSE // If set to TRUE, it updates Swords Dance's particle.
#define B_NEW_LEECH_SEED_PARTICLE FALSE // If set to TRUE, it updates Leech Seed's animation particle.
#define B_NEW_HORN_ATTACK_PARTICLE FALSE // If set to TRUE, it updates Horn Attack's horn particle.
#define B_NEW_ROCKS_PARTICLE FALSE // If set to TRUE, it updates rock particles.
#define B_NEW_LEAF_PARTICLE FALSE // If set to TRUE, it updates leaf particle.
#define B_NEW_EMBER_PARTICLES FALSE // If set to TRUE, it updates Ember's fire particle.
#define B_NEW_MEAN_LOOK_PARTICLE FALSE // If set to TRUE, it updates Mean Look's eye particle.
#define B_NEW_TEETH_PARTICLE FALSE // If set to TRUE, it updates Bite/Crunch teeth particle.
#define B_NEW_HANDS_FEET_PARTICLE FALSE // If set to TRUE, it updates chop/kick/punch particles.
#define B_NEW_SPIKES_PARTICLE FALSE // If set to TRUE, it updates Spikes particle.
#define B_NEW_FLY_BUBBLE_PARTICLE FALSE // If set to TRUE, it updates Fly's 'bubble' particle.
#define B_NEW_CURSE_NAIL_PARTICLE FALSE // If set to TRUE, it updates Curse's nail.
#define B_NEW_BATON_PASS_BALL_PARTICLE FALSE // If set to TRUE, it updates Baton Pass' Poké Ball sprite.
#define B_NEW_MORNING_SUN_STAR_PARTICLE FALSE // If set to TRUE, it updates Morning Sun's star particles.
#define B_NEW_IMPACT_PALETTE FALSE // If set to TRUE, it updates the basic 'hit' palette.
#define B_NEW_SURF_PARTICLE_PALETTE FALSE // If set to TRUE, it updates Surf's wave palette.
// Poké Ball animation and sounds
#define B_ENEMY_THROW_BALLS GEN_LATEST // In GEN_6+, enemy Trainers throw Poké Balls into battle instead of them just appearing on the ground and opening.
#define B_ENEMY_THROW_BALLS_SOUND GEN_LATEST // In GEN_5+, enemy Trainer's Poké Balls make a sound when thrown to send out a Pokémon. This can only be used when B_ENEMY_THROW_BALLS is set to GEN_6 or later.
#define B_PLAYER_THROW_BALLS_SOUND GEN_LATEST // In GEN_5+, the player's Poké Balls make a sound when thrown to send out a Pokémon.
#define SHOW_TYPES_NEVER 0
#define SHOW_TYPES_ALWAYS 1
#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.
#endif // GUARD_CONFIG_BATTLE_H

View File

@@ -1336,8 +1336,9 @@
#define STRINGID_FOGISDEEP 737
#define STRINGID_FOGLIFTED 738
#define STRINGID_PKMNMADESHELLGLEAM 739
#define STRINGID_FICKLEBEAMDOUBLED 740
#define BATTLESTRINGS_COUNT 740
#define BATTLESTRINGS_COUNT 741
// This is the string id that gBattleStringsTable starts with.
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,

View File

@@ -7,25 +7,21 @@
#define ISO_RANDOMIZE1(val)(RAND_MULT * (val) + 24691)
#define ISO_RANDOMIZE2(val)(RAND_MULT * (val) + 12345)
/* Some functions have been added to support HQ_RANDOM.
/* Some functions have been added to support Expansion's RNG implementation.
*
* If using HQ_RANDOM, you cannot call Random() in interrupt handlers safely.
* AdvanceRandom() is provided to handle burning numbers in the VBlank handler
* if you choose to do that, and can be used regardless of HQ_RANDOM setting.
* LocalRandom(*val) provides a higher-quality replacement for uses of
* ISO_RANDOMIZE in vanilla Emerald. You can use LocalRandomSeed(u32) to
* create a local state.
*
* It is no longer possible to call Random() in interrupt handlers safely.
* AdvanceRandom() is provided to handle burning numbers in VBlank handlers.
* If you need to use random numbers in the VBlank handler, a local state
* should be used instead.
*
* LocalRandom(*val) allows you to have local random states that are the same
* type as the global states regardless of HQ_RANDOM setting, which is useful
* if you want to be able to set them from or assign them to gRngValue.
* LocalRandomSeed(u32) returns a properly seeded rng_value_t.
*
* Random2_32() was added to HQ_RANDOM because the output of the generator is
* always 32 bits and Random()/Random2() are just wrappers in that mode. It is
* also available in non-HQ mode for consistency.
* Random2_32() was added, even though it is not used directly, because the
* underlying RNG always outputs 32 bits.
*/
#if HQ_RANDOM == TRUE
struct Sfc32State {
u32 a;
u32 b;
@@ -71,40 +67,6 @@ static inline u16 Random2(void)
}
void AdvanceRandom(void);
#else
typedef u32 rng_value_t;
#define RNG_VALUE_EMPTY 0
//Returns a 16-bit pseudorandom number
u16 Random(void);
u16 Random2(void);
//Sets the initial seed value of the pseudorandom number generator
void SeedRng(u16 seed);
void SeedRng2(u16 seed);
//Returns a 32-bit pseudorandom number
#define Random32() (Random() | (Random() << 16))
#define Random2_32() (Random2() | (Random2() << 16))
static inline u16 LocalRandom(rng_value_t *val)
{
*val = ISO_RANDOMIZE1(*val);
return *val >> 16;
}
static inline void AdvanceRandom(void)
{
Random();
}
static inline rng_value_t LocalRandomSeed(u32 seed)
{
return seed;
}
#endif
extern rng_value_t gRngValue;
extern rng_value_t gRng2Value;
@@ -174,12 +136,14 @@ enum RandomTag
RNG_G_MAX_BEFUDDLE,
RNG_G_MAX_REPLENISH,
RNG_G_MAX_SNOOZE,
RNG_HARVEST,
RNG_HITS,
RNG_HOLD_EFFECT_FLINCH,
RNG_INFATUATION,
RNG_LOADED_DICE,
RNG_METRONOME,
RNG_PARALYSIS,
RNG_PICKUP,
RNG_POISON_POINT,
RNG_POISON_TOUCH,
RNG_RAMPAGE_TURNS,

View File

@@ -6,6 +6,7 @@
#include "battle_ai_util.h"
#include "battle_ai_main.h"
#include "battle_controllers.h"
// #include "battle_factory.h"
#include "battle_setup.h"
#include "battle_z_move.h"
#include "battle_terastal.h"
@@ -107,7 +108,7 @@ void BattleAI_SetupItems(void)
// Items are allowed to use in ONLY trainer battles.
if ((gBattleTypeFlags & BATTLE_TYPE_TRAINER)
&& !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_SAFARI | BATTLE_TYPE_BATTLE_TOWER
| BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_SECRET_BASE | BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_RECORDED_LINK)
)
)
@@ -167,13 +168,13 @@ static u32 GetAiFlags(u16 trainerId)
flags = AI_FLAG_CHECK_BAD_MOVE;
// else if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)
// flags = AI_FLAG_FIRST_BATTLE;
else if (gBattleTypeFlags & (BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TRAINER_TOWER))
else if (gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TRAINER_HILL | BATTLE_TYPE_SECRET_BASE))
flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT;
else
flags = GetTrainerAIFlagsFromId(trainerId);
}
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
if (IsDoubleBattle())
{
flags |= AI_FLAG_DOUBLE_BATTLE;
}
@@ -223,7 +224,7 @@ void BattleAI_SetupFlags(void)
{
AI_THINKING_STRUCT->aiFlags[B_POSITION_PLAYER_RIGHT] = GetAiFlags(gPartnerTrainerId - TRAINER_PARTNER(PARTNER_NONE));
}
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsAiVsAiBattle())
else if (IsDoubleBattle() && IsAiVsAiBattle())
{
AI_THINKING_STRUCT->aiFlags[B_POSITION_PLAYER_RIGHT] = AI_THINKING_STRUCT->aiFlags[B_POSITION_PLAYER_LEFT];
}
@@ -261,7 +262,7 @@ void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler)
// Ignore moves that aren't possible to use.
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (gBitTable[i] & moveLimitations)
if ((1u << i) & moveLimitations)
SET_SCORE(battler, i, 0);
}
@@ -274,7 +275,7 @@ u32 BattleAI_ChooseMoveOrAction(void)
{
u32 ret;
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
if (!IsDoubleBattle())
ret = ChooseMoveOrAction_Singles(sBattler_AI);
else
ret = ChooseMoveOrAction_Doubles(sBattler_AI);
@@ -322,7 +323,7 @@ void Ai_InitPartyStruct(void)
// Save first 2 or 4(in doubles) mons
CopyBattlerDataToAIParty(B_POSITION_PLAYER_LEFT, B_SIDE_PLAYER);
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
if (IsDoubleBattle())
CopyBattlerDataToAIParty(B_POSITION_PLAYER_RIGHT, B_SIDE_PLAYER);
// If player's partner is AI, save opponent mons
@@ -445,7 +446,7 @@ static void SetBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u3
if (move != 0
&& move != 0xFFFF
//&& gMovesInfo[move].power != 0 /* we want to get effectiveness and accuracy of status moves */
&& !(aiData->moveLimitations[battlerAtk] & gBitTable[i]))
&& !(aiData->moveLimitations[battlerAtk] & (1u << i)))
{
if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_RISKY)
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, TRUE, weather, DMG_ROLL_HIGHEST);
@@ -505,12 +506,12 @@ static bool32 AI_SwitchMonIfSuitable(u32 battler, bool32 doubleBattle)
if (doubleBattle)
{
u32 partner = BATTLE_PARTNER(battler);
if (AI_DATA->shouldSwitchMon & gBitTable[partner] && AI_DATA->monToSwitchId[partner] == monToSwitchId)
if (AI_DATA->shouldSwitchMon & (1u << partner) && AI_DATA->monToSwitchId[partner] == monToSwitchId)
{
return FALSE;
}
}
AI_DATA->shouldSwitchMon |= gBitTable[battler];
AI_DATA->shouldSwitchMon |= 1 << battler;
AI_DATA->monToSwitchId[battler] = monToSwitchId;
return TRUE;
}
@@ -523,6 +524,7 @@ static bool32 AI_ShouldSwitchIfBadMoves(u32 battler, bool32 doubleBattle)
// If can switch.
if (CountUsablePartyMons(battler) > 0
&& !IsBattlerTrapped(battler, TRUE)
&& !(gBattleTypeFlags & (BATTLE_TYPE_ARENA | BATTLE_TYPE_PALACE))
&& AI_THINKING_STRUCT->aiFlags[battler] & (AI_FLAG_CHECK_VIABILITY | AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_PREFER_BATON_PASS)
&& !(AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SEQUENCE_SWITCHING))
{
@@ -1734,6 +1736,14 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
break;
case EFFECT_HIT_ESCAPE:
break;
case EFFECT_CHILLY_RECEPTION:
if (CountUsablePartyMons(battlerAtk) == 0)
ADJUST_SCORE(-10);
else if (weather & (B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY) || IsMoveEffectWeather(aiData->partnerMove))
ADJUST_SCORE(-8);
else if (weather & B_WEATHER_HAIL)
ADJUST_SCORE(-2); // mainly to prevent looping between hail and snow
break;
case EFFECT_BELLY_DRUM:
case EFFECT_FILLET_AWAY:
if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY)
@@ -2045,7 +2055,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
}
/*if (AI_THINKING_STRUCT->aiFlags[battlerAtk] == AI_SCRIPT_CHECK_BAD_MOVE //Only basic AI
&& IS_DOUBLE_BATTLE) //Make the regular AI know how to use Protect minimally in Doubles
&& IsDoubleBattle()) //Make the regular AI know how to use Protect minimally in Doubles
{
u8 shouldProtect = ShouldProtect(battlerAtk, battlerDef, move);
if (shouldProtect == USE_PROTECT || shouldProtect == PROTECT_FROM_FOES)
@@ -2768,6 +2778,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
case EFFECT_SNOWSCAPE:
case EFFECT_RAIN_DANCE:
case EFFECT_SANDSTORM:
case EFFECT_CHILLY_RECEPTION:
if (IsMoveEffectWeather(move))
ADJUST_SCORE(-10);
break;
@@ -2847,6 +2858,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
}
break;
case EFFECT_SNOWSCAPE:
case EFFECT_CHILLY_RECEPTION:
if (IsBattlerAlive(battlerAtkPartner)
&& ShouldSetSnow(battlerAtkPartner, atkPartnerAbility, atkPartnerHoldEffect))
{
@@ -3616,6 +3628,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
//fallthrough
case EFFECT_HIT_ESCAPE:
case EFFECT_PARTING_SHOT:
case EFFECT_CHILLY_RECEPTION:
if (!IsDoubleBattle())
{
switch (ShouldPivot(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, movesetIndex))
@@ -4051,7 +4064,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
ADJUST_SCORE(DECENT_EFFECT); // Force 'em out next turn
break;
default:
if (move != MOVE_BESTOW && aiData->items[battlerAtk] == ITEM_NONE)
if (gMovesInfo[gCurrentMove].effect != EFFECT_BESTOW && aiData->items[battlerAtk] == ITEM_NONE)
{
switch (aiData->holdEffects[battlerDef])
{
@@ -4874,6 +4887,7 @@ static s32 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
case EFFECT_SANDSTORM:
case EFFECT_HAIL:
case EFFECT_SNOWSCAPE:
case EFFECT_CHILLY_RECEPTION:
case EFFECT_GEOMANCY:
case EFFECT_VICTORY_DANCE:
ADJUST_SCORE(DECENT_EFFECT);
@@ -5042,7 +5056,7 @@ static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 scor
static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
{
u32 effect = gMovesInfo[move].effect;
u32 moveType = TYPE_NONE;
u32 moveType = 0;
SetTypeBeforeUsingMove(move, battlerAtk);
moveType = GetMoveType(move);

View File

@@ -40,7 +40,7 @@ static void InitializeSwitchinCandidate(struct Pokemon *mon)
static bool32 IsAceMon(u32 battler, u32 monPartyId)
{
if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_ACE_POKEMON
&& !(gBattleStruct->forcedSwitch & gBitTable[battler])
&& !(gBattleStruct->forcedSwitch & (1u << battler))
&& monPartyId == CalculateEnemyPartyCount()-1)
return TRUE;
return FALSE;
@@ -82,7 +82,7 @@ static bool32 HasBadOdds(u32 battler, bool32 emitResult)
return FALSE;
// Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
if (IsDoubleBattle())
return FALSE;
opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battler));
@@ -218,9 +218,9 @@ static bool32 HasBadOdds(u32 battler, bool32 emitResult)
static bool32 ShouldSwitchIfAllBadMoves(u32 battler, bool32 emitResult)
{
if (AI_DATA->shouldSwitchMon & gBitTable[battler])
if (AI_DATA->shouldSwitchMon & (1u << battler))
{
AI_DATA->shouldSwitchMon &= ~(gBitTable[battler]);
AI_DATA->shouldSwitchMon &= ~(1u << battler);
gBattleStruct->AI_monToSwitchIntoId[battler] = AI_DATA->monToSwitchId[battler];
if (emitResult)
BtlController_EmitTwoReturnValues(battler, BUFFER_B, B_ACTION_SWITCH, 0);
@@ -242,7 +242,7 @@ static bool32 ShouldSwitchIfWonderGuard(u32 battler, bool32 emitResult)
struct Pokemon *party = NULL;
u16 move;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
if (IsDoubleBattle())
return FALSE;
opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battler));
@@ -318,10 +318,10 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler, bool32 emitResult)
if (IS_MOVE_STATUS(gLastLandedMoves[battler]))
return FALSE;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
if (IsDoubleBattle())
{
battlerIn1 = battler;
if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))])
if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))))
battlerIn2 = battler;
else
battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)));
@@ -690,7 +690,7 @@ static bool32 HasSuperEffectiveMoveAgainstOpponents(u32 battler, bool32 noRng)
u32 opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battler));
u32 opposingBattler = GetBattlerAtPosition(opposingPosition);
if (!(gAbsentBattlerFlags & gBitTable[opposingBattler]))
if (!(gAbsentBattlerFlags & (1u << opposingBattler)))
{
for (i = 0; i < MAX_MON_MOVES; i++)
{
@@ -707,12 +707,12 @@ static bool32 HasSuperEffectiveMoveAgainstOpponents(u32 battler, bool32 noRng)
}
}
}
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
if (!IsDoubleBattle())
return FALSE;
opposingBattler = GetBattlerAtPosition(BATTLE_PARTNER(opposingPosition));
if (!(gAbsentBattlerFlags & gBitTable[opposingBattler]))
if (!(gAbsentBattlerFlags & (1u << opposingBattler)))
{
for (i = 0; i < MAX_MON_MOVES; i++)
{
@@ -765,10 +765,10 @@ static bool32 FindMonWithFlagsAndSuperEffective(u32 battler, u16 flags, u32 modu
if (IS_MOVE_STATUS(gLastLandedMoves[battler]))
return FALSE;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
if (IsDoubleBattle())
{
battlerIn1 = battler;
if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))])
if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))))
battlerIn2 = battler;
else
battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)));
@@ -846,10 +846,10 @@ static bool32 CanMonSurviveHazardSwitchin(u32 battler)
// Battler will faint to hazards, check to see if another mon can clear them
if (hazardDamage > battlerHp)
{
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
if (IsDoubleBattle())
{
battlerIn1 = battler;
if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))])
if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))))
battlerIn2 = battler;
else
battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)));
@@ -881,7 +881,9 @@ static bool32 CanMonSurviveHazardSwitchin(u32 battler)
for (j = 0; j < MAX_MON_MOVES; j++)
{
aiMove = GetMonData(&party[i], MON_DATA_MOVE1 + j, NULL);
if (aiMove == MOVE_RAPID_SPIN || aiMove == MOVE_DEFOG || aiMove == MOVE_MORTAL_SPIN || aiMove == MOVE_TIDY_UP)
if (MoveHasAdditionalEffectSelf(aiMove, MOVE_EFFECT_RAPID_SPIN)
|| (B_DEFOG_EFFECT_CLEARING >= GEN_6 && gMovesInfo[aiMove].effect == EFFECT_DEFOG)
|| gMovesInfo[aiMove].effect == EFFECT_TIDY_UP)
{
// Have a mon that can clear the hazards, so switching out is okay
return TRUE;
@@ -1014,6 +1016,8 @@ bool32 ShouldSwitch(u32 battler, bool32 emitResult)
return FALSE;
if (IsAbilityPreventingEscape(battler))
return FALSE;
if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
return FALSE;
// Sequence Switching AI never switches mid-battle
if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SEQUENCE_SWITCHING)
@@ -1021,10 +1025,10 @@ bool32 ShouldSwitch(u32 battler, bool32 emitResult)
availableToSwitch = 0;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
if (IsDoubleBattle())
{
battlerIn1 = battler;
if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))])
if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))))
battlerIn2 = battler;
else
battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)));
@@ -1138,7 +1142,7 @@ void AI_TrySwitchOrUseItem(u32 battler)
s32 monToSwitchId = AI_DATA->mostSuitableMonId[battler];
if (monToSwitchId == PARTY_SIZE)
{
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
if (!IsDoubleBattle())
{
battlerIn1 = GetBattlerAtPosition(battlerPosition);
battlerIn2 = battlerIn1;
@@ -1193,14 +1197,14 @@ static u32 GetBestMonBatonPass(struct Pokemon *party, int firstId, int lastId, u
for (i = firstId; i < lastId; i++)
{
if (invalidMons & gBitTable[i])
if (invalidMons & (1u << i))
continue;
for (j = 0; j < MAX_MON_MOVES; j++)
{
if (GetMonData(&party[i], MON_DATA_MOVE1 + j, NULL) == MOVE_BATON_PASS)
{
bits |= gBitTable[i];
bits |= 1u << i;
break;
}
}
@@ -1211,7 +1215,7 @@ static u32 GetBestMonBatonPass(struct Pokemon *party, int firstId, int lastId, u
do
{
i = (Random() % (lastId - firstId)) + firstId;
} while (!(bits & gBitTable[i]));
} while (!(bits & (1 << i)));
return i;
}
@@ -1229,7 +1233,7 @@ static u32 GetBestMonTypeMatchup(struct Pokemon *party, int firstId, int lastId,
// Find the mon whose type is the most suitable defensively.
for (i = firstId; i < lastId; i++)
{
if (!(gBitTable[i] & invalidMons) && !(gBitTable[i] & bits))
if (!((1u << i) & invalidMons) && !((1u << i) & bits))
{
u16 species = GetMonData(&party[i], MON_DATA_SPECIES);
uq4_12_t typeEffectiveness = UQ_4_12(1.0);
@@ -1269,7 +1273,7 @@ static u32 GetBestMonTypeMatchup(struct Pokemon *party, int firstId, int lastId,
if (i != MAX_MON_MOVES)
return bestMonId; // Has both the typing and at least one super effective move.
bits |= gBitTable[bestMonId]; // Sorry buddy, we want something better.
bits |= (1u << bestMonId); // Sorry buddy, we want something better.
}
else
{
@@ -1291,7 +1295,7 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva
// If we couldn't find the best mon in terms of typing, find the one that deals most damage.
for (i = firstId; i < lastId; i++)
{
if (gBitTable[i] & invalidMons)
if ((1 << (i)) & invalidMons)
continue;
InitializeSwitchinCandidate(&party[i]);
for (j = 0; j < MAX_MON_MOVES; j++)
@@ -1562,9 +1566,9 @@ static u32 GetSwitchinStatusDamage(u32 battler)
if ((status & STATUS1_TOXIC_COUNTER) != STATUS1_TOXIC_TURN(15)) // not 16 turns
AI_DATA->switchinCandidate.battleMon.status1 += STATUS1_TOXIC_TURN(1);
statusDamage = maxHP / 16;
statusDamage *= AI_DATA->switchinCandidate.battleMon.status1 & STATUS1_TOXIC_COUNTER >> 8;
if (statusDamage == 0)
statusDamage = 1;
statusDamage *= AI_DATA->switchinCandidate.battleMon.status1 & STATUS1_TOXIC_COUNTER >> 8;
}
}
@@ -1731,7 +1735,7 @@ static int GetRandomSwitchinWithBatonPass(int aliveCount, int bits, int firstId,
do
{
return (Random() % (lastId - firstId)) + firstId;
} while (!(bits & gBitTable[currentMonId]));
} while (!(bits & (1 << (currentMonId))));
}
// Catch any other cases (such as only one mon alive and it has Baton Pass)
@@ -1871,7 +1875,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
// Check for Baton Pass; hitsToKO requirements mean mon can boost and BP without dying whether it's slower or not
if (aiMove == MOVE_BATON_PASS && ((hitsToKOAI > hitsToKOAIThreshold + 1 && AI_DATA->switchinCandidate.battleMon.speed < playerMonSpeed) || (hitsToKOAI > hitsToKOAIThreshold && AI_DATA->switchinCandidate.battleMon.speed > playerMonSpeed)))
bits |= gBitTable[i];
bits |= 1u << i;
// Check for mon with resistance and super effective move for GetBestMonTypeMatchup
if (aiMove != MOVE_NONE && gMovesInfo[aiMove].power != 0)
@@ -1998,7 +2002,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_HIT_ESCAPE || gMovesInfo[gLastUsedMove].effect == EFFECT_PARTING_SHOT || gMovesInfo[gLastUsedMove].effect == EFFECT_BATON_PASS || gMovesInfo[gLastUsedMove].effect == EFFECT_CHILLY_RECEPTION))
return aceMonId;
return PARTY_SIZE;
@@ -2035,17 +2039,19 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd)
if (*(gBattleStruct->monToSwitchIntoId + battler) != PARTY_SIZE)
return *(gBattleStruct->monToSwitchIntoId + battler);
if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
return gBattlerPartyIndexes[battler] + 1;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
if (IsDoubleBattle())
{
battlerIn1 = battler;
if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))])
if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))))
battlerIn2 = battler;
else
battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)));
opposingBattler = BATTLE_OPPOSITE(battlerIn1);
if (gAbsentBattlerFlags & gBitTable[opposingBattler])
if (gAbsentBattlerFlags & (1u << opposingBattler))
opposingBattler ^= BIT_FLANK;
}
else
@@ -2070,7 +2076,7 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd)
// Split ideal mon decision between after previous mon KO'd (prioritize offensive options) and after switching active mon out (prioritize defensive options), and expand the scope of both.
// Only use better mon selection if AI_FLAG_SMART_MON_CHOICES is set for the trainer.
if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_MON_CHOICES && !(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) // Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic
if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_MON_CHOICES && !IsDoubleBattle()) // Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic
{
bestMonId = GetBestMonIntegrated(party, firstId, lastId, battler, opposingBattler, battlerIn1, battlerIn2, switchAfterMonKOd);
return bestMonId;
@@ -2091,12 +2097,12 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd)
|| i == gBattleStruct->monToSwitchIntoId[battlerIn2]
|| (GetMonAbility(&party[i]) == ABILITY_TRUANT && IsTruantMonVulnerable(battler, opposingBattler))) // While not really invalid per se, not really wise to switch into this mon.)
{
invalidMons |= gBitTable[i];
invalidMons |= 1u << i;
}
else if (IsAceMon(battler, i))// Save Ace Pokemon for last.
{
aceMonId = i;
invalidMons |= gBitTable[i];
invalidMons |= 1u << i;
}
else
{

View File

@@ -6,6 +6,7 @@
#include "battle_ai_util.h"
#include "battle_ai_main.h"
#include "battle_ai_switch_items.h"
// #include "battle_factory.h"
#include "battle_setup.h"
#include "event_data.h"
#include "data.h"
@@ -350,12 +351,12 @@ bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, u32 category)
if (moves[i] != MOVE_NONE
&& moves[i] != MOVE_UNAVAILABLE
&& GetBattleMoveCategory(moves[i]) == category
&& !(unusable & gBitTable[i]))
&& !(unusable & (1u << i)))
{
SetTypeBeforeUsingMove(moves[i], attacker);
moveType = GetMoveType(moves[i]);
if (CalcTypeEffectivenessMultiplier(moves[i], moveType, attacker, target, AI_DATA->abilities[target], FALSE) != 0)
usable |= gBitTable[i];
usable |= 1u << i;
}
}
@@ -481,7 +482,7 @@ bool32 IsDamageMoveUnusable(u32 move, u32 battlerAtk, u32 battlerDef)
return TRUE;
break;
case EFFECT_POLTERGEIST:
if (AI_DATA->items[battlerDef] == ITEM_NONE)
if (AI_DATA->items[battlerDef] == ITEM_NONE || gFieldStatuses & STATUS_FIELD_MAGIC_ROOM || battlerDefAbility == ABILITY_KLUTZ)
return TRUE;
break;
case EFFECT_FIRST_TURN_ONLY:
@@ -575,13 +576,13 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u
if (critChanceIndex > 1) // Consider crit damage only if a move has at least +2 crit chance
{
s32 nonCritDmg = CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower,
effectivenessMultiplier, weather, FALSE,
aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef],
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
effectivenessMultiplier, weather, FALSE,
aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef],
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
s32 critDmg = CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower,
effectivenessMultiplier, weather, TRUE,
aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef],
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
effectivenessMultiplier, weather, TRUE,
aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef],
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
u32 critOdds = GetCritHitOdds(critChanceIndex);
// With critOdds getting closer to 1, dmg gets closer to critDmg.
@@ -594,20 +595,33 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u
else if (critChanceIndex == -2) // Guaranteed critical
{
s32 critDmg = CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower,
effectivenessMultiplier, weather, TRUE,
aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef],
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
effectivenessMultiplier, weather, TRUE,
aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef],
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
simDamage.expected = GetDamageByRollType(critDmg, rollType);
simDamage.minimum = LowestRollDmg(critDmg);
}
else
{
s32 nonCritDmg = CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower,
effectivenessMultiplier, weather, FALSE,
aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef],
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
s32 nonCritDmg = 0;
if (gMovesInfo[move].effect == EFFECT_TRIPLE_KICK)
{
for (gMultiHitCounter = gMovesInfo[move].strikeCount; gMultiHitCounter > 0; gMultiHitCounter--) // The global is used to simulate actual damage done
{
nonCritDmg += CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower,
effectivenessMultiplier, weather, FALSE,
aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef],
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
}
}
else
{
nonCritDmg = CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower,
effectivenessMultiplier, weather, FALSE,
aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef],
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
}
simDamage.expected = GetDamageByRollType(nonCritDmg, rollType);
simDamage.minimum = LowestRollDmg(nonCritDmg);
}
@@ -1091,7 +1105,7 @@ bool32 CanTargetFaintAi(u32 battlerDef, u32 battlerAtk)
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(unusable & gBitTable[i])
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(unusable & (1u << i))
&& AI_DATA->simulatedDmg[battlerDef][battlerAtk][i].expected >= gBattleMons[battlerAtk].hp)
{
return TRUE;
@@ -1129,7 +1143,7 @@ u32 GetBestDmgMoveFromBattler(u32 battlerAtk, u32 battlerDef)
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(unusable & gBitTable[i])
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(unusable & (1u << i))
&& bestDmg < AI_DATA->simulatedDmg[battlerAtk][battlerDef][i].expected)
{
bestDmg = AI_DATA->simulatedDmg[battlerAtk][battlerDef][i].expected;
@@ -1150,7 +1164,7 @@ u32 GetBestDmgFromBattler(u32 battler, u32 battlerTarget)
{
if (moves[i] != MOVE_NONE
&& moves[i] != MOVE_UNAVAILABLE
&& !(unusable & gBitTable[i])
&& !(unusable & (1u << i))
&& bestDmg < AI_DATA->simulatedDmg[battler][battlerTarget][i].expected)
{
bestDmg = AI_DATA->simulatedDmg[battler][battlerTarget][i].expected;
@@ -1170,7 +1184,7 @@ bool32 CanAIFaintTarget(u32 battlerAtk, u32 battlerDef, u32 numHits)
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(moveLimitations & gBitTable[i]))
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(moveLimitations & (1u << i)))
{
// Use the pre-calculated value in simulatedDmg instead of re-calculating it
dmg = AI_DATA->simulatedDmg[battlerAtk][battlerDef][i].expected;
@@ -1215,7 +1229,7 @@ bool32 CanTargetFaintAiWithMod(u32 battlerDef, u32 battlerAtk, s32 hpMod, s32 dm
if (dmgMod)
dmg *= dmgMod;
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(unusable & gBitTable[i]) && dmg >= hpCheck)
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(unusable & (1u << i)) && dmg >= hpCheck)
{
return TRUE;
}
@@ -2077,7 +2091,7 @@ bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool
if (moves[i] == MOVE_NONE || moves[i] == MOVE_UNAVAILABLE)
continue;
if (!(gBitTable[i] & moveLimitations))
if (!((1u << i) & moveLimitations))
{
if (ignoreStatus && IS_MOVE_STATUS(moves[i]))
continue;
@@ -2103,7 +2117,7 @@ bool32 HasSleepMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef)
{
if (moves[i] == MOVE_NONE)
break;
if (!(gBitTable[i] & moveLimitations))
if (!((1u << i) & moveLimitations))
{
if (gMovesInfo[moves[i]].effect == EFFECT_SLEEP
&& AI_DATA->moveAccuracy[battlerAtk][battlerDef][i] < 85)
@@ -2499,7 +2513,7 @@ u32 GetBattlerSecondaryDamage(u32 battlerId)
bool32 BattlerWillFaintFromWeather(u32 battler, u32 ability)
{
if ((BattlerAffectedBySandstorm(battler, ability) || BattlerAffectedByHail(battler, ability))
&& gBattleMons[battler].hp <= gBattleMons[battler].maxHP / 16)
&& gBattleMons[battler].hp <= max(1, gBattleMons[battler].maxHP / 16))
return TRUE;
return FALSE;
@@ -2508,7 +2522,7 @@ bool32 BattlerWillFaintFromWeather(u32 battler, u32 ability)
bool32 BattlerWillFaintFromSecondaryDamage(u32 battler, u32 ability)
{
if (GetBattlerSecondaryDamage(battler) != 0
&& gBattleMons[battler].hp <= gBattleMons[battler].maxHP / 16)
&& gBattleMons[battler].hp <= max(1, gBattleMons[battler].maxHP / 16))
return TRUE;
return FALSE;
}
@@ -2778,6 +2792,7 @@ bool32 CanKnockOffItem(u32 battler, u32 item)
| BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_LINK
| BATTLE_TYPE_RECORDED_LINK
| BATTLE_TYPE_SECRET_BASE
| (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE ? BATTLE_TYPE_TRAINER : 0)
)) && GetBattlerSide(battler) == B_SIDE_PLAYER)
return FALSE;
@@ -3024,7 +3039,7 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof)
else
party = gEnemyParty;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
if (IsDoubleBattle())
{
battlerOnField1 = gBattlerPartyIndexes[battlerId];
battlerOnField2 = gBattlerPartyIndexes[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battlerId)))];
@@ -3247,7 +3262,8 @@ bool32 IsMoveEffectWeather(u32 move)
|| gMovesInfo[move].effect == EFFECT_RAIN_DANCE
|| gMovesInfo[move].effect == EFFECT_SANDSTORM
|| gMovesInfo[move].effect == EFFECT_HAIL
|| gMovesInfo[move].effect == EFFECT_SNOWSCAPE))
|| gMovesInfo[move].effect == EFFECT_SNOWSCAPE
|| gMovesInfo[move].effect == EFFECT_CHILLY_RECEPTION))
return TRUE;
return FALSE;
}
@@ -3415,7 +3431,7 @@ s32 CountUsablePartyMons(u32 battlerId)
else
party = gEnemyParty;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
if (IsDoubleBattle())
{
battlerOnField1 = gBattlerPartyIndexes[battlerId];
battlerOnField2 = gBattlerPartyIndexes[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battlerId)))];
@@ -3826,7 +3842,7 @@ bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u32 move)
bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove)
{
// simple logic. just upgrades chosen move to z move if possible, unless regular move would kill opponent
if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && battlerDef == BATTLE_PARTNER(battlerAtk))
if ((IsDoubleBattle()) && battlerDef == BATTLE_PARTNER(battlerAtk))
return FALSE; // don't use z move on partner
if (HasTrainerUsedGimmick(battlerAtk, GIMMICK_Z_MOVE))
return FALSE; // can't use z move twice

View File

@@ -2593,8 +2593,6 @@ static void BattleStartClearSetData(void)
gBattleStruct->itemLost[B_SIDE_PLAYER][i].originalItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
gBattleStruct->itemLost[B_SIDE_OPPONENT][i].originalItem = GetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM);
gPartyCriticalHits[i] = 0;
gBattleStruct->allowedToChangeFormInWeather[i][B_SIDE_PLAYER] = FALSE;
gBattleStruct->allowedToChangeFormInWeather[i][B_SIDE_OPPONENT] = FALSE;
}
gBattleStruct->swapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky

View File

@@ -973,6 +973,7 @@ const u8 gText_Unused_6F[] = _("6F");
const u8 gText_Unused_7F[] = _("7F");
const u8 gText_Unused_8F[] = _("8F");
static const u8 sText_PkmnTerastallizedInto[] = _("{B_ATK_NAME_WITH_PREFIX} terastallized\ninto the {B_BUFF1} type!");
static const u8 sText_FickleBeamDoubled[] = _("{B_ATK_NAME_WITH_PREFIX} is going all\nout for this attack!");
const u8 *const gStatNamesTable[] = {
@@ -994,7 +995,9 @@ const u8 *const gPokeblockWasTooXStringTable[] = {
sText_PokeblockWasTooSour
};
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT - BATTLESTRINGS_TABLE_START] = {
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT - BATTLESTRINGS_TABLE_START] =
{
[STRINGID_FICKLEBEAMDOUBLED - BATTLESTRINGS_TABLE_START] = sText_FickleBeamDoubled,
[STRINGID_PKMNTERASTALLIZEDINTO - BATTLESTRINGS_TABLE_START] = sText_PkmnTerastallizedInto,
[STRINGID_TIDYINGUPCOMPLETE - BATTLESTRINGS_TABLE_START] = sText_TidyingUpComplete,
[STRINGID_SUPERSWEETAROMAWAFTS - BATTLESTRINGS_TABLE_START] = sText_SupersweetAromaWafts,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1831,7 +1831,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_FICKLE_BEAM] =
{
.battleScript = BattleScript_EffectHit,
.battleScript = BattleScript_EffectFickleBeam,
},
[EFFECT_BLIZZARD] =

View File

@@ -930,7 +930,7 @@ static void Task_EvolutionScene(u8 taskId)
BattlePutTextOnWindow(gText_BattleYesNoChoice, B_WIN_YESNO);
gTasks[taskId].tLearnMoveState++;
sEvoCursorPos = 0;
BattleCreateYesNoCursorAt();
BattleCreateYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]);
}
break;
case MVSTATE_HANDLE_YES_NO:
@@ -941,17 +941,17 @@ static void Task_EvolutionScene(u8 taskId)
{
// Moved onto YES
PlaySE(SE_SELECT);
BattleDestroyYesNoCursorAt();
BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]);
sEvoCursorPos = 0;
BattleCreateYesNoCursorAt();
BattleCreateYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]);
}
if (JOY_NEW(DPAD_DOWN) && sEvoCursorPos == 0)
{
// Moved onto NO
PlaySE(SE_SELECT);
BattleDestroyYesNoCursorAt();
BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]);
sEvoCursorPos = 1;
BattleCreateYesNoCursorAt();
BattleCreateYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]);
}
if (JOY_NEW(A_BUTTON))
{

View File

@@ -248,12 +248,8 @@ void SetMainCallback2(MainCallback callback)
void StartTimer1(void)
{
if (HQ_RANDOM)
{
REG_TM2CNT_L = 0;
REG_TM2CNT_H = TIMER_ENABLE | TIMER_COUNTUP;
}
REG_TM2CNT_L = 0;
REG_TM2CNT_H = TIMER_ENABLE | TIMER_COUNTUP;
REG_TM1CNT_H = TIMER_ENABLE;
}
@@ -261,22 +257,12 @@ void SeedRngAndSetTrainerId(void)
{
u32 val;
if (HQ_RANDOM)
{
REG_TM1CNT_H = 0;
REG_TM2CNT_H = 0;
val = ((u32)REG_TM2CNT_L) << 16;
val |= REG_TM1CNT_L;
SeedRng(val);
gTrainerId = Random();
}
else
{
u16 val = REG_TM1CNT_L;
SeedRng(val);
REG_TM1CNT_H = 0;
gTrainerId = val;
}
REG_TM1CNT_H = 0;
REG_TM2CNT_H = 0;
val = ((u32)REG_TM2CNT_L) << 16;
val |= REG_TM1CNT_L;
SeedRng(val);
gTrainerId = Random();
}
u16 GetGeneratedTrainerIdLower(void)

View File

@@ -8,7 +8,6 @@
rng_value_t gRngValue;
rng_value_t gRng2Value;
#if HQ_RANDOM == TRUE
EWRAM_DATA static volatile bool8 sRngLoopUnlocked;
@@ -112,39 +111,6 @@ void AdvanceRandom(void)
#define LOOP_RANDOM ((u16)(_SFC32_Next(state) >> 16))
#else
EWRAM_DATA static u32 sRandCount = 0;
u16 Random(void)
{
gRngValue = ISO_RANDOMIZE1(gRngValue);
sRandCount++;
return gRngValue >> 16;
}
void SeedRng(u16 seed)
{
gRngValue = seed;
}
void SeedRng2(u16 seed)
{
gRng2Value = seed;
}
u16 Random2(void)
{
gRng2Value = ISO_RANDOMIZE1(gRng2Value);
return gRng2Value >> 16;
}
#define LOOP_RANDOM_START
#define LOOP_RANDOM_END
#define LOOP_RANDOM (Random())
#endif
#define SHUFFLE_IMPL \
u32 tmp; \
LOOP_RANDOM_START; \