Merge branch '_RHH/upcoming' into _RHH/pr/upcoming/merrpFollowers

# Conflicts:
#	src/data/graphics/pokemon.h
This commit is contained in:
Eduardo Quezada 2024-02-19 13:49:10 -03:00
commit ead108d28e
72 changed files with 1418 additions and 480 deletions

View File

@ -23,9 +23,10 @@ body:
label: Version
description: What version of pokeemerald-expansion are you using as a base?
options:
- 1.7.3 (Latest release)
- 1.7.4 (Latest release)
- master (default when pulling, unreleased bugfixes)
- upcoming (Edge)
- 1.7.3
- 1.7.2
- 1.7.1
- 1.7.0

View File

@ -23,9 +23,11 @@ body:
label: Version
description: What version of pokeemerald-expansion are you using as a base?
options:
- 1.7.2 (Latest release)
- 1.7.4 (Latest release)
- master (default when pulling, unreleased bugfixes)
- upcoming (Edge)
- 1.7.3
- 1.7.2
- 1.7.1
- 1.7.0
- 1.6.2

View File

@ -23,9 +23,10 @@ body:
label: Version
description: What version of pokeemerald-expansion are you using as a base?
options:
- 1.7.3 (Latest release)
- 1.7.4 (Latest release)
- master (default when pulling, unreleased bugfixes)
- upcoming (Edge)
- 1.7.3
- 1.7.2
- 1.7.1
- 1.7.0

View File

@ -1,6 +1,7 @@
# Pokeemerald-Expansion Changelogs
## Version 1.7.x
### [Version 1.7.4](docs/changelogs/1.7.4.md) - Bugfix Release
### [Version 1.7.3](docs/changelogs/1.7.3.md) - Bugfix Release
### [Version 1.7.2](docs/changelogs/1.7.2.md) - Bugfix Release
### [Version 1.7.1](docs/changelogs/1.7.1.md) - Bugfix Release

View File

@ -165,7 +165,7 @@ With this, you'll get the latest version of pokeemerald-expansion, plus a couple
## **How do I update my version of pokeemerald-expansion?**
- If you haven't set up a remote, run the command `git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion`.
- Once you have your remote set up, run the command `git pull RHH expansion/1.7.3`.
- Once you have your remote set up, run the command `git pull RHH expansion/1.7.4`.
### Please consider crediting the entire [list of contributors](https://github.com/rh-hideout/pokeemerald-expansion/wiki/Credits) in your project, as they have all worked hard to develop this project :)

View File

@ -1360,11 +1360,11 @@
.byte \battler
.4byte \jumpInstr
.endm
.macro allyswitchswapbattlers
callnative BS_AllySwitchSwapBattler
.endm
.macro allyswitchfailchance jumpInstr:req
callnative BS_AllySwitchFailChance
.4byte \jumpInstr
@ -1616,11 +1616,17 @@
callnative BS_TryUpperHand
.4byte \failInstr
.endm
.macro tryupdaterecoiltracker
callnative BS_TryUpdateRecoilTracker
.endm
.macro trytidyup clear:req, jumpInstr:req
callnative BS_TryTidyUp
.byte \clear
.4byte \jumpInstr
.endm
@ various command changed to more readable macros
.macro cancelmultiturnmoves battler:req
various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES

View File

@ -2139,3 +2139,34 @@
callnative ToggleGigantamaxFactor
.2byte \slot
.endm
@ Sets VAR_RESULT to one of the arguments (via setorcopyvar).
.macro randomelement element:req, elements:vararg
.set _randomelement_n, 0
.irp el, \element, \elements
.set _randomelement_n, _randomelement_n + 1
.endr
random _randomelement_n
.set _randomelement_n, 0
.irp el, \element, \elements
goto_if_ne VAR_RESULT, _randomelement_n, 1f
setorcopyvar VAR_RESULT, \el
goto 2f
1:
.set _randomelement_n, _randomelement_n + 1
.endr
2:
.endm
@ Sets VAR_RESULT to TRUE with probability 'percent', and FALSE
@ with probability '100% - percent'.
.macro randompercentage percent:req
random 100
goto_if_lt VAR_RESULT, \percent, 1f
setvar VAR_RESULT, FALSE
goto 2f
1:
setvar VAR_RESULT, TRUE
2:
.endm

View File

@ -1028,6 +1028,10 @@ gBattleAnims_General::
.4byte General_Rainbow @ B_ANIM_RAINBOW
.4byte General_SeaOfFire @ B_ANIM_SEA_OF_FIRE
.4byte General_Swamp @ B_ANIM_SWAMP
.4byte General_TrickRoom @ B_ANIM_TRICK_ROOM
.4byte General_WonderRoom @ B_ANIM_WONDER_ROOM
.4byte General_MagicRoom @ B_ANIM_MAGIC_ROOM
.4byte General_Tailwind @ B_ANIM_TAILLWIND
.align 2
gBattleAnims_Special::
@ -1316,6 +1320,35 @@ Move_TAILWIND:
delay 1
end
General_Tailwind:
loadspritegfx ANIM_TAG_FLYING_DIRT
playsewithpan SE_M_GUST, SOUND_PAN_ATTACKER
call SetHighSpeedBg
setalpha 12, 8
createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 10, 2304, 96, 0
delay 12
playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER
createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 90, 2048, 96, 0
delay 12
playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER
createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 50, 2560, 96, 0
delay 12
playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER
createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 20, 2304, 96, 0
delay 12
playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER
createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 70, 1984, 96, 0
delay 12
createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 0, 2816, 96, 0
delay 10
createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 60, 2560, 96, 0
waitforvisualfinish
stopsound
call UnsetHighSpeedBg
blendoff
delay 1
end
Move_ACUPRESSURE:
loadspritegfx ANIM_TAG_ACUPRESSURE
loadspritegfx ANIM_TAG_SPARK_2
@ -3303,6 +3336,8 @@ Move_DEFOG:
Move_TRICK_ROOM::
call InitRoomAnimation
General_TrickRoom:
playsewithpan SE_M_SUPERSONIC, SOUND_PAN_TARGET
fadetobg BG_TRICK_ROOM
waitbgfadein
delay 0x40
@ -3312,7 +3347,6 @@ Move_TRICK_ROOM::
end
InitRoomAnimation:
setalpha 8, 8
playsewithpan SE_M_SUPERSONIC, SOUND_PAN_TARGET
createvisualtask AnimTask_ScaleMonAndRestore, 5, -6, -6, 15, ANIM_TARGET, 1
return
@ -4932,6 +4966,8 @@ PowerSplitLaunch:
Move_WONDER_ROOM::
call InitRoomAnimation
General_WonderRoom:
playsewithpan SE_M_SUPERSONIC, SOUND_PAN_TARGET
fadetobg BG_WONDER_ROOM
waitbgfadein
delay 0x40
@ -5112,6 +5148,8 @@ Move_TELEKINESIS::
Move_MAGIC_ROOM::
call InitRoomAnimation
General_MagicRoom:
playsewithpan SE_M_SUPERSONIC, SOUND_PAN_TARGET
fadetobg BG_MAGIC_ROOM
waitbgfadein
delay 0x40

View File

@ -20,6 +20,23 @@
.section script_data, "aw", %progbits
BattleScript_EffectTidyUp::
attackcanceler
attackstring
pause B_WAIT_TIME_MED
ppreduce
waitstate
trytidyup FALSE, BattleScript_EffectTidyUpDoMoveAnimation
goto BattleScript_EffectDragonDanceFromStatUp
BattleScript_EffectTidyUpDoMoveAnimation::
attackanimation
waitanimation
trytidyup TRUE, NULL
printstring STRINGID_TIDYINGUPCOMPLETE
waitmessage B_WAIT_TIME_LONG
goto BattleScript_EffectDragonDanceFromStatUp
BattleScript_EffectUpperHand::
attackcanceler
tryupperhand BattleScript_FailedFromAtkString
@ -2534,6 +2551,10 @@ BattleScript_EffectTrickRoom::
waitanimation
printfromtable gRoomsStringIds
waitmessage B_WAIT_TIME_LONG
call BattleScript_TryRoomServiceLoop
goto BattleScript_MoveEnd
BattleScript_TryRoomServiceLoop:
savetarget
setbyte gBattlerTarget, 0
BattleScript_RoomServiceLoop:
@ -2544,7 +2565,7 @@ BattleScript_RoomServiceLoop_NextBattler:
addbyte gBattlerTarget, 0x1
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_RoomServiceLoop
restoretarget
goto BattleScript_MoveEnd
return
BattleScript_EffectWonderRoom::
BattleScript_EffectMagicRoom::
@ -5265,62 +5286,6 @@ BattleScript_EffectRecoilHP25::
incrementgamestat GAME_STAT_USED_STRUGGLE
goto BattleScript_EffectHit
BattleScript_EffectTeeterDance::
attackcanceler
attackstring
ppreduce
setbyte gBattlerTarget, 0
BattleScript_TeeterDanceLoop::
movevaluescleanup
jumpifbyteequal gBattlerAttacker, gBattlerTarget, BattleScript_TeeterDanceLoopIncrement
jumpifability BS_TARGET, ABILITY_OWN_TEMPO, BattleScript_TeeterDanceOwnTempoPrevents
jumpifsubstituteblocks BattleScript_TeeterDanceSubstitutePrevents
jumpifstatus2 BS_TARGET, STATUS2_CONFUSION, BattleScript_TeeterDanceAlreadyConfused
jumpifhasnohp BS_TARGET, BattleScript_TeeterDanceLoopIncrement
accuracycheck BattleScript_TeeterDanceMissed, ACC_CURR_MOVE
jumpifsafeguard BattleScript_TeeterDanceSafeguardProtected
attackanimation
waitanimation
seteffectprimary MOVE_EFFECT_CONFUSION
resultmessage
waitmessage B_WAIT_TIME_LONG
BattleScript_TeeterDanceDoMoveEndIncrement::
moveendto MOVEEND_NEXT_TARGET
BattleScript_TeeterDanceLoopIncrement::
addbyte gBattlerTarget, 1
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_TeeterDanceLoop
end
BattleScript_TeeterDanceOwnTempoPrevents::
pause B_WAIT_TIME_SHORT
printstring STRINGID_PKMNPREVENTSCONFUSIONWITH
waitmessage B_WAIT_TIME_LONG
goto BattleScript_TeeterDanceDoMoveEndIncrement
BattleScript_TeeterDanceSafeguardProtected::
pause B_WAIT_TIME_SHORT
printstring STRINGID_PKMNUSEDSAFEGUARD
waitmessage B_WAIT_TIME_LONG
goto BattleScript_TeeterDanceDoMoveEndIncrement
BattleScript_TeeterDanceSubstitutePrevents::
pause B_WAIT_TIME_SHORT
printstring STRINGID_BUTITFAILED
waitmessage B_WAIT_TIME_LONG
goto BattleScript_TeeterDanceDoMoveEndIncrement
BattleScript_TeeterDanceAlreadyConfused::
setalreadystatusedmoveattempt BS_ATTACKER
pause B_WAIT_TIME_SHORT
printstring STRINGID_PKMNALREADYCONFUSED
waitmessage B_WAIT_TIME_LONG
goto BattleScript_TeeterDanceDoMoveEndIncrement
BattleScript_TeeterDanceMissed::
resultmessage
waitmessage B_WAIT_TIME_LONG
goto BattleScript_TeeterDanceDoMoveEndIncrement
BattleScript_EffectMudSport::
BattleScript_EffectWaterSport::
attackcanceler
@ -5456,6 +5421,7 @@ BattleScript_EffectDragonDance::
attackcanceler
attackstring
ppreduce
BattleScript_EffectDragonDanceFromStatUp::
jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_DragonDanceDoMoveAnim
jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats
BattleScript_DragonDanceDoMoveAnim::
@ -5983,6 +5949,19 @@ BattleScript_SunlightFaded::
call BattleScript_ActivateWeatherAbilities
end2
BattleScript_OverworldStatusStarts::
printfromtable gStartingStatusStringIds
waitmessage B_WAIT_TIME_LONG
playanimation_var BS_ATTACKER, sB_ANIM_ARG1
call BattleScript_OverworldStatusStarts_TryActivations
end3
BattleScript_OverworldStatusStarts_TryActivations:
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_SET_TRICK_ROOM, BattleScript_TryRoomServiceLoop
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_SET_TAILWIND_PLAYER, BattleScript_TryTailwindAbilitiesLoop
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_SET_TAILWIND_OPPONENT, BattleScript_TryTailwindAbilitiesLoop
return
BattleScript_OverworldWeatherStarts::
printfromtable gWeatherStartsStringIds
waitmessage B_WAIT_TIME_LONG

View File

@ -116,7 +116,7 @@ SootopolisCity_LotadAndSeedotHouse_Text_PleaseShowMeBigSeedot:
.string "P-p-please, show me!$"
SootopolisCity_LotadAndSeedotHouse_Text_GoshMightBeBiggerThanLotad:
.string "{STR_VAR_2} inches!\n"
.string "{STR_VAR_2}!\n"
.string "Oh, my gosh, this is a big one!\p"
.string "It might even beat the big LOTAD\n"
.string "my younger brother saw!\p"
@ -132,7 +132,7 @@ SootopolisCity_LotadAndSeedotHouse_Text_BagCrammedFull1:
.string "Your BAG is crammed full.$"
SootopolisCity_LotadAndSeedotHouse_Text_SeenBiggerSeedot:
.string "{STR_VAR_2} inches, is it?\p"
.string "{STR_VAR_2}, is it?\p"
.string "Hmm… I've seen a bigger SEEDOT\n"
.string "than this one.$"
@ -148,7 +148,7 @@ SootopolisCity_LotadAndSeedotHouse_Text_DontHaveBigSeedot:
SootopolisCity_LotadAndSeedotHouse_Text_BiggestSeedotInHistory:
.string "The biggest SEEDOT in history!\n"
.string "{STR_VAR_2}'s {STR_VAR_3}-inch giant!\p"
.string "{STR_VAR_2}'s {STR_VAR_3} giant!\p"
.string "A SEEDOT bigger than a LOTAD\n"
.string "always wanted!$"
@ -164,7 +164,7 @@ SootopolisCity_LotadAndSeedotHouse_Text_PleaseShowMeBigLotad:
.string "P-p-please show me!$"
SootopolisCity_LotadAndSeedotHouse_Text_WowMightBeBiggerThanSeedot:
.string "{STR_VAR_2} inches!\n"
.string "{STR_VAR_2}!\n"
.string "Wow, that is big!\p"
.string "It might be even bigger than the huge\n"
.string "SEEDOT my big brother saw.\p"
@ -180,7 +180,7 @@ SootopolisCity_LotadAndSeedotHouse_Text_BagCrammedFull2:
.string "Your BAG is crammed full.$"
SootopolisCity_LotadAndSeedotHouse_Text_SeenBiggerLotad:
.string "{STR_VAR_2} inches?\p"
.string "{STR_VAR_2}?\p"
.string "Hmm… I've seen a bigger LOTAD\n"
.string "than this one here.$"
@ -196,7 +196,7 @@ SootopolisCity_LotadAndSeedotHouse_Text_DontHaveBigLotad:
SootopolisCity_LotadAndSeedotHouse_Text_BiggestLotadInHistory:
.string "The biggest LOTAD in history!\n"
.string "{STR_VAR_2}'s {STR_VAR_3}-inch colossus!\p"
.string "{STR_VAR_2}'s {STR_VAR_3} colossus!\p"
.string "A LOTAD bigger than a SEEDOT\n"
.string "always wanted!$"

68
docs/changelogs/1.7.4.md Normal file
View File

@ -0,0 +1,68 @@
# Version 1.7.4
```md
## How to update
- If you haven't set up a remote, run the command `git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion`.
- Once you have your remote set up, run the command `git pull RHH expansion/1.Y.Z`.
```
## 🧬 General 🧬
### Fixed
* HGSS Dex fixes:
* Fixed inconsistent list tileset between capped and decapped modes by @ravepossum in https://github.com/rh-hideout/pokeemerald-expansion/pull/4126
* Fixed screen select bar popping in too early for area screen by @ravepossum in https://github.com/rh-hideout/pokeemerald-expansion/pull/4094
* Fixed Lotad/Seedot house using species weight instead of height by @Bassoonian in https://github.com/rh-hideout/pokeemerald-expansion/pull/4195
## 🐉 Pokémon 🐉
### Fixed
* Fixed Ogerpon shiny palettes by @AsparagusEduardo in https://github.com/rh-hideout/pokeemerald-expansion/pull/4165
* Fixed Basculegion back sprite offset by @MelonSpeedruns in https://github.com/rh-hideout/pokeemerald-expansion/pull/4198
* Fixed Greninja form animations by @MelonSpeedruns in https://github.com/rh-hideout/pokeemerald-expansion/pull/4198
* Fixed compile error when `P_GEN_8_CROSS_EVOS` is enabled but not `P_GEN_9_CROSS_EVOS` due to Ursaluna's cry being labled as Gen 9 by @AsparagusEduardo in https://github.com/rh-hideout/pokeemerald-expansion/pull/4210
* Fixed Curly Tatsugiri and Green Plumage Squawkabilly icons not showing up properly in later versions of Porymap by @kittenchilly in https://github.com/rh-hideout/pokeemerald-expansion/pull/4212
## ⚔️ Battle General ⚔️ ##
### Fixed
* Fixed disobedience not resetting multihit moves by @DizzyEggg in https://github.com/rh-hideout/pokeemerald-expansion/pull/4133
* Fixed switch in interactions with hold effects abilities by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/4091
* Download activating on an empty field.
* Intimidate activating on an empty field and not activating upon new opponent switching in.
* Primal Reversion not happening immediately upon switching in from U-turn.
* Held items not being triggered when switching in fron U-turn and Intimidate being triggered beforehand.
* Fixed LastUsedBall issues not being saved and DisplayBall not being shown by @Wesmaster in https://github.com/rh-hideout/pokeemerald-expansion/pull/4209
## 🤹 Moves 🤹
### Fixed
* Fixed move animations crashing on some emulators because of division by zero by @DizzyEggg in https://github.com/rh-hideout/pokeemerald-expansion/pull/4121
* Flip Turn, Anchor Shot, Snipe Shot and Incinerate were affected by this.
* Fixed Eerie Spell consuming double PP and showing its message twice by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/4127
* Fixed Fairy Lock animation by @DizzyEggg in https://github.com/rh-hideout/pokeemerald-expansion/pull/4111
## 🎭 Abilities 🎭
### Added
* Added Gen 5+ config for Soundproof no longer preventing Uproar status by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/4174
### Fixed
* Fixed Mycelium Might speed calculation by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/4146
* Fixed Stench triggering on non-damaging attacks by @HungryPickle in https://github.com/rh-hideout/pokeemerald-expansion/pull/4159
* Fixed Disguise not ending the battle in the correct form by @AsparagusEduardo in https://github.com/rh-hideout/pokeemerald-expansion/pull/4167
* Fixed Opportunist accumulating stat changes by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/4168
## 🧶 Items 🧶
### Fixed
* Kee Berry fixes by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/4149
* Fixed triggering if the holder does a physical attack instead of receiving it.
* Fixed it boosting the target's defense if the attacker holds a Kee Berry, while still displaying the boost animation for the holder.
* Fixed poison-healing items not reseting Toxic Counter by @DizzyEggg in https://github.com/rh-hideout/pokeemerald-expansion/pull/4135
## 🧹 Other Cleanup 🧹
### Changed
* Clean up space/tabs difference by @Bassoonian in https://github.com/rh-hideout/pokeemerald-expansion/pull/4163
* Deleted a space by @cmy2008 in https://github.com/rh-hideout/pokeemerald-expansion/pull/4194
## New Contributors
* @cmy2008 made their first contribution in https://github.com/rh-hideout/pokeemerald-expansion/pull/4194
* @MelonSpeedruns made their first contribution in https://github.com/rh-hideout/pokeemerald-expansion/pull/4198
**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.7.3...expansion/1.7.4
<!--Last PR: 4212-->

View File

Before

Width:  |  Height:  |  Size: 384 B

After

Width:  |  Height:  |  Size: 384 B

View File

Before

Width:  |  Height:  |  Size: 449 B

After

Width:  |  Height:  |  Size: 449 B

View File

Before

Width:  |  Height:  |  Size: 459 B

After

Width:  |  Height:  |  Size: 459 B

View File

Before

Width:  |  Height:  |  Size: 334 B

After

Width:  |  Height:  |  Size: 334 B

View File

@ -682,9 +682,12 @@ struct BattleStruct
} multiBuffer;
u8 wishPerishSongState;
u8 wishPerishSongBattlerId;
bool8 overworldWeatherDone;
bool8 terrainDone;
u8 isAtkCancelerForCalledMove; // Certain cases in atk canceler should only be checked once, when the original move is called, however others need to be checked the twice.
u8 overworldWeatherDone:1;
u8 startingStatusDone:1;
u8 isAtkCancelerForCalledMove:1; // Certain cases in atk canceler should only be checked once, when the original move is called, however others need to be checked the twice.
u8 terrainDone:1;
u8 startingStatus; // status to apply at battle start. defined in constants/battle.h
u8 startingStatusTimer;
u8 atkCancellerTracker;
struct BattleTvMovePoints tvMovePoints;
struct BattleTv tv;

View File

@ -29,7 +29,8 @@
#define STAT_CHANGE_ACC 10
#define STAT_CHANGE_EVASION 11
#define BEST_DAMAGE_MOVE 1 // Move with the most amount of hits with the best accuracy/effect
#define BEST_DAMAGE_MOVE 1 // Move with the most amount of hits with the best accuracy/effect
#define POWERFUL_STATUS_MOVE 10 // Moves with this score will be chosen over a move that faints target
// Temporary scores that are added together to determine a final score at the at of AI_CalcMoveScore
#define WEAK_EFFECT 1

View File

@ -99,7 +99,8 @@ bool32 HasMoveWithCategory(u32 battler, u32 category);
bool32 HasMoveWithType(u32 battler, u32 type);
bool32 HasMoveEffect(u32 battlerId, u32 moveEffect);
bool32 HasMoveEffectANDArg(u32 battlerId, u32 effect, u32 argument);
bool32 HasMoveWithMoveEffect(u32 battlerId, u32 moveEffect);
bool32 HasMoveWithAdditionalEffect(u32 battlerId, u32 moveEffect);
bool32 HasMoveWithCriticalHitChance(u32 battlerId);
bool32 HasMoveWithMoveEffectExcept(u32 battlerId, u32 moveEffect, u32 exception);
bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect);
bool32 IsAromaVeilProtectedMove(u32 move);
@ -135,7 +136,7 @@ bool32 HasSnatchAffectedMove(u32 battler);
// status checks
bool32 AI_CanBeBurned(u32 battler, u32 ability);
bool32 AI_CanGetFrostbite(u32 battler, u32 ability);
bool32 AI_CanBeConfused(u32 battler, u32 ability);
bool32 AI_CanBeConfused(u32 battlerAtk, u32 battlerDef, u32 move, u32 ability);
bool32 AI_CanSleep(u32 battler, u32 ability);
bool32 IsBattlerIncapacitated(u32 battler, u32 ability);
bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove);
@ -189,6 +190,7 @@ s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct Battl
s32 AI_CheckMoveEffects(u32 battlerAtk, u32 battlerDef, u32 move, s32 score, struct AiLogicData *aiData, u32 predictedMove, bool32 isDoubleBattle);
s32 AI_TryToClearStats(u32 battlerAtk, u32 battlerDef, bool32 isDoubleBattle);
bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef);
s32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData);
bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData);
void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score);
#endif //GUARD_BATTLE_AI_UTIL_H

View File

@ -54,6 +54,7 @@ extern const u8 BattleScript_DamagingWeatherContinues[];
extern const u8 BattleScript_SandStormHailSnowEnds[];
extern const u8 BattleScript_SunlightContinues[];
extern const u8 BattleScript_SunlightFaded[];
extern const u8 BattleScript_OverworldStatusStarts[];
extern const u8 BattleScript_OverworldWeatherStarts[];
extern const u8 BattleScript_OverworldTerrain[];
extern const u8 BattleScript_SideStatusWoreOff[];
@ -680,7 +681,6 @@ extern const u8 BattleScript_EffectImprison[];
extern const u8 BattleScript_EffectRefresh[];
extern const u8 BattleScript_EffectGrudge[];
extern const u8 BattleScript_EffectSnatch[];
extern const u8 BattleScript_EffectTeeterDance[];
extern const u8 BattleScript_EffectHitEscape[];
extern const u8 BattleScript_EffectMudSport[];
extern const u8 BattleScript_EffectTickle[];
@ -823,5 +823,6 @@ extern const u8 BattleScript_EffectDoodle[];
extern const u8 BattleScript_EffectFilletAway[];
extern const u8 BattleScript_EffectShedTail[];
extern const u8 BattleScript_EffectUpperHand[];
extern const u8 BattleScript_EffectTidyUp[];
#endif // GUARD_BATTLE_SCRIPTS_H

View File

@ -39,6 +39,7 @@
#define ABILITYEFFECT_SWITCH_IN_TERRAIN 16
#define ABILITYEFFECT_SWITCH_IN_WEATHER 17
#define ABILITYEFFECT_OPPORTUNIST 18
#define ABILITYEFFECT_SWITCH_IN_STATUSES 19
// Special cases
#define ABILITYEFFECT_MUD_SPORT 252 // Only used if B_SPORT_TURNS >= GEN_6
#define ABILITYEFFECT_WATER_SPORT 253 // Only used if B_SPORT_TURNS >= GEN_6

View File

@ -34,16 +34,6 @@
#define LOG_HANDLER (LOG_HANDLER_MGBA_PRINT)
#endif
#define ENGLISH
#ifdef ENGLISH
#define UNITS_IMPERIAL
#define CHAR_DEC_SEPARATOR CHAR_PERIOD // Period is used as a decimal separator only in the UK and the US.
#else
#define UNITS_METRIC
#define CHAR_DEC_SEPARATOR CHAR_COMMA
#endif
// Uncomment to fix some identified minor bugs
#define BUGFIX
@ -81,4 +71,11 @@
#define SUMMARY_SCREEN_NATURE_COLORS TRUE // If TRUE, nature-based stat boosts and reductions will be red and blue in the summary screen.
#define HQ_RANDOM TRUE // If TRUE, replaces the default RNG with an implementation of SFC32 RNG. May break code that relies on RNG.
// Measurement system constants to be used for UNITS
#define UNITS_IMPERIAL 0 // Inches, feet, pounds
#define UNITS_METRIC 1 // meters, kilograms
#define UNITS UNITS_IMPERIAL
#define CHAR_DEC_SEPARATOR CHAR_PERIOD // CHAR_PERIOD is used as a decimal separator only in the UK and the US. The rest of the world uses CHAR_COMMA.
#endif // GUARD_CONFIG_H

View File

@ -51,6 +51,7 @@
// Turn settings
#define B_BINDING_TURNS GEN_LATEST // In Gen5+, binding moves last for 4-5 turns instead of 2-5 turns. (With Grip Claw, 7 and 5 turns respectively.)
#define B_UPROAR_TURNS GEN_LATEST // In Gen5+, Uproar lasts for 3 turns instead of 2-5 turns.
#define B_UPROAR_IGNORE_SOUNDPROOF GEN_LATEST // In Gen5+, Uproar status ignores Soundproof.
#define B_DISABLE_TURNS GEN_LATEST // Disable's turns. See Cmd_disablelastusedattack.
#define B_TAILWIND_TURNS GEN_LATEST // In Gen5+, Tailwind lasts 4 turns instead of 3.
#define B_SLEEP_TURNS GEN_LATEST // In Gen5+, sleep lasts for 1-3 turns instead of 2-5 turns.
@ -180,8 +181,8 @@
// Var Settings
// To use the following features in scripting, replace the 0s with the var ID you're assigning it to.
// Eg: Replace with VAR_UNUSED_0x40F7 so you can use B_VAR_TERRAIN for that feature.
#define B_VAR_TERRAIN 0 // If this var has a value, assigning a STATUS_FIELD_xx_TERRAIN to it before battle causes the battle to start with that terrain active.
#define B_VAR_TERRAIN_TIMER 0 // If this var has a value greater or equal than 1 field terrains will last that number of turns, otherwise they will last until they're overwritten.
#define B_VAR_STARTING_STATUS 0 // If this var has a value, assigning a STATUS_FIELD_xx_TERRAIN to it before battle causes the battle to start with that terrain active.
#define B_VAR_STARTING_STATUS_TIMER 0 // If this var has a value greater or equal than 1 field terrains will last that number of turns, otherwise they will last until they're overwritten.
#define B_VAR_WILD_AI_FLAGS 0 // If not 0, you can use this var to add to default wild AI flags. NOT usable with flags above (1 << 15)
// Sky Battles
@ -229,6 +230,7 @@
#define B_WILD_NATURAL_ENEMIES TRUE // If set to TRUE, certain wild mon species will attack other species when partnered in double wild battles (eg. Zangoose vs Seviper)
#define B_AFFECTION_MECHANICS TRUE // In Gen6+, there's a stat called affection that can trigger different effects in battle. From LGPE onwards, those effects use friendship instead.
#define B_TRAINER_CLASS_POKE_BALLS GEN_LATEST // In Gen7+, trainers will use certain types of Poké Balls depending on their trainer class.
#define B_TRAINER_MON_RANDOM_ABILITY FALSE // If this is set to TRUE a random legal ability will be generated for a trainer mon
#define B_OBEDIENCE_MECHANICS GEN_LATEST // In PLA+ (here Gen8+), obedience restrictions also apply to non-outsider Pokémon, albeit based on their level met rather than actual level
#define B_USE_FROSTBITE FALSE // In PLA, Frostbite replaces Freeze. Enabling this flag does the same here. Moves can still be cherry-picked to either Freeze or Frostbite. Freeze-Dry, Secret Power & Tri Attack depend on this config.
#define B_OVERWORLD_SNOW GEN_LATEST // In Gen9+, overworld Snow will summon snow instead of hail.

View File

@ -354,7 +354,7 @@
#define MOVE_EFFECT_PREVENT_ESCAPE 33
#define MOVE_EFFECT_NIGHTMARE 34
#define MOVE_EFFECT_ALL_STATS_UP 35
#define MOVE_EFFECT_RAPIDSPIN 36
#define MOVE_EFFECT_RAPID_SPIN 36
#define MOVE_EFFECT_REMOVE_STATUS 37
#define MOVE_EFFECT_ATK_DEF_DOWN 38
#define MOVE_EFFECT_ATK_PLUS_2 39
@ -517,4 +517,17 @@
// Constants for Torment
#define PERMANENT_TORMENT 0xF
// Constants for B_VAR_STARTING_STATUS
// Timer value controlled by B_VAR_STARTING_STATUS_TIMER
#define STARTING_STATUS_NONE 0
#define STARTING_STATUS_ELECTRIC_TERRAIN 1
#define STARTING_STATUS_MISTY_TERRAIN 2
#define STARTING_STATUS_GRASSY_TERRAIN 3
#define STARTING_STATUS_PSYCHIC_TERRAIN 4
#define STARTING_STATUS_TRICK_ROOM 5
#define STARTING_STATUS_MAGIC_ROOM 6
#define STARTING_STATUS_WONDER_ROOM 7
#define STARTING_STATUS_TAILWIND_PLAYER 8
#define STARTING_STATUS_TAILWIND_OPPONENT 9
#endif // GUARD_CONSTANTS_BATTLE_H

View File

@ -34,20 +34,20 @@
#define AI_FLAG_PREFER_BATON_PASS (1 << 6)
#define AI_FLAG_DOUBLE_BATTLE (1 << 7) // removed, split between AI_FLAG_CHECK_BAD_MOVE & AI_FLAG_CHECK_GOOD_MOVE
#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
// New, Trainer Handicap Flags
#define AI_FLAG_NEGATE_UNAWARE (1 << 9) // AI is NOT aware of negating effects like wonder room, mold breaker, etc
#define AI_FLAG_WILL_SUICIDE (1 << 10) // 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_HELP_PARTNER (1 << 11) // AI can try to help partner. If not set, will tend not to target partner
#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_SCREENER (1 << 14) // AI prefers screening effects like reflect, mist, etc. TODO unfinished
#define AI_FLAG_HELP_PARTNER (1 << 12) // AI can try to help partner. If not set, will tend not to target partner
#define AI_FLAG_PREFER_STATUS_MOVES (1 << 13) // 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 << 14) // AI stalls battle and prefers secondary damage/trapping/etc. TODO not finished
#define AI_FLAG_SMART_SWITCHING (1 << 15) // AI includes a lot more switching checks
#define AI_FLAG_ACE_POKEMON (1 << 16) // 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 << 17) // AI has full knowledge of player moves, abilities, hold items
#define AI_FLAG_SMART_MON_CHOICES (1 << 18) // AI will make smarter decisions when choosing which mon to send out mid-battle and after a KO, which are separate decisions. Pairs very well with AI_FLAG_SMART_SWITCHING.
#define AI_FLAG_COUNT 18
#define AI_FLAG_COUNT 19
// 'other' ai logic flags
#define AI_FLAG_ROAMING (1 << 29)

View File

@ -563,6 +563,10 @@
#define B_ANIM_RAINBOW 42
#define B_ANIM_SEA_OF_FIRE 43
#define B_ANIM_SWAMP 44
#define B_ANIM_TRICK_ROOM 45
#define B_ANIM_WONDER_ROOM 46
#define B_ANIM_MAGIC_ROOM 47
#define B_ANIM_TAILWIND 48
// special animations table (gBattleAnims_Special)
#define B_ANIM_LVL_UP 0

View File

@ -164,7 +164,6 @@ enum {
EFFECT_GRUDGE,
EFFECT_SNATCH,
EFFECT_LOW_KICK,
EFFECT_TEETER_DANCE,
EFFECT_HIT_ESCAPE,
EFFECT_MUD_SPORT,
EFFECT_WEATHER_BALL,
@ -350,6 +349,7 @@ enum {
EFFECT_UPPER_HAND,
EFFECT_DRAGON_CHEER,
EFFECT_LAST_RESPECTS,
EFFECT_TIDY_UP,
NUM_BATTLE_MOVE_EFFECTS,
};

View File

@ -703,8 +703,12 @@
#define STRINGID_SHEDITSTAIL 701
#define STRINGID_CLOAKEDINAHARSHLIGHT 702
#define STRINGID_SUPERSWEETAROMAWAFTS 703
#define STRINGID_DIMENSIONSWERETWISTED 704
#define STRINGID_BIZARREARENACREATED 705
#define STRINGID_BIZARREAREACREATED 706
#define STRINGID_TIDYINGUPCOMPLETE 707
#define BATTLESTRINGS_COUNT 704
#define BATTLESTRINGS_COUNT 708
// This is the string id that gBattleStringsTable starts with.
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,
@ -967,6 +971,19 @@
#define B_MSG_TERRAIN_END_GRASSY 7
#define B_MSG_TERRAIN_COUNT 8
// gStartingStatusStringIds
#define B_MSG_TERRAIN_SET_MISTY 0
#define B_MSG_TERRAIN_SET_ELECTRIC 1
#define B_MSG_TERRAIN_SET_PSYCHIC 2
#define B_MSG_TERRAIN_SET_GRASSY 3
#define B_MSG_SET_TRICK_ROOM 4
#define B_MSG_SET_MAGIC_ROOM 5
#define B_MSG_SET_WONDER_ROOM 6
#define B_MSG_SET_TAILWIND_PLAYER 7
#define B_MSG_SET_TAILWIND_OPPONENT 8
#define B_MSG_STARTING_STATUS_COUNT 9
// gWrappedStringIds
#define B_MSG_WRAPPED_BIND 0
#define B_MSG_WRAPPED_WRAP 1

View File

@ -626,9 +626,9 @@ enum {
#if P_FAMILY_TEDDIURSA
CRY_TEDDIURSA,
CRY_URSARING,
#if P_GEN_9_CROSS_EVOS
#if P_GEN_8_CROSS_EVOS
CRY_URSALUNA,
#endif //P_GEN_9_CROSS_EVOS
#endif //P_GEN_8_CROSS_EVOS
#endif //P_FAMILY_TEDDIURSA
#if P_FAMILY_SLUGMA
CRY_SLUGMA,

View File

@ -3,7 +3,7 @@
#define EXPANSION_VERSION_MAJOR 1
#define EXPANSION_VERSION_MINOR 7
#define EXPANSION_VERSION_PATCH 3
#define EXPANSION_VERSION_PATCH 4
// FALSE if this this version of Expansion is not a tagged commit, i.e.
// it contains unreleased changes.

View File

@ -1307,4 +1307,24 @@ enum {
#define HOENN_DEX_COUNT (HOENN_DEX_DEOXYS + 1)
#define DECAGRAMS_IN_POUND 4536
#define CM_PER_INCH 2.54
#define CM_PER_INCH_FACTOR (CM_PER_INCH * 100)
#define INCHES_IN_FOOT 12
#define INCHES_IN_ONE_AND_HALF_FOOT (INCHES_IN_FOOT * 1.5)
#define INCHES_IN_FOOT_FACTOR (INCHES_IN_FOOT * 10)
#define WEIGHT_HEIGHT_STR_LEN 16
#define WEIGHT_HEIGHT_STR_MEM (WEIGHT_HEIGHT_STR_LEN * sizeof(u8))
#define DEX_HEADER_X 96
#define DEX_Y_TOP 57
#define DEX_Y_BOTTOM 73
#define DEX_MEASUREMENT_X 129
#define DEX_HGSS_HEADER_X_PADDING 59
#define DEX_HGSS_Y_TOP_PADDING 7
#define DEX_HGSS_Y_BOTTOM_PADDING 4
#define DEX_HGSS_MEASUREMENT_X_PADDING 51
#endif // GUARD_CONSTANTS_POKEDEX_H

View File

@ -323,6 +323,9 @@
#define NUM_NORMAL_ABILITY_SLOTS 2
#define NUM_HIDDEN_ABILITY_SLOTS 1
// Used as a signal for givemon to generate a default ability by personality.
#define NUM_ABILITY_PERSONALITY 0xFF
#define LEGENDARY_PERFECT_IV_COUNT 3
#endif // GUARD_CONSTANTS_POKEMON_H

View File

@ -63,7 +63,6 @@ struct TrainerBacksprite
#define GET_MON_COORDS_HEIGHT(size)((size & 0xF) * 8)
#define TRAINER_PARTY_IVS(hp, atk, def, speed, spatk, spdef) (hp | (atk << 5) | (def << 10) | (speed << 15) | (spatk << 20) | (spdef << 25))
#define TRAINER_PARTY_EVS(hp, atk, def, speed, spatk, spdef) ((const u8[6]){hp,atk,def,spatk,spdef,speed})
#define TRAINER_PARTY_NATURE(nature) (nature+1)
struct TrainerMon
{
@ -99,7 +98,7 @@ struct Trainer
/*0x13*/ u8 trainerName[TRAINER_NAME_LENGTH + 1];
/*0x1E*/ bool8 doubleBattle:1;
bool8 mugshotEnabled:1;
u8 padding:6;
u8 startingStatus:6; // this trainer starts a battle with a given status. see include/constants/battle.h for values
/*0x1F*/ u8 mugshotColor;
/*0x20*/ u8 partySize;
};

View File

@ -29,5 +29,8 @@ bool16 HasAllHoennMons(void);
void ResetPokedexScrollPositions(void);
bool16 HasAllMons(void);
void CB2_OpenPokedex(void);
void PrintMonMeasurements(u16 species, u32 owned);
u8* ConvertMonHeightToString(u32 height);
u8* ConvertMonWeightToString(u32 weight);
#endif // GUARD_POKEDEX_H

View File

@ -531,7 +531,9 @@ extern const u8 gText_PokedexRegistration[];
extern const u8 gText_NumberClear01[];
extern const u8 gText_5MarksPokemon[];
extern const u8 gText_UnkHeight[];
extern const u8 gText_UnkHeightMetric[];
extern const u8 gText_UnkWeight[];
extern const u8 gText_UnkWeightMetric[];
extern const u8 gText_HTHeight[];
extern const u8 gText_WTWeight[];
extern const u8 gText_SearchingPleaseWait[];

View File

@ -623,9 +623,9 @@ gCryTable::
.if P_FAMILY_TEDDIURSA == TRUE
cry Cry_Teddiursa
cry Cry_Ursaring
.if P_GEN_9_CROSS_EVOS == TRUE
.if P_GEN_8_CROSS_EVOS == TRUE
cry Cry_Ursaluna
.endif @ P_GEN_9_CROSS_EVOS
.endif @ P_GEN_8_CROSS_EVOS
.endif @ P_FAMILY_TEDDIURSA
.if P_FAMILY_SLUGMA == TRUE
cry Cry_Slugma
@ -3049,9 +3049,9 @@ gCryTable_Reverse::
.if P_FAMILY_TEDDIURSA == TRUE
cry_reverse Cry_Teddiursa
cry_reverse Cry_Ursaring
.if P_GEN_9_CROSS_EVOS == TRUE
.if P_GEN_8_CROSS_EVOS == TRUE
cry_reverse Cry_Ursaluna
.endif @ P_GEN_9_CROSS_EVOS
.endif @ P_GEN_8_CROSS_EVOS
.endif @ P_FAMILY_TEDDIURSA
.if P_FAMILY_SLUGMA == TRUE
cry_reverse Cry_Slugma

View File

@ -1844,11 +1844,11 @@ Cry_Teddiursa::
Cry_Ursaring::
.incbin "sound/direct_sound_samples/cries/ursaring.bin"
.if P_GEN_9_CROSS_EVOS == TRUE
.if P_GEN_8_CROSS_EVOS == TRUE
.align 2
Cry_Ursaluna::
.incbin "sound/direct_sound_samples/cries/ursaluna.bin"
.endif @ P_GEN_9_CROSS_EVOS
.endif @ P_GEN_8_CROSS_EVOS
.endif @ P_FAMILY_TEDDIURSA
.if P_FAMILY_SLUGMA == TRUE

View File

@ -52,6 +52,7 @@ static s32 AI_Roaming(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
static s32 AI_Safari(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
static s32 AI_FirstBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
static s32 AI_PowerfulStatus(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
static s32 (*const sBattleAiFuncTable[])(u32, u32, u32, s32) =
@ -65,10 +66,10 @@ static s32 (*const sBattleAiFuncTable[])(u32, u32, u32, s32) =
[6] = AI_PreferBatonPass, // AI_FLAG_PREFER_BATON_PASS
[7] = AI_DoubleBattle, // AI_FLAG_DOUBLE_BATTLE
[8] = AI_HPAware, // AI_FLAG_HP_AWARE
[9] = NULL, // AI_FLAG_NEGATE_UNAWARE
[10] = NULL, // AI_FLAG_WILL_SUICIDE
[11] = NULL, // AI_FLAG_HELP_PARTNER
[12] = NULL, // Unused
[9] = AI_PowerfulStatus, // AI_FLAG_POWERFUL_STATUS
[10] = NULL, // AI_FLAG_NEGATE_UNAWARE
[11] = NULL, // AI_FLAG_WILL_SUICIDE
[12] = NULL, // AI_FLAG_HELP_PARTNER
[13] = NULL, // Unused
[14] = NULL, // Unused
[15] = NULL, // Unused
@ -1762,7 +1763,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
break;
case EFFECT_FOLLOW_ME:
case EFFECT_HELPING_HAND:
case EFFECT_DRAGON_CHEER:
if (!isDoubleBattle
|| !IsBattlerAlive(BATTLE_PARTNER(battlerAtk))
|| PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)
@ -1904,19 +1904,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
if (aiData->abilities[battlerAtk] != ABILITY_MAGIC_GUARD && AI_DATA->moveAccuracy[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] < 75)
ADJUST_SCORE(-6);
break;
case EFFECT_TEETER_DANCE:
if (((gBattleMons[battlerDef].status2 & STATUS2_CONFUSION)
|| (!DoesBattlerIgnoreAbilityChecks(aiData->abilities[battlerAtk], move) && aiData->abilities[battlerDef] == ABILITY_OWN_TEMPO)
|| (IsBattlerGrounded(battlerDef) && AI_IsTerrainAffected(battlerDef, STATUS_FIELD_MISTY_TERRAIN))
|| (DoesSubstituteBlockMove(battlerAtk, battlerDef, move)))
&& ((gBattleMons[BATTLE_PARTNER(battlerDef)].status2 & STATUS2_CONFUSION)
|| (!DoesBattlerIgnoreAbilityChecks(aiData->abilities[battlerAtk], move) && aiData->abilities[BATTLE_PARTNER(battlerDef)] == ABILITY_OWN_TEMPO)
|| (IsBattlerGrounded(BATTLE_PARTNER(battlerDef)) && AI_IsTerrainAffected(BATTLE_PARTNER(battlerDef), STATUS_FIELD_MISTY_TERRAIN))
|| (DoesSubstituteBlockMove(battlerAtk, BATTLE_PARTNER(battlerDef), move))))
{
ADJUST_SCORE(-10);
}
break;
case EFFECT_TRANSFORM:
if (gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED
|| (gBattleMons[battlerDef].status2 & (STATUS2_TRANSFORMED | STATUS2_SUBSTITUTE))) //Leave out Illusion b/c AI is supposed to be fooled
@ -2341,15 +2328,18 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
{
ADJUST_SCORE(-10);
}
else if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM) // Trick Room Up
else if (!(AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_POWERFUL_STATUS))
{
if (GetBattlerSideSpeedAverage(battlerAtk) < GetBattlerSideSpeedAverage(battlerDef)) // Attacker side slower than target side
ADJUST_SCORE(-10); // Keep the Trick Room up
}
else
{
if (GetBattlerSideSpeedAverage(battlerAtk) >= GetBattlerSideSpeedAverage(battlerDef)) // Attacker side faster than target side
ADJUST_SCORE(-10); // Keep the Trick Room down
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM) // Trick Room Up
{
if (GetBattlerSideSpeedAverage(battlerAtk) < GetBattlerSideSpeedAverage(battlerDef)) // Attacker side slower than target side
ADJUST_SCORE(-10); // Keep the Trick Room up
}
else
{
if (GetBattlerSideSpeedAverage(battlerAtk) >= GetBattlerSideSpeedAverage(battlerDef)) // Attacker side faster than target side
ADJUST_SCORE(-10); // Keep the Trick Room down
}
}
break;
case EFFECT_MAGIC_ROOM:
@ -2787,7 +2777,8 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
ADJUST_SCORE(-5);
else if (atkPartnerHoldEffect == HOLD_EFFECT_SCOPE_LENS
|| IS_BATTLER_OF_TYPE(battlerAtkPartner, TYPE_DRAGON)
|| gMovesInfo[aiData->partnerMove].criticalHitStage > 0)
|| gMovesInfo[aiData->partnerMove].criticalHitStage > 0
|| HasMoveWithCriticalHitChance(battlerAtkPartner))
ADJUST_SCORE(GOOD_EFFECT);
} // our effect relative to partner
@ -2950,7 +2941,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
case EFFECT_SWAGGER:
if (gBattleMons[battlerAtkPartner].statStages[STAT_ATK] < MAX_STAT_STAGE
&& HasMoveWithCategory(battlerAtkPartner, DAMAGE_CATEGORY_PHYSICAL)
&& (!AI_CanBeConfused(battlerAtkPartner, TRUE)
&& (!AI_CanBeConfused(battlerAtk, battlerAtkPartner, move, TRUE)
|| atkPartnerHoldEffect == HOLD_EFFECT_CURE_CONFUSION
|| atkPartnerHoldEffect == HOLD_EFFECT_CURE_STATUS))
{
@ -2960,7 +2951,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
case EFFECT_FLATTER:
if (gBattleMons[battlerAtkPartner].statStages[STAT_SPATK] < MAX_STAT_STAGE
&& HasMoveWithCategory(battlerAtkPartner, DAMAGE_CATEGORY_SPECIAL)
&& (!AI_CanBeConfused(battlerAtkPartner, TRUE)
&& (!AI_CanBeConfused(battlerAtk, battlerAtkPartner, move, TRUE)
|| atkPartnerHoldEffect == HOLD_EFFECT_CURE_CONFUSION
|| atkPartnerHoldEffect == HOLD_EFFECT_CURE_STATUS))
{
@ -3489,8 +3480,6 @@ static u32 AI_CalcMoveScore(u32 battlerAtk, u32 battlerDef, u32 move)
ADJUST_SCORE(BEST_EFFECT);
if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_LIGHT_CLAY)
ADJUST_SCORE(DECENT_EFFECT);
if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_SCREENER)
ADJUST_SCORE(DECENT_EFFECT);
}
break;
case EFFECT_REST:
@ -3518,10 +3507,6 @@ static u32 AI_CalcMoveScore(u32 battlerAtk, u32 battlerDef, u32 move)
if (ShouldTrap(battlerAtk, battlerDef, move))
ADJUST_SCORE(GOOD_EFFECT);
break;
case EFFECT_MIST:
if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_SCREENER)
ADJUST_SCORE(DECENT_EFFECT);
break;
case EFFECT_FOCUS_ENERGY:
case EFFECT_LASER_FOCUS:
if (aiData->abilities[battlerAtk] == ABILITY_SUPER_LUCK
@ -3537,6 +3522,7 @@ static u32 AI_CalcMoveScore(u32 battlerAtk, u32 battlerDef, u32 move)
IncreaseParalyzeScore(battlerAtk, battlerDef, move, &score);
break;
case EFFECT_SUBSTITUTE:
ADJUST_SCORE(GOOD_EFFECT);
if (gStatuses3[battlerDef] & STATUS3_PERISH_SONG)
ADJUST_SCORE(GOOD_EFFECT);
if (gBattleMons[battlerDef].status1 & (STATUS1_BURN | STATUS1_PSN_ANY | STATUS1_FROSTBITE))
@ -3562,7 +3548,7 @@ static u32 AI_CalcMoveScore(u32 battlerAtk, u32 battlerDef, u32 move)
case EFFECT_LEECH_SEED:
if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS)
|| gStatuses3[battlerDef] & STATUS3_LEECHSEED
|| HasMoveWithMoveEffect(battlerDef, MOVE_EFFECT_RAPIDSPIN)
|| HasMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_RAPID_SPIN)
|| aiData->abilities[battlerDef] == ABILITY_LIQUID_OOZE
|| aiData->abilities[battlerDef] == ABILITY_MAGIC_GUARD)
break;
@ -3721,7 +3707,13 @@ static u32 AI_CalcMoveScore(u32 battlerAtk, u32 battlerDef, u32 move)
case EFFECT_STEALTH_ROCK:
case EFFECT_STICKY_WEB:
case EFFECT_TOXIC_SPIKES:
score += AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData);
if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData));
{
if (gDisableStructs[battlerAtk].isFirstTurn)
ADJUST_SCORE(BEST_EFFECT);
else
ADJUST_SCORE(DECENT_EFFECT);
}
break;
case EFFECT_FORESIGHT:
if (aiData->abilities[battlerAtk] == ABILITY_SCRAPPY || aiData->abilities[battlerAtk] == ABILITY_MINDS_EYE)
@ -3846,7 +3838,7 @@ static u32 AI_CalcMoveScore(u32 battlerAtk, u32 battlerDef, u32 move)
case EFFECT_FIRST_TURN_ONLY:
if (ShouldFakeOut(battlerAtk, battlerDef, move))
ADJUST_SCORE(GOOD_EFFECT);
else if (gMovesInfo[move].priority >= 1 && gDisableStructs[battlerAtk].isFirstTurn && GetBestDmgMoveFromBattler(battlerAtk, battlerDef) == move)
else if (gMovesInfo[move].argument == MOVE_FIRST_IMPRESSION && gDisableStructs[battlerAtk].isFirstTurn && GetBestDmgMoveFromBattler(battlerAtk, battlerDef) == move)
ADJUST_SCORE(BEST_EFFECT);
break;
case EFFECT_STOCKPILE:
@ -3861,7 +3853,7 @@ static u32 AI_CalcMoveScore(u32 battlerAtk, u32 battlerDef, u32 move)
case EFFECT_FLATTER:
if (HasMoveEffect(battlerAtk, EFFECT_FOUL_PLAY)
|| HasMoveEffect(battlerAtk, EFFECT_PSYCH_UP)
|| HasMoveWithMoveEffect(battlerAtk, MOVE_EFFECT_SPECTRAL_THIEF))
|| HasMoveWithAdditionalEffect(battlerAtk, MOVE_EFFECT_SPECTRAL_THIEF))
ADJUST_SCORE(DECENT_EFFECT);
if (aiData->abilities[battlerDef] == ABILITY_CONTRARY)
ADJUST_SCORE(GOOD_EFFECT);
@ -4173,6 +4165,8 @@ static u32 AI_CalcMoveScore(u32 battlerAtk, u32 battlerDef, u32 move)
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK, &score);
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK, &score);
break;
case EFFECT_TIDY_UP:
IncreaseTidyUpScore(battlerAtk, battlerDef, move, &score);
case EFFECT_DRAGON_DANCE:
case EFFECT_SHIFT_GEAR:
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPEED, &score);
@ -4254,10 +4248,13 @@ static u32 AI_CalcMoveScore(u32 battlerAtk, u32 battlerDef, u32 move)
ADJUST_SCORE(GOOD_EFFECT); // Partner might use pledge move
break;
case EFFECT_TRICK_ROOM:
if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && GetBattlerSideSpeedAverage(battlerAtk) < GetBattlerSideSpeedAverage(battlerDef))
ADJUST_SCORE(GOOD_EFFECT);
else if ((gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && GetBattlerSideSpeedAverage(battlerAtk) >= GetBattlerSideSpeedAverage(battlerDef))
ADJUST_SCORE(GOOD_EFFECT);
if (!(AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_POWERFUL_STATUS))
{
if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && GetBattlerSideSpeedAverage(battlerAtk) < GetBattlerSideSpeedAverage(battlerDef))
ADJUST_SCORE(GOOD_EFFECT);
else if ((gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && GetBattlerSideSpeedAverage(battlerAtk) >= GetBattlerSideSpeedAverage(battlerDef))
ADJUST_SCORE(GOOD_EFFECT);
}
break;
case EFFECT_MAGIC_ROOM:
ADJUST_SCORE(WEAK_EFFECT);
@ -4505,7 +4502,7 @@ static u32 AI_CalcMoveScore(u32 battlerAtk, u32 battlerDef, u32 move)
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPDEF, &score);
}
break;
case MOVE_EFFECT_RAPIDSPIN:
case MOVE_EFFECT_RAPID_SPIN:
if ((gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerAtk) != 0)
|| (gStatuses3[battlerAtk] & STATUS3_LEECHSEED || gBattleMons[battlerAtk].status2 & STATUS2_WRAPPED))
ADJUST_SCORE(GOOD_EFFECT);
@ -4638,7 +4635,13 @@ static u32 AI_CalcMoveScore(u32 battlerAtk, u32 battlerDef, u32 move)
break;
case MOVE_EFFECT_STEALTH_ROCK:
case MOVE_EFFECT_SPIKES:
score += AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData);
if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData));
{
if (gDisableStructs[battlerAtk].isFirstTurn)
ADJUST_SCORE(BEST_EFFECT);
else
ADJUST_SCORE(DECENT_EFFECT);
}
break;
case MOVE_EFFECT_FEINT:
if (gMovesInfo[predictedMove].effect == EFFECT_PROTECT)
@ -4654,7 +4657,7 @@ static u32 AI_CalcMoveScore(u32 battlerAtk, u32 battlerDef, u32 move)
}
break;
case MOVE_EFFECT_WRAP:
if (!HasMoveWithMoveEffect(battlerDef, MOVE_EFFECT_RAPIDSPIN) && ShouldTrap(battlerAtk, battlerDef, move))
if (!HasMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_RAPID_SPIN) && ShouldTrap(battlerAtk, battlerDef, move))
ADJUST_SCORE(BEST_EFFECT);
break;
}
@ -4757,7 +4760,6 @@ static s32 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
case EFFECT_WILL_O_WISP:
case EFFECT_INGRAIN:
case EFFECT_IMPRISON:
case EFFECT_TEETER_DANCE:
case EFFECT_TICKLE:
case EFFECT_COSMIC_POWER:
case EFFECT_BULK_UP:
@ -4781,6 +4783,7 @@ static s32 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
case EFFECT_MAGIC_ROOM:
case EFFECT_TAILWIND:
case EFFECT_DRAGON_DANCE:
case EFFECT_TIDY_UP:
case EFFECT_STICKY_WEB:
case EFFECT_RAIN_DANCE:
case EFFECT_SUNNY_DAY:
@ -4841,7 +4844,6 @@ static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
case EFFECT_MIRROR_COAT:
case EFFECT_FOCUS_PUNCH:
case EFFECT_REVENGE:
case EFFECT_TEETER_DANCE:
case EFFECT_FILLET_AWAY:
if (Random() & 1)
ADJUST_SCORE(DECENT_EFFECT);
@ -5124,6 +5126,96 @@ static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
return score;
}
static s32 AI_PowerfulStatus(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
{
u32 moveEffect = gMovesInfo[move].effect;
if (gMovesInfo[move].category != DAMAGE_CATEGORY_STATUS || gMovesInfo[AI_DATA->partnerMove].effect == moveEffect)
return score;
switch (moveEffect)
{
case EFFECT_TAILWIND:
if (!gSideTimers[GetBattlerSide(battlerAtk)].tailwindTimer && !(gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer > 1))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_TRICK_ROOM:
if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && !HasMoveEffect(battlerDef, EFFECT_TRICK_ROOM))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_MAGIC_ROOM:
if (!(gFieldStatuses & STATUS_FIELD_MAGIC_ROOM) && !HasMoveEffect(battlerDef, EFFECT_MAGIC_ROOM))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_WONDER_ROOM:
if (!(gFieldStatuses & STATUS_FIELD_WONDER_ROOM) && !HasMoveEffect(battlerDef, EFFECT_WONDER_ROOM))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_GRAVITY:
if (!(gFieldStatuses & STATUS_FIELD_GRAVITY))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_SAFEGUARD:
if (!(gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_SAFEGUARD))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_MIST:
if (!(gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_MIST))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_LIGHT_SCREEN:
case EFFECT_REFLECT:
case EFFECT_AURORA_VEIL:
if (ShouldSetScreen(battlerAtk, battlerDef, moveEffect))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_SPIKES:
case EFFECT_STEALTH_ROCK:
case EFFECT_STICKY_WEB:
case EFFECT_TOXIC_SPIKES:
if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, AI_DATA))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_GRASSY_TERRAIN:
if (!(gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_ELECTRIC_TERRAIN:
if (!(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_PSYCHIC_TERRAIN:
if (!(gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_MISTY_TERRAIN:
if (!(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_SANDSTORM:
if (!(AI_GetWeather(AI_DATA) & (B_WEATHER_SANDSTORM | B_WEATHER_PRIMAL_ANY)))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_SUNNY_DAY:
if (!(AI_GetWeather(AI_DATA) & (B_WEATHER_SUN | B_WEATHER_PRIMAL_ANY)))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_RAIN_DANCE:
if (!(AI_GetWeather(AI_DATA) & (B_WEATHER_RAIN | B_WEATHER_PRIMAL_ANY)))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_HAIL:
if (!(AI_GetWeather(AI_DATA) & (B_WEATHER_HAIL | B_WEATHER_PRIMAL_ANY)))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_SNOWSCAPE:
if (!(AI_GetWeather(AI_DATA) & (B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY)))
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
}
return score;
}
static void AI_Flee(void)
{
AI_THINKING_STRUCT->aiAction |= (AI_ACTION_DONE | AI_ACTION_FLEE | AI_ACTION_DO_NOT_ATTACK);

View File

@ -1134,7 +1134,6 @@ bool32 IsConfusionMoveEffect(u32 moveEffect)
case EFFECT_CONFUSE:
case EFFECT_SWAGGER:
case EFFECT_FLATTER:
case EFFECT_TEETER_DANCE:
return TRUE;
default:
return FALSE;
@ -1709,7 +1708,7 @@ bool32 HasMoveEffectANDArg(u32 battlerId, u32 effect, u32 argument)
return FALSE;
}
bool32 HasMoveWithMoveEffect(u32 battlerId, u32 moveEffect)
bool32 HasMoveWithAdditionalEffect(u32 battlerId, u32 moveEffect)
{
s32 i;
u16 *moves = GetMovesArray(battlerId);
@ -1724,6 +1723,21 @@ bool32 HasMoveWithMoveEffect(u32 battlerId, u32 moveEffect)
return FALSE;
}
bool32 HasMoveWithCriticalHitChance(u32 battlerId)
{
s32 i;
u16 *moves = GetMovesArray(battlerId);
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE
&& gMovesInfo[moves[i]].criticalHitStage > 0)
return TRUE;
}
return FALSE;
}
bool32 HasMoveWithMoveEffectExcept(u32 battlerId, u32 moveEffect, u32 exception)
{
s32 i;
@ -2585,25 +2599,27 @@ bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move,
return TRUE;
}
bool32 AI_CanBeConfused(u32 battler, u32 ability)
bool32 AI_CanBeConfused(u32 battlerAtk, u32 battlerDef, u32 move, u32 ability)
{
if ((gBattleMons[battler].status2 & STATUS2_CONFUSION)
|| (ability == ABILITY_OWN_TEMPO)
|| (IsBattlerGrounded(battler) && (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN)))
if ((gBattleMons[battlerDef].status2 & STATUS2_CONFUSION)
|| (ability == ABILITY_OWN_TEMPO && !DoesBattlerIgnoreAbilityChecks(AI_DATA->abilities[battlerAtk], move))
|| (IsBattlerGrounded(battlerDef) && (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN))
|| gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move))
return FALSE;
return TRUE;
}
bool32 AI_CanConfuse(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove)
{
if (!AI_CanBeConfused(battlerDef, defAbility)
|| AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == AI_EFFECTIVENESS_x0
|| gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|| DoesPartnerHaveSameMoveEffect(battlerAtkPartner, battlerDef, move, partnerMove))
{
if (gMovesInfo[move].target == MOVE_TARGET_FOES_AND_ALLY
&& AI_CanBeConfused(battlerAtk, battlerDef, move, defAbility)
&& !AI_CanBeConfused(battlerAtk, BATTLE_PARTNER(battlerDef), move, AI_DATA->abilities[BATTLE_PARTNER(battlerDef)]))
return FALSE;
if (!AI_CanBeConfused(battlerAtk, battlerDef, move, defAbility)
|| DoesPartnerHaveSameMoveEffect(battlerAtkPartner, battlerDef, move, partnerMove))
return FALSE;
}
return TRUE;
}
@ -2860,6 +2876,10 @@ bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u32 move, u32 healPercent)
bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, u32 moveEffect)
{
u32 atkSide = GetBattlerSide(battlerAtk);
if (HasMoveEffect(battlerDef, EFFECT_BRICK_BREAK)) // Don't waste a turn if screens will be broken
return FALSE;
switch (moveEffect)
{
case EFFECT_AURORA_VEIL:
@ -3297,7 +3317,7 @@ void IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, u32 statId, s32 *score)
return;
// Don't set up if AI is dead to residual damage from weather
if (BattlerWillFaintFromWeather(battlerAtk, AI_DATA->abilities[battlerAtk]))
if (GetBattlerSecondaryDamage(battlerAtk) >= gBattleMons[battlerAtk].hp)
return;
// Don't increase stats if opposing battler has Opportunist
@ -3312,10 +3332,15 @@ void IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, u32 statId, s32 *score)
break;
case STAT_CHANGE_DEF:
if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL) || !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL))
ADJUST_SCORE_PTR(DECENT_EFFECT);
{
if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_STALL)
ADJUST_SCORE_PTR(DECENT_EFFECT);
else
ADJUST_SCORE_PTR(WEAK_EFFECT);
}
break;
case STAT_CHANGE_SPEED:
if ((noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == 0)
if ((noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS)
ADJUST_SCORE_PTR(DECENT_EFFECT);
break;
case STAT_CHANGE_SPATK:
@ -3324,7 +3349,12 @@ void IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, u32 statId, s32 *score)
break;
case STAT_CHANGE_SPDEF:
if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL) || !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL))
ADJUST_SCORE_PTR(DECENT_EFFECT);
{
if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_STALL)
ADJUST_SCORE_PTR(DECENT_EFFECT);
else
ADJUST_SCORE_PTR(WEAK_EFFECT);
}
break;
case STAT_CHANGE_ATK_2:
if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL) && shouldSetUp)
@ -3332,10 +3362,15 @@ void IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, u32 statId, s32 *score)
break;
case STAT_CHANGE_DEF_2:
if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL) || !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL))
ADJUST_SCORE_PTR(GOOD_EFFECT);
{
if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_STALL)
ADJUST_SCORE_PTR(GOOD_EFFECT);
else
ADJUST_SCORE_PTR(DECENT_EFFECT);
}
break;
case STAT_CHANGE_SPEED_2:
if ((noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == 0)
if ((noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS)
ADJUST_SCORE_PTR(GOOD_EFFECT);
break;
case STAT_CHANGE_SPATK_2:
@ -3344,14 +3379,19 @@ void IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, u32 statId, s32 *score)
break;
case STAT_CHANGE_SPDEF_2:
if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL) || !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL))
ADJUST_SCORE_PTR(GOOD_EFFECT);
{
if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_STALL)
ADJUST_SCORE_PTR(GOOD_EFFECT);
else
ADJUST_SCORE_PTR(DECENT_EFFECT);
}
break;
case STAT_CHANGE_ACC:
if (gBattleMons[battlerAtk].statStages[STAT_ACC] <= 3) // Increase only if necessary
ADJUST_SCORE_PTR(DECENT_EFFECT);
break;
case STAT_CHANGE_EVASION:
if (GetBattlerSecondaryDamage(battlerAtk) && ((noOfHitsToFaint > 3) || noOfHitsToFaint == 0))
if (noOfHitsToFaint > 3 || noOfHitsToFaint == UNKNOWN_NO_OF_HITS)
ADJUST_SCORE_PTR(GOOD_EFFECT);
else
ADJUST_SCORE_PTR(DECENT_EFFECT);
@ -3567,10 +3607,31 @@ bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef)
}
//TODO - track entire opponent party data to determine hazard effectiveness
s32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData)
bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData)
{
if (aiData->abilities[battlerDef] == ABILITY_MAGIC_BOUNCE || CountUsablePartyMons(battlerDef) == 0)
return 0;
if (aiData->abilities[battlerDef] == ABILITY_MAGIC_BOUNCE
|| CountUsablePartyMons(battlerDef) == 0
|| HasMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_RAPID_SPIN)
|| HasMoveEffect(battlerDef, EFFECT_DEFOG))
return FALSE;
return 2 * gDisableStructs[battlerAtk].isFirstTurn;
return TRUE;
}
void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score)
{
if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerAtk) != 0)
ADJUST_SCORE_PTR(GOOD_EFFECT);
if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerDef) != 0)
ADJUST_SCORE_PTR(-2);
if (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE && AI_STRIKES_FIRST(battlerAtk, battlerDef, move))
ADJUST_SCORE_PTR(-10);
if (gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE)
ADJUST_SCORE_PTR(GOOD_EFFECT);
if (gStatuses3[battlerAtk] & STATUS3_LEECHSEED)
ADJUST_SCORE_PTR(DECENT_EFFECT);
if (gStatuses3[battlerDef] & STATUS3_LEECHSEED)
ADJUST_SCORE_PTR(-2);
}

View File

@ -3468,9 +3468,14 @@ void TryAddLastUsedBallItemSprites(void)
|| (gLastThrownBall != 0 && !CheckBagHasItem(gLastThrownBall, 1)))
{
// we're out of the last used ball, so just set it to the first ball in the bag
u16 firstBall;
// we have to compact the bag first bc it is typically only compacted when you open it
CompactItemsInBagPocket(&gBagPockets[BALLS_POCKET]);
gBallToDisplay = gBagPockets[BALLS_POCKET].itemSlots[0].itemId;
firstBall = gBagPockets[BALLS_POCKET].itemSlots[0].itemId;
if (firstBall > ITEM_NONE)
gBallToDisplay = firstBall;
}
if (!CanThrowLastUsedBall())

View File

@ -1928,7 +1928,7 @@ void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMon
u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer, u32 battleTypeFlags)
{
u32 personalityValue;
s32 i, j;
s32 i;
u8 monsCount;
if (battleTypeFlags & BATTLE_TYPE_TRAINER && !(battleTypeFlags & (BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_EREADER_TRAINER
@ -1956,6 +1956,7 @@ u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer
const struct TrainerMon *partyData = trainer->party;
u32 otIdType = OT_ID_RANDOM_NO_SHINY;
u32 fixedOtId = 0;
u32 ability = 0;
if (trainer->doubleBattle == TRUE)
personalityValue = 0x80;
@ -1969,8 +1970,7 @@ u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer
personalityValue = (personalityValue & 0xFFFFFF00) | GeneratePersonalityForGender(MON_MALE, partyData[i].species);
else if (partyData[i].gender == TRAINER_MON_FEMALE)
personalityValue = (personalityValue & 0xFFFFFF00) | GeneratePersonalityForGender(MON_FEMALE, partyData[i].species);
if (partyData[i].nature != 0)
ModifyPersonalityForNature(&personalityValue, partyData[i].nature - 1);
ModifyPersonalityForNature(&personalityValue, partyData[i].nature);
if (partyData[i].isShiny)
{
otIdType = OT_ID_PRESET;
@ -1994,14 +1994,24 @@ u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer
{
const struct SpeciesInfo *speciesInfo = &gSpeciesInfo[partyData[i].species];
u32 maxAbilities = ARRAY_COUNT(speciesInfo->abilities);
for (j = 0; j < maxAbilities; ++j)
for (ability = 0; ability < maxAbilities; ++ability)
{
if (speciesInfo->abilities[j] == partyData[i].ability)
if (speciesInfo->abilities[ability] == partyData[i].ability)
break;
}
if (j < maxAbilities)
SetMonData(&party[i], MON_DATA_ABILITY_NUM, &j);
if (ability >= maxAbilities)
ability = 0;
}
else if (B_TRAINER_MON_RANDOM_ABILITY)
{
const struct SpeciesInfo *speciesInfo = &gSpeciesInfo[partyData[i].species];
ability = personalityHash % 3;
while (speciesInfo->abilities[ability] == ABILITY_NONE)
{
ability--;
}
}
SetMonData(&party[i], MON_DATA_ABILITY_NUM, &ability);
SetMonData(&party[i], MON_DATA_FRIENDSHIP, &(partyData[i].friendship));
if (partyData[i].ball != ITEM_NONE)
{
@ -3724,6 +3734,24 @@ static void DoBattleIntro(void)
gBattleStruct->overworldWeatherDone = FALSE;
SetAiLogicDataForTurn(AI_DATA); // get assumed abilities, hold effects, etc of all battlers
Ai_InitPartyStruct(); // Save mons party counts, and first 2/4 mons on the battlefield.
// Try to set a status to start the battle with
gBattleStruct->startingStatus = 0;
if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && gTrainers[gTrainerBattleOpponent_B].startingStatus)
{
gBattleStruct->startingStatus = gTrainers[gTrainerBattleOpponent_B].startingStatus;
gBattleStruct->startingStatusTimer = 0; // infinite
}
else if (gTrainers[gTrainerBattleOpponent_A].startingStatus)
{
gBattleStruct->startingStatus = gTrainers[gTrainerBattleOpponent_A].startingStatus;
gBattleStruct->startingStatusTimer = 0; // infinite
}
else if (B_VAR_STARTING_STATUS != 0)
{
gBattleStruct->startingStatus = VarGet(B_VAR_STARTING_STATUS);
gBattleStruct->startingStatusTimer = VarGet(B_VAR_STARTING_STATUS_TIMER);
}
gBattleMainFunc = TryDoEventsBeforeFirstTurn;
}
break;
@ -3789,6 +3817,14 @@ static void TryDoEventsBeforeFirstTurn(void)
return;
}
if (!gBattleStruct->startingStatusDone
&& gBattleStruct->startingStatus
&& AbilityBattleEffects(ABILITYEFFECT_SWITCH_IN_STATUSES, 0, 0, ABILITYEFFECT_SWITCH_IN_STATUSES, 0) != 0)
{
gBattleStruct->startingStatusDone = TRUE;
return;
}
// Totem boosts
for (i = 0; i < gBattlersCount; i++)
{
@ -4977,7 +5013,7 @@ static void TurnValuesCleanUp(bool8 var0)
else
{
memset(&gProtectStructs[i], 0, sizeof(struct ProtectStruct));
memset(&gQueuedStatBoosts[i], 0, sizeof(gQueuedStatBoosts));
memset(&gQueuedStatBoosts[i], 0, sizeof(struct QueuedStatBoost));
if (gDisableStructs[i].isFirstTurn)
gDisableStructs[i].isFirstTurn--;

View File

@ -559,6 +559,7 @@ static const u8 sText_PkmnSwitchedStatChanges[] = _("{B_ATK_NAME_WITH_PREFIX} sw
static const u8 sText_PkmnSurroundedWithVeilOfWater[] = _("{B_ATK_NAME_WITH_PREFIX} surrounded itself\nwith a veil of water!");
static const u8 sText_PkmnLevitatedOnElectromagnetism[] = _("{B_ATK_NAME_WITH_PREFIX} levitated on\nelectromagnetism!");
static const u8 sText_PkmnTwistedDimensions[] = _("{B_ATK_NAME_WITH_PREFIX} twisted\nthe dimensions!");
static const u8 sText_DimensionsWereTwisted[] = _("The dimensions were\ntwisted!");
static const u8 sText_PointedStonesFloat[] =_("Pointed stones float in the air\naround {B_DEF_TEAM2} team!");
static const u8 sText_CloakedInMysticalMoonlight[] =_("It became cloaked in mystical\nmoonlight!");
static const u8 sText_TrappedBySwirlingMagma[] =_("{B_DEF_NAME_WITH_PREFIX} became\ntrapped by swirling magma!");
@ -567,9 +568,11 @@ static const u8 sText_ProtectedTeam[] =_("{B_CURRENT_MOVE} protected\n{B_ATK_TEA
static const u8 sText_SharedItsGuard[] =_("{B_ATK_NAME_WITH_PREFIX} shared its\nguard with the target!");
static const u8 sText_SharedItsPower[] =_("{B_ATK_NAME_WITH_PREFIX} shared its\npower with the target!");
static const u8 sText_SwapsDefAndSpDefOfAllPkmn[] =_("It created a bizarre area in which the\nDefense and Sp. Def stats are swapped!");
static const u8 sText_BizzareAreaCreated[] =_("A bizarre area was created in which the\nDefense and Sp. Def stats are swapped!");
static const u8 sText_BecameNimble[] =_("{B_ATK_NAME_WITH_PREFIX} became nimble!");
static const u8 sText_HurledIntoTheAir[] =_("{B_DEF_NAME_WITH_PREFIX} was hurled\ninto the air!");
static const u8 sText_HeldItemsLoseEffects[] =_("It created a bizarre area in which\nPokémon's held items lose their effects!");
static const u8 sText_BizarreArenaCreated[] =_("A bizarre area was created!\nHold items lost their effects!");
static const u8 sText_FellStraightDown[] =_("{B_DEF_NAME_WITH_PREFIX} fell\nstraight down!");
static const u8 sText_TargetChangedType[] =_("{B_DEF_NAME_WITH_PREFIX} transformed\ninto the {B_BUFF1} type!");
static const u8 sText_PkmnAcquiredSimple[] =_("{B_DEF_NAME_WITH_PREFIX} acquired\nSimple!");
@ -840,9 +843,11 @@ static const u8 sText_ItemWasUsedUp[] = _("The {B_LAST_ITEM}\nwas used up...");
static const u8 sText_AttackerLostItsType[] = _("{B_ATK_NAME_WITH_PREFIX} lost\nits {B_BUFF1} type!");
static const u8 sText_ShedItsTail[] = _("{B_ATK_NAME_WITH_PREFIX} shed its tail\nto create a decoy!");
static const u8 sText_SupersweetAromaWafts[] = _("A supersweet aroma is wafting from\nthe syrup covering {B_ATK_NAME_WITH_PREFIX}!");
static const u8 sText_TidyingUpComplete[] = _("Tidying up complete!");
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
{
[STRINGID_TIDYINGUPCOMPLETE - BATTLESTRINGS_TABLE_START] = sText_TidyingUpComplete,
[STRINGID_SUPERSWEETAROMAWAFTS - BATTLESTRINGS_TABLE_START] = sText_SupersweetAromaWafts,
[STRINGID_SHEDITSTAIL - BATTLESTRINGS_TABLE_START] = sText_ShedItsTail,
[STRINGID_ELECTROSHOTCHARGING - BATTLESTRINGS_TABLE_START] = sText_ElectroShotCharging,
@ -1384,6 +1389,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
[STRINGID_PKMNSURROUNDEDWITHVEILOFWATER - BATTLESTRINGS_TABLE_START] = sText_PkmnSurroundedWithVeilOfWater,
[STRINGID_PKMNLEVITATEDONELECTROMAGNETISM - BATTLESTRINGS_TABLE_START] = sText_PkmnLevitatedOnElectromagnetism,
[STRINGID_PKMNTWISTEDDIMENSIONS - BATTLESTRINGS_TABLE_START] = sText_PkmnTwistedDimensions,
[STRINGID_DIMENSIONSWERETWISTED - BATTLESTRINGS_TABLE_START] = sText_DimensionsWereTwisted,
[STRINGID_POINTEDSTONESFLOAT - BATTLESTRINGS_TABLE_START] = sText_PointedStonesFloat,
[STRINGID_CLOAKEDINMYSTICALMOONLIGHT - BATTLESTRINGS_TABLE_START] = sText_CloakedInMysticalMoonlight,
[STRINGID_TRAPPEDBYSWIRLINGMAGMA - BATTLESTRINGS_TABLE_START] = sText_TrappedBySwirlingMagma,
@ -1392,9 +1398,11 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
[STRINGID_SHAREDITSGUARD - BATTLESTRINGS_TABLE_START] = sText_SharedItsGuard,
[STRINGID_SHAREDITSPOWER - BATTLESTRINGS_TABLE_START] = sText_SharedItsPower,
[STRINGID_SWAPSDEFANDSPDEFOFALLPOKEMON - BATTLESTRINGS_TABLE_START] = sText_SwapsDefAndSpDefOfAllPkmn,
[STRINGID_BIZARREAREACREATED - BATTLESTRINGS_TABLE_START] = sText_BizzareAreaCreated,
[STRINGID_BECAMENIMBLE - BATTLESTRINGS_TABLE_START] = sText_BecameNimble,
[STRINGID_HURLEDINTOTHEAIR - BATTLESTRINGS_TABLE_START] = sText_HurledIntoTheAir,
[STRINGID_HELDITEMSLOSEEFFECTS - BATTLESTRINGS_TABLE_START] = sText_HeldItemsLoseEffects,
[STRINGID_BIZARREARENACREATED - BATTLESTRINGS_TABLE_START] = sText_BizarreArenaCreated,
[STRINGID_FELLSTRAIGHTDOWN - BATTLESTRINGS_TABLE_START] = sText_FellStraightDown,
[STRINGID_TARGETCHANGEDTYPE - BATTLESTRINGS_TABLE_START] = sText_TargetChangedType,
[STRINGID_PKMNACQUIREDSIMPLE - BATTLESTRINGS_TABLE_START] = sText_PkmnAcquiredSimple,
@ -1563,6 +1571,19 @@ const u16 gMentalHerbCureStringIds[] =
[B_MSG_MENTALHERBCURE_DISABLE] = STRINGID_PKMNMOVEDISABLEDNOMORE,
};
const u16 gStartingStatusStringIds[B_MSG_STARTING_STATUS_COUNT] =
{
[B_MSG_TERRAIN_SET_MISTY] = STRINGID_TERRAINBECOMESMISTY,
[B_MSG_TERRAIN_SET_ELECTRIC] = STRINGID_TERRAINBECOMESELECTRIC,
[B_MSG_TERRAIN_SET_PSYCHIC] = STRINGID_TERRAINBECOMESPSYCHIC,
[B_MSG_TERRAIN_SET_GRASSY] = STRINGID_TERRAINBECOMESGRASSY,
[B_MSG_SET_TRICK_ROOM] = STRINGID_DIMENSIONSWERETWISTED,
[B_MSG_SET_MAGIC_ROOM] = STRINGID_BIZARREARENACREATED,
[B_MSG_SET_WONDER_ROOM] = STRINGID_BIZARREAREACREATED,
[B_MSG_SET_TAILWIND_PLAYER] = STRINGID_TAILWINDBLEW,
[B_MSG_SET_TAILWIND_OPPONENT] = STRINGID_TAILWINDBLEW,
};
const u16 gTerrainStringIds[B_MSG_TERRAIN_COUNT] =
{
[B_MSG_TERRAIN_SET_MISTY] = STRINGID_TERRAINBECOMESMISTY,
@ -3189,7 +3210,7 @@ static const u8 *BattleStringGetPlayerName(u8 *text, u8 battler)
if (DECAP_ENABLED && !DECAP_NICKNAMES && toCpy != text && *toCpy != CHAR_FIXED_CASE)
{
*text = CHAR_FIXED_CASE;
StringCopyN(text+1, toCpy, PLAYER_NAME_LENGTH);
StringCopyN(text+1, toCpy, PLAYER_NAME_LENGTH + 1);
toCpy = text;
}

View File

@ -2843,7 +2843,7 @@ void SetMoveEffect(bool32 primary, bool32 certain)
{
case STATUS1_SLEEP:
// check active uproar
if (battlerAbility != ABILITY_SOUNDPROOF)
if (battlerAbility != ABILITY_SOUNDPROOF || B_UPROAR_IGNORE_SOUNDPROOF >= GEN_5)
{
for (i = 0; i < gBattlersCount && !(gBattleMons[i].status2 & STATUS2_UPROAR); i++)
;
@ -3451,7 +3451,7 @@ void SetMoveEffect(bool32 primary, bool32 certain)
gBattlescriptCurrInstr = BattleScript_AllStatsUp;
}
break;
case MOVE_EFFECT_RAPIDSPIN:
case MOVE_EFFECT_RAPID_SPIN:
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_RapidSpinAway;
break;
@ -8397,6 +8397,44 @@ static bool32 TryDefogClear(u32 battlerAtk, bool32 clear)
return FALSE;
}
static bool32 TryTidyUpClear(u32 battlerAtk, bool32 clear)
{
s32 i;
u8 saveBattler = gBattlerAttacker;
for (i = 0; i < NUM_BATTLE_SIDES; i++)
{
struct SideTimer *sideTimer = &gSideTimers[i];
u32 *sideStatuses = &gSideStatuses[i];
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);
DEFOG_CLEAR(SIDE_STATUS_STICKY_WEB, stickyWebAmount, BattleScript_StickyWebDefog, 0);
}
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
if (gBattleMons[i].status2 & STATUS2_SUBSTITUTE)
{
if (clear)
{
gBattlerTarget = i;
gDisableStructs[i].substituteHP = 0;
gBattleMons[i].status2 &= ~STATUS2_SUBSTITUTE;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_SubstituteFade;
}
gBattlerAttacker = saveBattler;
return TRUE;
}
}
gBattlerAttacker = saveBattler;
return FALSE;
}
u32 IsFlowerVeilProtected(u32 battler)
{
if (IS_BATTLER_OF_TYPE(battler, TYPE_GRASS))
@ -11142,7 +11180,7 @@ bool8 UproarWakeUpCheck(u8 battler)
for (i = 0; i < gBattlersCount; i++)
{
if (!(gBattleMons[i].status2 & STATUS2_UPROAR) || GetBattlerAbility(battler) == ABILITY_SOUNDPROOF)
if (!(gBattleMons[i].status2 & STATUS2_UPROAR) || (GetBattlerAbility(battler) == ABILITY_SOUNDPROOF && B_UPROAR_IGNORE_SOUNDPROOF < GEN_5))
continue;
gBattleScripting.battler = i;
@ -16671,3 +16709,23 @@ void BS_TryUpdateRecoilTracker(void)
TryUpdateEvolutionTracker(EVO_LEVEL_RECOIL_DAMAGE_FEMALE, gBattleMoveDamage);
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_TryTidyUp(void)
{
NATIVE_ARGS(u8 clear, const u8 *jumpInstr);
if (cmd->clear)
{
if (TryTidyUpClear(gEffectBattler, TRUE))
return;
else
gBattlescriptCurrInstr = cmd->nextInstr;
}
else
{
if (TryTidyUpClear(gBattlerAttacker, FALSE))
gBattlescriptCurrInstr = cmd->jumpInstr;
else
gBattlescriptCurrInstr = cmd->nextInstr;
}
}

View File

@ -942,7 +942,7 @@ static void AddMovePoints(u8 caseId, u16 arg1, u8 arg2, u8 arg3)
// Various cases to add/remove points
if (gMovesInfo[arg2].recoil > 0)
baseFromEffect++; // Recoil moves
if (MoveHasMoveEffect(arg2, MOVE_EFFECT_RAPIDSPIN))
if (MoveHasMoveEffect(arg2, MOVE_EFFECT_RAPID_SPIN))
baseFromEffect++;
if (MoveHasMoveEffect(arg2, MOVE_EFFECT_SP_ATK_TWO_DOWN) || MoveHasMoveEffect(arg2, MOVE_EFFECT_ATK_DEF_DOWN))
baseFromEffect += 2; // Overheat, Superpower, etc.

View File

@ -1907,7 +1907,7 @@ u8 DoFieldEndTurnEffects(void)
gBattlerAttacker = gSideTimers[side].tailwindBattlerId;
if (gSideStatuses[side] & SIDE_STATUS_TAILWIND)
{
if (--gSideTimers[side].tailwindTimer == 0)
if (gSideTimers[side].tailwindTimer > 0 && --gSideTimers[side].tailwindTimer == 0)
{
gSideStatuses[side] &= ~SIDE_STATUS_TAILWIND;
BattleScriptExecute(BattleScript_TailwindEnds);
@ -2088,7 +2088,7 @@ u8 DoFieldEndTurnEffects(void)
}
break;
case ENDTURN_TRICK_ROOM:
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && --gFieldTimers.trickRoomTimer == 0)
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer > 0 && --gFieldTimers.trickRoomTimer == 0)
{
gFieldStatuses &= ~STATUS_FIELD_TRICK_ROOM;
BattleScriptExecute(BattleScript_TrickRoomEnds);
@ -2097,7 +2097,7 @@ u8 DoFieldEndTurnEffects(void)
gBattleStruct->turnCountersTracker++;
break;
case ENDTURN_WONDER_ROOM:
if (gFieldStatuses & STATUS_FIELD_WONDER_ROOM && --gFieldTimers.wonderRoomTimer == 0)
if (gFieldStatuses & STATUS_FIELD_WONDER_ROOM && gFieldTimers.wonderRoomTimer > 0 && --gFieldTimers.wonderRoomTimer == 0)
{
gFieldStatuses &= ~STATUS_FIELD_WONDER_ROOM;
BattleScriptExecute(BattleScript_WonderRoomEnds);
@ -2106,7 +2106,7 @@ u8 DoFieldEndTurnEffects(void)
gBattleStruct->turnCountersTracker++;
break;
case ENDTURN_MAGIC_ROOM:
if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM && --gFieldTimers.magicRoomTimer == 0)
if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM && gFieldTimers.magicRoomTimer > 0 && --gFieldTimers.magicRoomTimer == 0)
{
gFieldStatuses &= ~STATUS_FIELD_MAGIC_ROOM;
BattleScriptExecute(BattleScript_MagicRoomEnds);
@ -4000,78 +4000,155 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
switch (caseID)
{
case ABILITYEFFECT_SWITCH_IN_TERRAIN:
case ABILITYEFFECT_SWITCH_IN_STATUSES: // starting field/side/etc statuses with a variable
{
u8 varTerrainTimer = VarGet(B_VAR_TERRAIN_TIMER);
u8 timerVal = gBattleStruct->startingStatusTimer;
gBattleScripting.battler = battler;
if (VarGet(B_VAR_TERRAIN) & STATUS_FIELD_TERRAIN_ANY)
switch (gBattleStruct->startingStatus)
{
u16 terrainFlags = VarGet(B_VAR_TERRAIN) & STATUS_FIELD_TERRAIN_ANY; // only works for status flag (1 << 15)
if (varTerrainTimer == 0)
case STARTING_STATUS_ELECTRIC_TERRAIN:
if (!(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN))
{
gFieldStatuses = terrainFlags | STATUS_FIELD_TERRAIN_PERMANENT; // terrain is permanent
}
else
{
gFieldStatuses |= terrainFlags;
gFieldTimers.terrainTimer = varTerrainTimer;
}
switch (VarGet(B_VAR_TERRAIN) & STATUS_FIELD_TERRAIN_ANY)
{
case STATUS_FIELD_ELECTRIC_TERRAIN:
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_ELECTRIC;
break;
case STATUS_FIELD_MISTY_TERRAIN:
gFieldStatuses |= STATUS_FIELD_ELECTRIC_TERRAIN;
if (timerVal == 0)
gFieldStatuses |= STATUS_FIELD_TERRAIN_PERMANENT;
else
gFieldTimers.terrainTimer = timerVal;
effect = 2;
}
break;
case STARTING_STATUS_MISTY_TERRAIN:
if (!(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN))
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_MISTY;
break;
case STATUS_FIELD_GRASSY_TERRAIN:
gFieldStatuses |= STATUS_FIELD_MISTY_TERRAIN;
if (timerVal == 0)
gFieldStatuses |= STATUS_FIELD_TERRAIN_PERMANENT;
else
gFieldTimers.terrainTimer = timerVal;
effect = 2;
}
break;
case STARTING_STATUS_GRASSY_TERRAIN:
if (!(gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN))
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_GRASSY;
break;
case STATUS_FIELD_PSYCHIC_TERRAIN:
gFieldStatuses |= STATUS_FIELD_GRASSY_TERRAIN;
if (timerVal == 0)
gFieldStatuses |= STATUS_FIELD_TERRAIN_PERMANENT;
else
gFieldTimers.terrainTimer = timerVal;
effect = 2;
}
break;
case STARTING_STATUS_PSYCHIC_TERRAIN:
if (!(gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN))
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC;
break;
gFieldStatuses |= STATUS_FIELD_PSYCHIC_TERRAIN;
if (timerVal == 0)
gFieldStatuses |= STATUS_FIELD_TERRAIN_PERMANENT;
else
gFieldTimers.terrainTimer = timerVal;
effect = 2;
}
BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain);
effect++;
break;
case STARTING_STATUS_TRICK_ROOM:
if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM))
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_TRICK_ROOM;
gFieldStatuses |= STATUS_FIELD_TRICK_ROOM;
gBattleScripting.animArg1 = B_ANIM_TRICK_ROOM;
if (timerVal == 0)
gFieldTimers.trickRoomTimer = 0; // infinite
else
gFieldTimers.trickRoomTimer = 5;
effect = 1;
}
break;
case STARTING_STATUS_MAGIC_ROOM:
if (!(gFieldStatuses & STATUS_FIELD_MAGIC_ROOM))
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_MAGIC_ROOM;
gFieldStatuses |= STATUS_FIELD_MAGIC_ROOM;
gBattleScripting.animArg1 = B_ANIM_MAGIC_ROOM;
if (timerVal == 0)
gFieldTimers.magicRoomTimer = 0; // infinite
else
gFieldTimers.magicRoomTimer = 5;
effect = 1;
}
break;
case STARTING_STATUS_WONDER_ROOM:
if (!(gFieldStatuses & STATUS_FIELD_WONDER_ROOM))
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_WONDER_ROOM;
gFieldStatuses |= STATUS_FIELD_WONDER_ROOM;
gBattleScripting.animArg1 = B_ANIM_WONDER_ROOM;
if (timerVal == 0)
gFieldTimers.wonderRoomTimer = 0; // infinite
else
gFieldTimers.wonderRoomTimer = 5;
effect = 1;
}
break;
case STARTING_STATUS_TAILWIND_PLAYER:
if (!(gSideStatuses[B_SIDE_PLAYER] & SIDE_STATUS_TAILWIND))
{
gBattlerAttacker = B_POSITION_PLAYER_LEFT;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_TAILWIND_PLAYER;
gSideStatuses[B_SIDE_PLAYER] |= SIDE_STATUS_TAILWIND;
gBattleScripting.animArg1 = B_ANIM_TAILWIND;
if (timerVal == 0)
gSideTimers[B_SIDE_PLAYER].tailwindTimer = 0; // infinite
else
gSideTimers[B_SIDE_PLAYER].tailwindTimer = 5;
effect = 1;
}
break;
case STARTING_STATUS_TAILWIND_OPPONENT:
if (!(gSideStatuses[B_SIDE_OPPONENT] & SIDE_STATUS_TAILWIND))
{
gBattlerAttacker = B_POSITION_OPPONENT_LEFT;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_TAILWIND_OPPONENT;
gSideStatuses[B_SIDE_OPPONENT] |= SIDE_STATUS_TAILWIND;
gBattleScripting.animArg1 = B_ANIM_TAILWIND;
if (timerVal == 0)
gSideTimers[B_SIDE_OPPONENT].tailwindTimer = 0; // infinite
else
gSideTimers[B_SIDE_OPPONENT].tailwindTimer = 5;
effect = 1;
}
break;
}
else if (B_THUNDERSTORM_TERRAIN == TRUE
&& GetCurrentWeather() == WEATHER_RAIN_THUNDERSTORM
&& !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN))
{
// overworld weather started rain, so just do electric terrain anim
if (varTerrainTimer == 0)
{
gFieldStatuses = (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT);
}
else
{
gFieldStatuses |= STATUS_FIELD_ELECTRIC_TERRAIN;
gFieldTimers.terrainTimer = varTerrainTimer;
}
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_ELECTRIC;
if (effect == 1)
BattleScriptPushCursorAndCallback(BattleScript_OverworldStatusStarts);
else if (effect == 2)
BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain);
effect++;
}
else if (B_FOG_TERRAIN == TRUE
&& (GetCurrentWeather() == WEATHER_FOG_HORIZONTAL || GetCurrentWeather() == WEATHER_FOG_DIAGONAL)
&& !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN))
{
if (varTerrainTimer == 0)
{
gFieldStatuses = (STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT);
}
else
{
gFieldStatuses |= STATUS_FIELD_ELECTRIC_TERRAIN;
gFieldTimers.terrainTimer = varTerrainTimer;
}
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_MISTY;
BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain);
effect++;
}
}
break;
case ABILITYEFFECT_SWITCH_IN_TERRAIN: // terrain starting from overworld weather
if (B_THUNDERSTORM_TERRAIN == TRUE
&& !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN)
&& GetCurrentWeather() == WEATHER_RAIN_THUNDERSTORM)
{
// overworld weather started rain, so just do electric terrain anim
gFieldStatuses = (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_ELECTRIC;
BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain);
effect++;
}
else if (B_FOG_TERRAIN == TRUE
&& (GetCurrentWeather() == WEATHER_FOG_HORIZONTAL || GetCurrentWeather() == WEATHER_FOG_DIAGONAL)
&& !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN))
{
gFieldStatuses = (STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_MISTY;
BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain);
effect++;
}
break;
case ABILITYEFFECT_SWITCH_IN_WEATHER:

View File

@ -1052,12 +1052,6 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
.battleTvScore = 1,
},
[EFFECT_TEETER_DANCE] =
{
.battleScript = BattleScript_EffectTeeterDance,
.battleTvScore = 6,
},
[EFFECT_HIT_ESCAPE] =
{
.battleScript = BattleScript_EffectHitEscape,
@ -2200,12 +2194,14 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
{
.battleScript = BattleScript_EffectShedTail,
.battleTvScore = 0, // TODO: Assign points
.encourageEncore = TRUE,
},
[EFFECT_UPPER_HAND] =
{
.battleScript = BattleScript_EffectUpperHand,
.battleTvScore = 0, // TODO: Assign points
.encourageEncore = TRUE,
},
[EFFECT_DRAGON_CHEER] =
@ -2220,4 +2216,11 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
.battleScript = BattleScript_EffectHit,
.battleTvScore = 0, // TODO: Assign points
},
[EFFECT_TIDY_UP] =
{
.battleScript = BattleScript_EffectTidyUp,
.battleTvScore = 0, // TODO: Assign points
.encourageEncore = TRUE,
},
};

View File

@ -17,5 +17,4 @@ const struct Trainer gBattlePartners[] = {
.trainerPic = TRAINER_BACK_PIC_STEVEN,
.trainerName = _("STEVEN"),
},
};

View File

@ -15778,9 +15778,9 @@ const u32 gObjectEventPic_Substitute[] = INCBIN_COMP("graphics/pokemon/question_
// const u8 gMonFootprint_Squawkabilly[] = INCBIN_U8("graphics/pokemon/squawkabilly/footprint.1bpp");
#endif //P_FOOTPRINTS
const u32 gMonPalette_SquawkabillyGreenPlumage[] = INCBIN_U32("graphics/pokemon/squawkabilly/green_plumage/normal.gbapal.lz");
const u32 gMonShinyPalette_SquawkabillyGreenPlumage[] = INCBIN_U32("graphics/pokemon/squawkabilly/green_plumage/shiny.gbapal.lz");
const u8 gMonIcon_SquawkabillyGreenPlumage[] = INCBIN_U8("graphics/pokemon/squawkabilly/green_plumage/icon.4bpp");
const u32 gMonPalette_SquawkabillyGreenPlumage[] = INCBIN_U32("graphics/pokemon/squawkabilly/normal.gbapal.lz");
const u32 gMonShinyPalette_SquawkabillyGreenPlumage[] = INCBIN_U32("graphics/pokemon/squawkabilly/shiny.gbapal.lz");
const u8 gMonIcon_SquawkabillyGreenPlumage[] = INCBIN_U8("graphics/pokemon/squawkabilly/icon.4bpp");
#if OW_FOLLOWERS_ENABLED
// const u32 gObjectEventPic_SquawkabillyGreenPlumage[] = INCBIN_COMP("graphics/pokemon/squawkabilly/green_plumage/follower.4bpp");
#endif //OW_FOLLOWERS_ENABLED
@ -16419,11 +16419,11 @@ const u32 gObjectEventPic_Substitute[] = INCBIN_COMP("graphics/pokemon/question_
#endif //P_FAMILY_DONDOZO
#if P_FAMILY_TATSUGIRI
const u32 gMonFrontPic_TatsugiriCurly[] = INCBIN_U32("graphics/pokemon/tatsugiri/curly/front.4bpp.lz");
const u32 gMonPalette_TatsugiriCurly[] = INCBIN_U32("graphics/pokemon/tatsugiri/curly/normal.gbapal.lz");
const u32 gMonBackPic_TatsugiriCurly[] = INCBIN_U32("graphics/pokemon/tatsugiri/curly/back.4bpp.lz");
const u32 gMonShinyPalette_TatsugiriCurly[] = INCBIN_U32("graphics/pokemon/tatsugiri/curly/shiny.gbapal.lz");
const u8 gMonIcon_TatsugiriCurly[] = INCBIN_U8("graphics/pokemon/tatsugiri/curly/icon.4bpp");
const u32 gMonFrontPic_TatsugiriCurly[] = INCBIN_U32("graphics/pokemon/tatsugiri/front.4bpp.lz");
const u32 gMonPalette_TatsugiriCurly[] = INCBIN_U32("graphics/pokemon/tatsugiri/normal.gbapal.lz");
const u32 gMonBackPic_TatsugiriCurly[] = INCBIN_U32("graphics/pokemon/tatsugiri/back.4bpp.lz");
const u32 gMonShinyPalette_TatsugiriCurly[] = INCBIN_U32("graphics/pokemon/tatsugiri/shiny.gbapal.lz");
const u8 gMonIcon_TatsugiriCurly[] = INCBIN_U8("graphics/pokemon/tatsugiri/icon.4bpp");
#if P_FOOTPRINTS
// const u8 gMonFootprint_Tatsugiri[] = INCBIN_U8("graphics/pokemon/tatsugiri/footprint.1bpp");
#endif //P_FOOTPRINTS

View File

@ -1847,6 +1847,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_SPECIAL,
.zMove = { .powerOverride = 120 },
.ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_3 || B_UPDATED_MOVE_FLAGS == GEN_4),
.healingMove = B_HEAL_BLOCKING >= GEN_6,
.contestEffect = CONTEST_EFFECT_BADLY_STARTLE_FRONT_MON,
@ -5638,7 +5639,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.category = DAMAGE_CATEGORY_PHYSICAL,
.makesContact = TRUE,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_RAPIDSPIN,
.moveEffect = MOVE_EFFECT_RAPID_SPIN,
.self = TRUE,
}
#if B_SPEED_BUFFING_RAPID_SPIN >= GEN_8
@ -7313,7 +7314,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.description = COMPOUND_STRING(
"Confuses all Pokémon on\n"
"the scene."),
.effect = EFFECT_TEETER_DANCE,
.effect = EFFECT_CONFUSE,
.power = 0,
.type = TYPE_NORMAL,
.accuracy = 100,
@ -7649,6 +7650,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_SPECIAL,
.zMove = { .powerOverride = 160 },
.ballisticMove = TRUE,
.contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING,
.contestCategory = CONTEST_CATEGORY_SMART,
@ -12247,6 +12249,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_SPECIAL,
.zMove = { .powerOverride = 160 },
.argument = STATUS1_ANY,
.contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE,
.contestCategory = CONTEST_CATEGORY_SMART,
@ -13114,6 +13117,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.zMove = { .powerOverride = 180 },
.makesContact = TRUE,
.strikeCount = 2,
.contestEffect = CONTEST_EFFECT_REPETITION_NOT_BORING,
@ -13449,6 +13453,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.zMove = { .powerOverride = 220 },
.makesContact = TRUE,
.metronomeBanned = TRUE,
.additionalEffects = ADDITIONAL_EFFECTS({
@ -13516,6 +13521,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.zMove = { .powerOverride = 170 },
.argument = TYPE_FLYING,
.makesContact = TRUE,
.minimizeDoubleDamage = TRUE,
@ -15021,6 +15027,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 2,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = MOVE_FIRST_IMPRESSION,
.makesContact = TRUE,
.contestEffect = CONTEST_EFFECT_BETTER_IF_FIRST,
.contestCategory = CONTEST_CATEGORY_COOL,
@ -18927,7 +18934,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.sheerForceBoost = TRUE,
.makesContact = TRUE,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_RAPIDSPIN,
.moveEffect = MOVE_EFFECT_RAPID_SPIN,
.self = TRUE,
},
{
@ -19200,7 +19207,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.description = COMPOUND_STRING(
"User tidies up hazards and\n"
"raises its Attack and Speed."),
.effect = EFFECT_PLACEHOLDER, // EFFECT_TIDY_UP
.effect = EFFECT_TIDY_UP,
.power = 0,
.type = TYPE_NORMAL,
.accuracy = 0,

View File

@ -2,7 +2,7 @@ static const struct TrainerMon sParty_StevenPartner[] = {
{
.species = SPECIES_METANG,
.lvl = 42,
.nature = TRAINER_PARTY_NATURE(NATURE_BRAVE),
.nature = NATURE_BRAVE,
.iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31),
.ev = TRAINER_PARTY_EVS(0, 252, 252, 0, 6, 0),
.moves = {MOVE_LIGHT_SCREEN, MOVE_PSYCHIC, MOVE_REFLECT, MOVE_METAL_CLAW},
@ -10,7 +10,7 @@ static const struct TrainerMon sParty_StevenPartner[] = {
{
.species = SPECIES_SKARMORY,
.lvl = 43,
.nature = TRAINER_PARTY_NATURE(NATURE_IMPISH),
.nature = NATURE_IMPISH,
.iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31),
.ev = TRAINER_PARTY_EVS(252, 0, 0, 0, 6, 252),
.moves = {MOVE_TOXIC, MOVE_AERIAL_ACE, MOVE_PROTECT, MOVE_STEEL_WING},
@ -18,7 +18,7 @@ static const struct TrainerMon sParty_StevenPartner[] = {
{
.species = SPECIES_AGGRON,
.lvl = 44,
.nature = TRAINER_PARTY_NATURE(NATURE_ADAMANT),
.nature = NATURE_ADAMANT,
.iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31),
.ev = TRAINER_PARTY_EVS(0, 252, 0, 0, 252, 6),
.moves = {MOVE_THUNDER, MOVE_PROTECT, MOVE_SOLAR_BEAM, MOVE_DRAGON_CLAW},

View File

@ -3125,7 +3125,7 @@ const struct SpeciesInfo gSpeciesInfoGen5[] =
.frontAnimFrames = sAnims_Basculegion, \
.frontPicYOffset = 0, \
.enemyMonElevation = 5, \
.backPicYOffset = 0, \
.backPicYOffset = 8, \
LEARNSETS(Basculegion), \
.formSpeciesIdTable = sBasculegionFormSpeciesIdTable
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,

View File

@ -458,8 +458,8 @@ const struct SpeciesInfo gSpeciesInfoGen6[] =
.genderRatio = MON_MALE,
.eggGroups = MON_EGG_GROUPS(EGG_GROUP_NO_EGGS_DISCOVERED),
.abilities = { ABILITY_BATTLE_BOND, ABILITY_NONE, ABILITY_NONE },
.frontAnimId = ANIM_FLICKER_INCREASING,
.backAnimId = BACK_ANIM_V_STRETCH,
.frontAnimId = ANIM_V_STRETCH,
.backAnimId = BACK_ANIM_JOLT_RIGHT,
.formChangeTable = sGreninjaBattleBondFormChangeTable,
},
@ -488,7 +488,7 @@ const struct SpeciesInfo gSpeciesInfoGen6[] =
.backPicYOffset = 11,
PALETTES(GreninjaAsh),
ICON(GreninjaAsh, 0),
.frontAnimId = ANIM_FLICKER_INCREASING,
.frontAnimId = ANIM_V_STRETCH,
.backAnimId = BACK_ANIM_SHAKE_GLOW_BLUE,
.formChangeTable = sGreninjaBattleBondFormChangeTable,
},

View File

@ -402,12 +402,12 @@ void Overworld_ResetStateAfterDigEscRope(void)
#if B_RESET_FLAGS_VARS_AFTER_WHITEOUT == TRUE
void Overworld_ResetBattleFlagsAndVars(void)
{
#if B_VAR_TERRAIN != 0
VarSet(B_VAR_TERRAIN, 0);
#if B_VAR_STARTING_STATUS != 0
VarSet(B_VAR_STARTING_STATUS, 0);
#endif
#if B_VAR_TERRAIN_TIMER != 0
VarSet(B_VAR_TERRAIN_TIMER, 0);
#if B_VAR_STARTING_STATUS_TIMER != 0
VarSet(B_VAR_STARTING_STATUS_TIMER, 0);
#endif
#if B_VAR_WILD_AI_FLAGS != 0

View File

@ -274,8 +274,19 @@ static void Task_HandleCaughtMonPageInput(u8);
static void Task_ExitCaughtMonPage(u8);
static void SpriteCB_SlideCaughtMonToCenter(struct Sprite *sprite);
static void PrintMonInfo(u32 num, u32, u32 owned, u32 newEntry);
static void PrintMonHeight(u16 height, u8 left, u8 top);
static void PrintMonWeight(u16 weight, u8 left, u8 top);
static u32 GetMeasurementTextPositions(u32 textElement);
static void PrintUnknownMonMeasurements(void);
static u8* GetUnknownMonHeightString(void);
static u8* GetUnknownMonWeightString(void);
static u8* ReplaceDecimalSeparator(const u8* originalString);
static void PrintOwnedMonMeasurements(u16 species);
static void PrintOwnedMonHeight(u16 species);
static void PrintOwnedMonWeight(u16 species);
static u8* ConvertMonHeightToImperialString(u32 height);
static u8* ConvertMonHeightToMetricString(u32 height);
static u8* ConvertMonWeightToImperialString(u32 weight);
static u8* ConvertMonWeightToMetricString(u32 weight);
static u8* ConvertMeasurementToMetricString(u32 num, u32* index);
static void ResetOtherVideoRegisters(u16);
static u8 PrintCryScreenSpeciesName(u8, u16, u8, u8);
static void PrintDecimalNum(u8 windowId, u16 num, u8 left, u8 top);
@ -4141,7 +4152,7 @@ static void PrintMonInfo(u32 num, u32 value, u32 owned, u32 newEntry)
const u8 *name;
const u8 *category;
const u8 *description;
u8 digitCount = (NATIONAL_DEX_COUNT > 999 && IsNationalPokedexEnabled()) ? 4 : 3;
u8 digitCount = (NATIONAL_DEX_COUNT > 999 && IsNationalPokedexEnabled()) ? 4 : 3;
if (newEntry)
PrintInfoScreenText(gText_PokedexRegistration, GetStringCenterAlignXOffset(FONT_NORMAL, gText_PokedexRegistration, DISPLAY_WIDTH), 0);
@ -4169,18 +4180,7 @@ static void PrintMonInfo(u32 num, u32 value, u32 owned, u32 newEntry)
category = gText_5MarksPokemon;
}
PrintInfoScreenText(category, 0x64, 0x29);
PrintInfoScreenText(gText_HTHeight, 0x60, 0x39);
PrintInfoScreenText(gText_WTWeight, 0x60, 0x49);
if (owned)
{
PrintMonHeight(GetSpeciesHeight(species), 0x81, 0x39);
PrintMonWeight(GetSpeciesWeight(species), 0x81, 0x49);
}
else
{
PrintInfoScreenText(gText_UnkHeight, 0x81, 0x39);
PrintInfoScreenText(gText_UnkWeight, 0x81, 0x49);
}
PrintMonMeasurements(species,owned);
if (owned)
description = GetSpeciesPokedexDescription(species);
else
@ -4188,95 +4188,289 @@ static void PrintMonInfo(u32 num, u32 value, u32 owned, u32 newEntry)
PrintInfoScreenText(description, GetStringCenterAlignXOffset(FONT_NORMAL, description, DISPLAY_WIDTH), 95);
}
static void PrintMonHeight(u16 height, u8 left, u8 top)
void PrintMonMeasurements(u16 species, u32 owned)
{
u8 buffer[16];
u32 inches, feet;
u8 i = 0;
u32 x = GetMeasurementTextPositions(DEX_HEADER_X);
u32 yTop = GetMeasurementTextPositions(DEX_Y_TOP);
u32 yBottom = GetMeasurementTextPositions(DEX_Y_BOTTOM);
inches = (height * 10000) / 254;
PrintInfoScreenText(gText_HTHeight, x, yTop);
PrintInfoScreenText(gText_WTWeight, x, yBottom);
if (owned)
PrintOwnedMonMeasurements(species);
else
PrintUnknownMonMeasurements();
}
static u32 GetMeasurementTextPositions(u32 textElement)
{
if (!POKEDEX_PLUS_HGSS)
return textElement;
switch(textElement)
{
case DEX_HEADER_X:
return (DEX_HEADER_X + DEX_HGSS_HEADER_X_PADDING);
case DEX_Y_TOP:
return (DEX_Y_TOP + DEX_HGSS_Y_TOP_PADDING);
case DEX_Y_BOTTOM:
return (DEX_Y_BOTTOM + DEX_HGSS_Y_BOTTOM_PADDING);
default:
case DEX_MEASUREMENT_X:
return (DEX_MEASUREMENT_X + DEX_HGSS_MEASUREMENT_X_PADDING);
}
}
static void PrintUnknownMonMeasurements(void)
{
u8* heightString = GetUnknownMonHeightString();
u8* weightString = GetUnknownMonWeightString();
u32 x = GetMeasurementTextPositions(DEX_MEASUREMENT_X);
u32 yTop = GetMeasurementTextPositions(DEX_Y_TOP);
u32 yBottom = GetMeasurementTextPositions(DEX_Y_BOTTOM);
PrintInfoScreenText(heightString, x, yTop);
PrintInfoScreenText(weightString, x, yBottom);
Free(heightString);
Free(weightString);
}
static u8* GetUnknownMonHeightString(void)
{
if (UNITS == UNITS_IMPERIAL)
return ReplaceDecimalSeparator(gText_UnkHeight);
else
return ReplaceDecimalSeparator(gText_UnkHeightMetric);
}
static u8* GetUnknownMonWeightString(void)
{
if (UNITS == UNITS_IMPERIAL)
return ReplaceDecimalSeparator(gText_UnkWeight);
else
return ReplaceDecimalSeparator(gText_UnkWeightMetric);
}
static u8* ReplaceDecimalSeparator(const u8* originalString)
{
bool32 replaced = FALSE;
u32 length = StringLength(originalString), i;
u8* modifiedString = Alloc(WEIGHT_HEIGHT_STR_MEM);
for (i = 0; i < length; i++)
{
if ((originalString[i] != CHAR_PERIOD) || replaced)
{
modifiedString[i] = originalString[i];
continue;
}
modifiedString[i] = CHAR_DEC_SEPARATOR;
replaced = TRUE;
}
modifiedString[length] = EOS;
return modifiedString;
}
static void PrintOwnedMonMeasurements(u16 species)
{
PrintOwnedMonHeight(species);
PrintOwnedMonWeight(species);
}
static void PrintOwnedMonHeight(u16 species)
{
u32 height = GetSpeciesHeight(species);
u8* heightString;
u32 x = GetMeasurementTextPositions(DEX_MEASUREMENT_X);
u32 yTop = GetMeasurementTextPositions(DEX_Y_TOP);
heightString = ConvertMonHeightToString(height);
PrintInfoScreenText(heightString, x, yTop);
Free(heightString);
}
u8* ConvertMonHeightToString(u32 height)
{
if (UNITS == UNITS_IMPERIAL)
return ConvertMonHeightToImperialString(height);
else
return ConvertMonHeightToMetricString(height);
}
static void PrintOwnedMonWeight(u16 species)
{
u32 weight = GetSpeciesWeight(species);
u8* weightString;
u32 x = GetMeasurementTextPositions(DEX_MEASUREMENT_X);
u32 yBottom = GetMeasurementTextPositions(DEX_Y_BOTTOM);
weightString = ConvertMonWeightToString(weight);
PrintInfoScreenText(weightString, x, yBottom);
Free(weightString);
}
u8* ConvertMonWeightToString(u32 weight)
{
if (UNITS == UNITS_IMPERIAL)
return ConvertMonWeightToImperialString(weight);
else
return ConvertMonWeightToMetricString(weight);
}
static u8* ConvertMonHeightToImperialString(u32 height)
{
u8* heightString = Alloc(WEIGHT_HEIGHT_STR_MEM);
u32 inches, feet, index = 0;
inches = (height * 10000) / CM_PER_INCH_FACTOR;
if (inches % 10 >= 5)
inches += 10;
feet = inches / 120;
inches = (inches - (feet * 120)) / 10;
feet = inches / INCHES_IN_FOOT_FACTOR;
inches = (inches - (feet * INCHES_IN_FOOT_FACTOR)) / 10;
buffer[i++] = EXT_CTRL_CODE_BEGIN;
buffer[i++] = EXT_CTRL_CODE_CLEAR_TO;
heightString[index++] = EXT_CTRL_CODE_BEGIN;
heightString[index++] = EXT_CTRL_CODE_CLEAR_TO;
if (feet / 10 == 0)
{
buffer[i++] = 18;
buffer[i++] = feet + CHAR_0;
heightString[index++] = INCHES_IN_ONE_AND_HALF_FOOT;
heightString[index++] = feet + CHAR_0;
}
else
{
buffer[i++] = 12;
buffer[i++] = feet / 10 + CHAR_0;
buffer[i++] = (feet % 10) + CHAR_0;
heightString[index++] = INCHES_IN_FOOT;
heightString[index++] = feet / 10 + CHAR_0;
heightString[index++] = (feet % 10) + CHAR_0;
}
buffer[i++] = CHAR_SGL_QUOTE_RIGHT;
buffer[i++] = (inches / 10) + CHAR_0;
buffer[i++] = (inches % 10) + CHAR_0;
buffer[i++] = CHAR_DBL_QUOTE_RIGHT;
buffer[i++] = EOS;
PrintInfoScreenText(buffer, left, top);
heightString[index++] = CHAR_SGL_QUOTE_RIGHT;
heightString[index++] = (inches / 10) + CHAR_0;
heightString[index++] = (inches % 10) + CHAR_0;
heightString[index++] = CHAR_DBL_QUOTE_RIGHT;
heightString[index++] = EOS;
return heightString;
}
static void PrintMonWeight(u16 weight, u8 left, u8 top)
static u8* ConvertMonHeightToMetricString(u32 height)
{
u8 buffer[16];
bool8 output;
u8 i;
u32 lbs = (weight * 100000) / 4536;
u32 index = 0;
u8* heightString = ConvertMeasurementToMetricString(height, &index);
heightString[index++] = CHAR_m;
heightString[index++] = EOS;
return heightString;
}
static u8* ConvertMonWeightToImperialString(u32 weight)
{
u8* weightString = Alloc(WEIGHT_HEIGHT_STR_MEM);
bool32 output = FALSE;
u32 index = 0, lbs = (weight * 100000) / DECAGRAMS_IN_POUND;
if (lbs % 10u >= 5)
lbs += 10;
i = 0;
output = FALSE;
if ((buffer[i] = (lbs / 100000) + CHAR_0) == CHAR_0 && !output)
if ((weightString[index] = (lbs / 100000) + CHAR_0) == CHAR_0 && !output)
{
buffer[i++] = CHAR_SPACER;
weightString[index++] = CHAR_SPACER;
}
else
{
output = TRUE;
i++;
index++;
}
lbs %= 100000;
if ((buffer[i] = (lbs / 10000) + CHAR_0) == CHAR_0 && !output)
if ((weightString[index] = (lbs / 10000) + CHAR_0) == CHAR_0 && !output)
{
buffer[i++] = CHAR_SPACER;
weightString[index++] = CHAR_SPACER;
}
else
{
output = TRUE;
i++;
index++;
}
lbs %= 10000;
if ((buffer[i] = (lbs / 1000) + CHAR_0) == CHAR_0 && !output)
if ((weightString[index] = (lbs / 1000) + CHAR_0) == CHAR_0 && !output)
{
buffer[i++] = CHAR_SPACER;
weightString[index++] = CHAR_SPACER;
}
else
{
output = TRUE;
i++;
index++;
}
lbs %= 1000;
buffer[i++] = (lbs / 100) + CHAR_0;
weightString[index++] = (lbs / 100) + CHAR_0;
lbs %= 100;
buffer[i++] = CHAR_PERIOD;
buffer[i++] = (lbs / 10) + CHAR_0;
buffer[i++] = CHAR_SPACE;
buffer[i++] = CHAR_l;
buffer[i++] = CHAR_b;
buffer[i++] = CHAR_s;
buffer[i++] = CHAR_PERIOD;
buffer[i++] = EOS;
PrintInfoScreenText(buffer, left, top);
weightString[index++] = CHAR_DEC_SEPARATOR;
weightString[index++] = (lbs / 10) + CHAR_0;
weightString[index++] = CHAR_SPACE;
weightString[index++] = CHAR_l;
weightString[index++] = CHAR_b;
weightString[index++] = CHAR_s;
weightString[index++] = CHAR_PERIOD;
weightString[index++] = EOS;
return weightString;
}
static u8* ConvertMonWeightToMetricString(u32 weight)
{
u32 index = 0;
u8* weightString = ConvertMeasurementToMetricString(weight, &index);
weightString[index++] = CHAR_k;
weightString[index++] = CHAR_g;
weightString[index++] = CHAR_PERIOD;
weightString[index++] = EOS;
return weightString;
}
static u8* ConvertMeasurementToMetricString(u32 num, u32* index)
{
u8* string = Alloc(WEIGHT_HEIGHT_STR_MEM);
bool32 outputted = FALSE;
u32 result;
result = num / 1000;
if (result == 0)
{
string[(*index)++] = CHAR_SPACER;
outputted = FALSE;
}
else
{
string[(*index)++] = CHAR_0 + result;
outputted = TRUE;
}
result = (num % 1000) / 100;
if (result == 0 && !outputted)
{
string[(*index)++] = CHAR_SPACER;
outputted = FALSE;
}
else
{
string[(*index)++] = CHAR_0 + result;
outputted = TRUE;
}
string[(*index)++] = CHAR_0 + ((num % 1000) % 100) / 10;
string[(*index)++] = CHAR_DEC_SEPARATOR;
string[(*index)++] = CHAR_0 + ((num % 1000) % 100) % 10;
string[(*index)++] = CHAR_SPACE;
return string;
}
s8 GetSetPokedexFlag(u16 nationalDexNo, u8 caseID)

View File

@ -536,8 +536,6 @@ static void Task_HandleCaughtMonPageInput(u8);
static void Task_ExitCaughtMonPage(u8);
static void SpriteCB_SlideCaughtMonToCenter(struct Sprite *sprite);
static void PrintMonInfo(u32 num, u32, u32 owned, u32 newEntry);
static void PrintMonHeight(u16 height, u8 left, u8 top);
static void PrintMonWeight(u16 weight, u8 left, u8 top);
static void ResetOtherVideoRegisters(u16);
static u8 PrintCryScreenSpeciesName(u8, u16, u8, u8);
static void PrintDecimalNum(u8 windowId, u16 num, u8 left, u8 top);
@ -4487,18 +4485,7 @@ static void PrintMonInfo(u32 num, u32 value, u32 owned, u32 newEntry)
category = gText_5MarksPokemon;
}
PrintInfoScreenText(category, 123, 31);
PrintInfoScreenText(gText_HTHeight, 155, 64);
PrintInfoScreenText(gText_WTWeight, 155, 77);
if (owned)
{
PrintMonHeight(GetSpeciesHeight(species), 180, 64);
PrintMonWeight(GetSpeciesWeight(species), 180, 77);
}
else
{
PrintInfoScreenText(gText_UnkHeight, 180, 64);
PrintInfoScreenText(gText_UnkWeight, 180, 77);
}
PrintMonMeasurements(species,owned);
if (owned)
description = GetSpeciesPokedexDescription(species);
else
@ -4510,97 +4497,6 @@ static void PrintMonInfo(u32 num, u32 value, u32 owned, u32 newEntry)
PrintCurrentSpeciesTypeInfo(newEntry, species);
}
static void PrintMonHeight(u16 height, u8 left, u8 top)
{
u8 buffer[16];
u32 inches, feet;
u8 i = 0;
inches = (height * 10000) / 254;
if (inches % 10 >= 5)
inches += 10;
feet = inches / 120;
inches = (inches - (feet * 120)) / 10;
buffer[i++] = EXT_CTRL_CODE_BEGIN;
buffer[i++] = EXT_CTRL_CODE_CLEAR_TO;
if (feet / 10 == 0)
{
buffer[i++] = 18;
buffer[i++] = feet + CHAR_0;
}
else
{
buffer[i++] = 12;
buffer[i++] = feet / 10 + CHAR_0;
buffer[i++] = (feet % 10) + CHAR_0;
}
buffer[i++] = CHAR_SGL_QUOTE_RIGHT;
buffer[i++] = (inches / 10) + CHAR_0;
buffer[i++] = (inches % 10) + CHAR_0;
buffer[i++] = CHAR_DBL_QUOTE_RIGHT;
buffer[i++] = EOS;
PrintInfoScreenText(buffer, left, top);
}
static void PrintMonWeight(u16 weight, u8 left, u8 top)
{
u8 buffer[16];
bool8 output;
u8 i;
u32 lbs = (weight * 100000) / 4536;
if (lbs % 10u >= 5)
lbs += 10;
i = 0;
output = FALSE;
if ((buffer[i] = (lbs / 100000) + CHAR_0) == CHAR_0 && !output)
{
buffer[i++] = CHAR_SPACER;
}
else
{
output = TRUE;
i++;
}
lbs %= 100000;
if ((buffer[i] = (lbs / 10000) + CHAR_0) == CHAR_0 && !output)
{
buffer[i++] = CHAR_SPACER;
}
else
{
output = TRUE;
i++;
}
lbs %= 10000;
if ((buffer[i] = (lbs / 1000) + CHAR_0) == CHAR_0 && !output)
{
buffer[i++] = CHAR_SPACER;
}
else
{
output = TRUE;
i++;
}
lbs %= 1000;
buffer[i++] = (lbs / 100) + CHAR_0;
lbs %= 100;
buffer[i++] = CHAR_PERIOD;
buffer[i++] = (lbs / 10) + CHAR_0;
buffer[i++] = CHAR_SPACE;
buffer[i++] = CHAR_l;
buffer[i++] = CHAR_b;
buffer[i++] = CHAR_s;
buffer[i++] = CHAR_PERIOD;
buffer[i++] = EOS;
PrintInfoScreenText(buffer, left, top);
}
// Unused in the English version, used to print height/weight in versions which use metric system.
static void UNUSED PrintDecimalNum(u8 windowId, u16 num, u8 left, u8 top)
{
@ -5294,7 +5190,7 @@ static bool8 CalculateMoves(void)
if (j >= NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES)
{
numTutorMoves++;
sStatsMoves[movesTotal] = move;
movesTotal++;
}

View File

@ -425,7 +425,7 @@ static const u8 sBackAnimationIds[] =
[(BACK_ANIM_SHAKE_FLASH_YELLOW - 1) * 3] = ANIM_SHAKE_FLASH_YELLOW_FAST, ANIM_SHAKE_FLASH_YELLOW, ANIM_SHAKE_FLASH_YELLOW_SLOW,
[(BACK_ANIM_SHAKE_GLOW_RED - 1) * 3] = ANIM_SHAKE_GLOW_RED_FAST, ANIM_SHAKE_GLOW_RED, ANIM_SHAKE_GLOW_RED_SLOW,
[(BACK_ANIM_SHAKE_GLOW_GREEN - 1) * 3] = ANIM_SHAKE_GLOW_GREEN_FAST, ANIM_SHAKE_GLOW_GREEN, ANIM_SHAKE_GLOW_GREEN_SLOW,
[(BACK_ANIM_SHAKE_GLOW_BLUE - 1) * 3] = ANIM_SHAKE_GLOW_BLUE_FAST, ANIM_SHAKE_GLOW_BLUE, ANIM_SHAKE_GLOW_BLUE_SLOW,
[(BACK_ANIM_SHAKE_GLOW_BLUE - 1) * 3] = ANIM_SHAKE_GLOW_BLUE_FAST, ANIM_SHAKE_GLOW_BLUE, ANIM_SHAKE_GLOW_BLUE_SLOW,
};
static const u8 sBackAnimNatureModTable[NUM_NATURES] =

View File

@ -8,6 +8,7 @@
#include "text.h"
#define DEFAULT_MAX_SIZE 0x8000 // was 0x8100 in Ruby/Sapphire
static u8* ReturnHeightStringNoWhitespace(u32 size);
struct UnknownStruct
{
@ -47,8 +48,6 @@ static const u8 sGiftRibbonsMonDataIds[GIFT_RIBBONS_COUNT - 4] =
extern const u8 gText_DecimalPoint[];
extern const u8 gText_Marco[];
#define CM_PER_INCH 2.54
static u32 GetMonSizeHash(struct Pokemon *pkmn)
{
u16 personality = GetMonData(pkmn, MON_DATA_PERSONALITY);
@ -84,7 +83,7 @@ static u32 GetMonSize(u16 species, u16 b)
u32 height;
u32 var;
height = GetSpeciesWeight(species);
height = GetSpeciesHeight(species);
var = TranslateBigMonSizeTableIndex(b);
unk0 = sBigMonSizeTable[var].unk0;
unk2 = sBigMonSizeTable[var].unk2;
@ -95,14 +94,24 @@ static u32 GetMonSize(u16 species, u16 b)
static void FormatMonSizeRecord(u8 *string, u32 size)
{
#ifdef UNITS_IMPERIAL
//Convert size from centimeters to inches
size = (f64)(size * 10) / (CM_PER_INCH * 10);
#endif
size = (f64)(size / 100);
StringCopy(string,ReturnHeightStringNoWhitespace(size));
}
string = ConvertIntToDecimalStringN(string, size / 10, STR_CONV_MODE_LEFT_ALIGN, 8);
string = StringAppend(string, gText_DecimalPoint);
ConvertIntToDecimalStringN(string, size % 10, STR_CONV_MODE_LEFT_ALIGN, 1);
static u8* ReturnHeightStringNoWhitespace(u32 size)
{
u8* heightStr = ConvertMonHeightToString(size);
u32 length = StringLength(heightStr);
u32 i = 0, j = 0;
while (i < length && !(heightStr[i] >= CHAR_0 && heightStr[i] <= CHAR_9))
i++;
while (i < length)
heightStr[j++] = heightStr[i++];
heightStr[j] = EOS;
return heightStr;
}
static u8 CompareMonSize(u16 species, u16 *sizeRecord)

View File

@ -345,7 +345,11 @@ u32 ScriptGiveMonParameterized(u16 species, u8 level, u16 item, u8 ball, u8 natu
}
// ability
if (abilityNum >= NUM_ABILITY_SLOTS || GetAbilityBySpecies(species, abilityNum) == ABILITY_NONE)
if (abilityNum == NUM_ABILITY_PERSONALITY)
{
abilityNum = GetMonData(&mon, MON_DATA_PERSONALITY) & 1;
}
else if (abilityNum > NUM_NORMAL_ABILITY_SLOTS || GetAbilityBySpecies(species, abilityNum) == ABILITY_NONE)
{
do {
abilityNum = Random() % NUM_ABILITY_SLOTS; // includes hidden abilities
@ -410,7 +414,7 @@ u32 ScriptGiveMon(u16 species, u8 level, u16 item)
MAX_PER_STAT_IVS + 1, MAX_PER_STAT_IVS + 1, MAX_PER_STAT_IVS + 1}; // ScriptGiveMonParameterized won't touch the stats' IV.
u16 moves[MAX_MON_MOVES] = {MOVE_NONE, MOVE_NONE, MOVE_NONE, MOVE_NONE};
return ScriptGiveMonParameterized(species, level, item, ITEM_POKE_BALL, NUM_NATURES, NUM_ABILITY_SLOTS, MON_GENDERLESS, evs, ivs, moves, FALSE, FALSE, NUMBER_OF_MON_TYPES);
return ScriptGiveMonParameterized(species, level, item, ITEM_POKE_BALL, NUM_NATURES, NUM_ABILITY_PERSONALITY, MON_GENDERLESS, evs, ivs, moves, FALSE, FALSE, NUMBER_OF_MON_TYPES);
}
#define PARSE_FLAG(n, default_) (flags & (1 << (n))) ? VarGet(ScriptReadHalfword(ctx)) : (default_)
@ -424,7 +428,7 @@ void ScrCmd_givemon(struct ScriptContext *ctx)
u16 item = PARSE_FLAG(0, ITEM_NONE);
u8 ball = PARSE_FLAG(1, ITEM_POKE_BALL);
u8 nature = PARSE_FLAG(2, NUM_NATURES);
u8 abilityNum = PARSE_FLAG(3, NUM_ABILITY_SLOTS);
u8 abilityNum = PARSE_FLAG(3, NUM_ABILITY_PERSONALITY);
u8 gender = PARSE_FLAG(4, MON_GENDERLESS); // TODO: Find a better way to assign a random gender.
u8 hpEv = PARSE_FLAG(5, 0);
u8 atkEv = PARSE_FLAG(6, 0);

View File

@ -101,7 +101,9 @@ const u8 gText_DefaultNameHalie[] = _("HALIE");
const u8 gText_ThisIsAPokemon[] = _("This is what we call a “POKéMON.”{PAUSE 96}\p");
const u8 gText_5MarksPokemon[] = _("????? POKéMON");
const u8 gText_UnkHeight[] = _("{CLEAR_TO 0x0C}??'??”");
const u8 gText_UnkHeightMetric[] = _("???.? m");
const u8 gText_UnkWeight[] = _("????.? lbs.");
const u8 gText_UnkWeightMetric[] = _("???.? kg.");
const u8 gText_EmptyPkmnCategory[] = _(" POKéMON"); // Unused
const u8 gText_EmptyHeight[] = _("{CLEAR_TO 0x0C} ' ”"); // Unused
const u8 gText_EmptyWeight[] = _(" . lbs."); // Unused

View File

@ -0,0 +1,35 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Dancer can copy a dance move immediately after it was used and allow the user of Dancer to still use its move")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_QUIVER_DANCE].danceMove == TRUE);
PLAYER(SPECIES_WOBBUFFET)
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); }
} WHEN {
TURN { MOVE(player, MOVE_QUIVER_DANCE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_QUIVER_DANCE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
ABILITY_POPUP(opponent, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_QUIVER_DANCE, opponent);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); // Same turn
}
}
SINGLE_BATTLE_TEST("Dancer can copy Teeter Dance")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_TEETER_DANCE].danceMove == TRUE);
PLAYER(SPECIES_WOBBUFFET)
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Item(ITEM_LUM_BERRY); }
} WHEN {
TURN { MOVE(player, MOVE_TEETER_DANCE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TEETER_DANCE, player);
ABILITY_POPUP(opponent, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TEETER_DANCE, opponent);
}
}

View File

@ -94,7 +94,7 @@ SINGLE_BATTLE_TEST("Shield Dust does not block self-targeting effects, primary o
GIVEN {
ASSUME(MoveHasMoveEffectSelf(MOVE_POWER_UP_PUNCH, MOVE_EFFECT_ATK_PLUS_1) == TRUE);
ASSUME(MoveHasMoveEffectSelf(MOVE_RAPID_SPIN, MOVE_EFFECT_RAPIDSPIN) == TRUE);
ASSUME(MoveHasMoveEffectSelf(MOVE_RAPID_SPIN, MOVE_EFFECT_RAPID_SPIN) == TRUE);
ASSUME(MoveHasMoveEffectSelf(MOVE_LEAF_STORM, MOVE_EFFECT_SP_ATK_TWO_DOWN) == TRUE);
ASSUME(MoveHasMoveEffectSelf(MOVE_METEOR_ASSAULT, MOVE_EFFECT_RECHARGE) == TRUE);
PLAYER(SPECIES_WOBBUFFET);

View File

@ -179,7 +179,6 @@ AI_SINGLE_BATTLE_TEST("AI chooses moves with secondary effect that have a 100% c
PARAMETRIZE { ability = ABILITY_SERENE_GRACE; }
GIVEN {
AI_LOG;
ASSUME(MoveHasMoveEffectWithChance(MOVE_SHADOW_BALL, MOVE_EFFECT_SP_DEF_MINUS_1, 20));
ASSUME(MoveHasMoveEffectWithChance(MOVE_OCTAZOOKA, MOVE_EFFECT_ACC_MINUS_1, 50));
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);

View File

@ -0,0 +1,54 @@
#include "global.h"
#include "test/battle.h"
#include "battle_ai_util.h"
AI_SINGLE_BATTLE_TEST("AI prefers to set up a powerful Status over fainting a target")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_TRICK_ROOM].effect == EFFECT_TRICK_ROOM);
ASSUME(gMovesInfo[MOVE_TACKLE].power > 0);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_POWERFUL_STATUS);
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_DUSCLOPS) { Moves(MOVE_TRICK_ROOM, MOVE_TACKLE); }
} WHEN {
TURN { EXPECT_MOVE(opponent, MOVE_TRICK_ROOM); }
TURN { EXPECT_MOVE(opponent, MOVE_TACKLE); SEND_OUT(player, 1); }
} SCENE {
MESSAGE("Wobbuffet fainted!");
}
}
AI_SINGLE_BATTLE_TEST("AI will try to do damage on target instead of setting up hazards if target has a way to remove them")
{
GIVEN {
ASSUME(MoveHasMoveEffectSelf(MOVE_RAPID_SPIN, MOVE_EFFECT_RAPID_SPIN) == TRUE);
ASSUME(gMovesInfo[MOVE_STEALTH_ROCK].effect == EFFECT_STEALTH_ROCK);
ASSUME(gMovesInfo[MOVE_TACKLE].power > 0);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_POWERFUL_STATUS | AI_FLAG_OMNISCIENT);
PLAYER(SPECIES_WOBBUFFET) { HP(1); Moves(MOVE_RAPID_SPIN, MOVE_DEFOG, MOVE_CELEBRATE); }
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_GLIGAR) { Moves(MOVE_STEALTH_ROCK, MOVE_TACKLE); }
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { EXPECT_MOVE(opponent, MOVE_TACKLE); SEND_OUT(player, 1); }
} SCENE {
MESSAGE("Wobbuffet fainted!");
}
}
AI_SINGLE_BATTLE_TEST("AI will not set up Rain if it is already raining")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_RAIN_DANCE].effect == EFFECT_RAIN_DANCE);
ASSUME(gMovesInfo[MOVE_TACKLE].power > 0);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_POWERFUL_STATUS);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_RAIN_DANCE, MOVE_TACKLE); }
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { EXPECT_MOVE(opponent, MOVE_RAIN_DANCE); }
TURN { EXPECT_MOVE(opponent, MOVE_TACKLE); }
}
}

View File

@ -0,0 +1,58 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_TEETER_DANCE].effect == EFFECT_CONFUSE);
}
SINGLE_BATTLE_TEST("Teeter Dance confuses target")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_TEETER_DANCE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TEETER_DANCE, player);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, opponent);
MESSAGE("Foe Wobbuffet became confused!");
}
}
SINGLE_BATTLE_TEST("Teeter Dance confusion is blocked by Own Tempo")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_SLOWPOKE) { Ability(ABILITY_OWN_TEMPO); }
} WHEN {
TURN { MOVE(player, MOVE_TEETER_DANCE); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_OWN_TEMPO);
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TEETER_DANCE, player);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, opponent);
MESSAGE("Foe Wobbuffet became confused!");
}
}
}
DOUBLE_BATTLE_TEST("Teeter Dance can confuse foes and allies")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(playerLeft, MOVE_TEETER_DANCE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TEETER_DANCE, playerLeft);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, opponentLeft);
MESSAGE("Foe Wobbuffet became confused!");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, playerRight);
MESSAGE("Wynaut became confused!");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, opponentRight);
MESSAGE("Foe Wynaut became confused!");
}
}

View File

@ -3,11 +3,11 @@
ASSUMPTIONS
{
ASSUME(MoveHasMoveEffectSelf(MOVE_RAPID_SPIN, MOVE_EFFECT_RAPIDSPIN) == TRUE);
ASSUME(MoveHasMoveEffectSelf(MOVE_RAPID_SPIN, MOVE_EFFECT_RAPID_SPIN) == TRUE);
#if B_SPEED_BUFFING_RAPID_SPIN >= GEN_8
ASSUME(MoveHasMoveEffectSelf(MOVE_RAPID_SPIN, MOVE_EFFECT_SPD_PLUS_1) == TRUE);
#endif
ASSUME(MoveHasMoveEffectSelf(MOVE_MORTAL_SPIN, MOVE_EFFECT_RAPIDSPIN) == TRUE);
ASSUME(MoveHasMoveEffectSelf(MOVE_MORTAL_SPIN, MOVE_EFFECT_RAPID_SPIN) == TRUE);
ASSUME(MoveHasMoveEffect(MOVE_MORTAL_SPIN, MOVE_EFFECT_POISON) == TRUE);
}

View File

@ -0,0 +1,99 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_TIDY_UP].effect == EFFECT_TIDY_UP);
}
SINGLE_BATTLE_TEST("Tidy Up raises Attack and Speed by one")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_TIDY_UP); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TIDY_UP, player);
NOT MESSAGE("Tidying up complete!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Attack rose!");
MESSAGE("Wobbuffet's Speed rose!");
} THEN {
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1);
EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 1);
}
}
SINGLE_BATTLE_TEST("Tidy Up removes hazards and raises Stats")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SPIKES); }
TURN { MOVE(opponent, MOVE_STEALTH_ROCK); }
TURN { MOVE(opponent, MOVE_TOXIC_SPIKES); }
TURN { MOVE(opponent, MOVE_STICKY_WEB); MOVE(player, MOVE_TIDY_UP); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_SPIKES, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponent);
MESSAGE("Wobbuffet used Tidy Up!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TIDY_UP, player);
MESSAGE("The spikes disappeared from the ground around your team!");
MESSAGE("The pointed stones disappeared from around your team!");
MESSAGE("The poison spikes disappeared from the ground around your team!");
MESSAGE("The sticky web has disappeared from the ground around your team!");
MESSAGE("Tidying up complete!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Attack rose!");
MESSAGE("Wobbuffet's Speed rose!");
}
}
SINGLE_BATTLE_TEST("Tidy Up removes Substitute")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_TIDY_UP); }
} SCENE {
MESSAGE("Foe Wobbuffet used Substitute!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, opponent);
MESSAGE("Foe Wobbuffet made a SUBSTITUTE!");
MESSAGE("Wobbuffet used Tidy Up!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TIDY_UP, player);
MESSAGE("Foe Wobbuffet's SUBSTITUTE faded!");
MESSAGE("Tidying up complete!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Attack rose!");
MESSAGE("Wobbuffet's Speed rose!");
}
}
AI_SINGLE_BATTLE_TEST("AI prefers to keep it's substitute over removing hazards if target is slower")
{
GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
PLAYER(SPECIES_WOBBUFFET) { Speed(50); Status1(STATUS1_PARALYSIS); Moves(MOVE_SLEEP_POWDER, MOVE_STEALTH_ROCK, MOVE_CELEBRATE); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(100); Moves(MOVE_BITE, MOVE_TACKLE, MOVE_SUBSTITUTE, MOVE_TIDY_UP); }
} WHEN {
TURN { MOVE(player, MOVE_STEALTH_ROCK); EXPECT_MOVE(opponent, MOVE_SUBSTITUTE); }
TURN { EXPECT_MOVE(opponent, MOVE_BITE); }
}
}
AI_SINGLE_BATTLE_TEST("AI will try to remove hazards if slower then target even with a Substitute because it expects the Sub to be broken")
{
GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
PLAYER(SPECIES_WOBBUFFET) { Speed(100); Status1(STATUS1_BURN); Moves(MOVE_SLEEP_POWDER, MOVE_STEALTH_ROCK, MOVE_CELEBRATE); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(50); Moves(MOVE_BITE, MOVE_TACKLE, MOVE_SUBSTITUTE, MOVE_TIDY_UP); }
} WHEN {
TURN { MOVE(player, MOVE_STEALTH_ROCK); EXPECT_MOVE(opponent, MOVE_SUBSTITUTE); }
TURN { EXPECT_MOVE(opponent, MOVE_TIDY_UP); }
}
}

View File

@ -0,0 +1,28 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_UPROAR].effect == EFFECT_UPROAR);
}
DOUBLE_BATTLE_TEST("Uproar status causes sleeping pokemon to wake up during an attack")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); }
OPPONENT(SPECIES_VOLTORB) { Ability(ABILITY_SOUNDPROOF); Status1(STATUS1_SLEEP); }
OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); }
} WHEN {
TURN { MOVE(playerLeft, MOVE_UPROAR); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_UPROAR, playerLeft);
HP_BAR(opponentRight);
MESSAGE("Wobbuffet woke up in the UPROAR!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight);
MESSAGE("Foe Voltorb woke up in the UPROAR!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentLeft);
MESSAGE("Foe Wobbuffet woke up in the UPROAR!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight);
}
}

View File

@ -26,7 +26,7 @@ static const struct TrainerMon sTestParty1[] =
.ev = TRAINER_PARTY_EVS(252, 0, 0, 252, 4, 0),
.lvl = 67,
.moves = {MOVE_AIR_SLASH, MOVE_BARRIER, MOVE_SOLAR_BEAM, MOVE_EXPLOSION},
.nature = TRAINER_PARTY_NATURE(NATURE_HASTY),
.nature = NATURE_HASTY,
.nickname = COMPOUND_STRING("Bubbles"),
.dynamaxLevel = 5,
},
@ -35,6 +35,10 @@ static const struct TrainerMon sTestParty1[] =
.ability = ABILITY_SHADOW_TAG,
.lvl = 5,
},
{
.species = SPECIES_WYNAUT,
.lvl = 5,
},
};
static const struct Trainer sTestTrainer1 =
@ -59,6 +63,7 @@ TEST("CreateNPCTrainerPartyForTrainer generates customized Pokémon")
EXPECT(GetMonAbility(&testParty[0]) == ABILITY_TELEPATHY);
EXPECT(GetMonAbility(&testParty[1]) == ABILITY_SHADOW_TAG);
EXPECT(GetMonAbility(&testParty[2]) == ABILITY_SHADOW_TAG);
EXPECT(GetMonData(&testParty[0], MON_DATA_FRIENDSHIP, 0) == 42);
EXPECT(GetMonData(&testParty[1], MON_DATA_FRIENDSHIP, 0) == 0);
@ -110,6 +115,7 @@ TEST("CreateNPCTrainerPartyForTrainer generates customized Pokémon")
EXPECT(GetMonGender(&testParty[0]) == MON_FEMALE);
EXPECT(GetNature(&testParty[0]) == NATURE_HASTY);
EXPECT(GetNature(&testParty[1]) == NATURE_HARDY);
EXPECT_EQ(GetMonData(&testParty[0], MON_DATA_DYNAMAX_LEVEL), 5);
EXPECT_EQ(GetMonData(&testParty[1], MON_DATA_DYNAMAX_LEVEL), 0);

View File

@ -1533,7 +1533,7 @@ void SetFlagForTest(u32 sourceLine, u16 flagId)
void ClearFlagAfterTest(void)
{
if (DATA.flagId != 0)
if (DATA.flagId != 0)
{
FlagClear(DATA.flagId);
DATA.flagId = 0;