Merge branch '_RHH/upcoming' into _RHH/pr/upcoming/merrpFollowers
# Conflicts: # src/data/graphics/pokemon.h
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
3
.github/ISSUE_TEMPLATE/04_other_errors.yaml
vendored
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 :)
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
@ -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-->
|
||||
0
graphics/pokemon/squawkabilly/green_plumage/icon.png → graphics/pokemon/squawkabilly/icon.png
Executable file → Normal file
|
Before Width: | Height: | Size: 384 B After Width: | Height: | Size: 384 B |
|
Before Width: | Height: | Size: 449 B After Width: | Height: | Size: 449 B |
|
Before Width: | Height: | Size: 459 B After Width: | Height: | Size: 459 B |
0
graphics/pokemon/tatsugiri/curly/icon.png → graphics/pokemon/tatsugiri/icon.png
Executable file → Normal file
|
Before Width: | Height: | Size: 334 B After Width: | Height: | Size: 334 B |
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
};
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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[];
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -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--;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
@ -17,5 +17,4 @@ const struct Trainer gBattlePartners[] = {
|
||||
.trainerPic = TRAINER_BACK_PIC_STEVEN,
|
||||
.trainerName = _("STEVEN"),
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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},
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
},
|
||||
|
||||
@ -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
|
||||
|
||||
316
src/pokedex.c
@ -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)
|
||||
|
||||
@ -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++;
|
||||
}
|
||||
|
||||
@ -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] =
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
35
test/battle/ability/dancer.c
Normal 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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
54
test/battle/ai_powerful_status.c
Normal 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); }
|
||||
}
|
||||
}
|
||||
58
test/battle/move_effect/confuse.c
Normal 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!");
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
99
test/battle/move_effect/tidy_up.c
Normal 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); }
|
||||
}
|
||||
}
|
||||
28
test/battle/move_effect/uproar.c
Normal 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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||