Merge branch 'RHH/master' into RHH/pr/master/opponentName

This commit is contained in:
Eduardo Quezada 2023-08-29 13:11:32 -04:00
commit be152fbee8
226 changed files with 2430 additions and 970 deletions

View File

@ -1,50 +1,52 @@
name: ⚔️ Battle Engine mechanical bugs 🐛 name: ⚔️ Battle Engine mechanical bugs 🐛
description: File a bug report related to battle mechanic, be it moves, abilities and/or items. description: File a bug report related to battle mechanic, be it moves, abilities and/or items.
labels: ["bug", "status: unconfirmed", "category: battle-mechanic"] labels: ["bug", "status: unconfirmed", "category: battle-mechanic"]
body: body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
Please fill in all required fields with as many details as possible. Please fill in all required fields with as many details as possible.
- type: textarea - type: textarea
id: description id: description
attributes: attributes:
label: Description label: Description
description: | description: |
Describe the issue you are experiencing. Describe the issue you are experiencing.
Attach images/videos if possible. Attach images/videos if possible.
placeholder: | placeholder: |
Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video
validations: validations:
required: true required: true
- type: dropdown - type: dropdown
id: version id: version
attributes: attributes:
label: Version label: Version
description: What version of pokeemerald-expansion are you using as a base? description: What version of pokeemerald-expansion are you using as a base?
options: options:
- 1.5.1 (Default) - 1.5.3 (Default)
- upcoming (Edge) - upcoming (Edge)
- 1.5.0 - 1.5.2
- 1.4.3 - 1.5.1
- 1.4.2 - 1.5.0
- 1.4.1 - 1.4.3
- 1.4.0 - 1.4.2
- pre-1.4.0 - 1.4.1
validations: - 1.4.0
required: true - pre-1.4.0
- type: input validations:
id: upcomingversion required: true
attributes: - type: input
label: Upcoming Version id: upcomingversion
description: If you're using the upcoming branch, please specify what was the commit hash you pulled from. attributes:
validations: label: Upcoming Version
required: false description: If you're using the upcoming branch, please specify what was the commit hash you pulled from.
- type: input validations:
id: contact required: false
attributes: - type: input
label: Discord contact info id: contact
description: Provide your Discord tag here so we can contact you in case we need more details. Be sure to join our server ([here](https://discord.gg/6CzjAG6GZk)). attributes:
placeholder: ex. Lunos#4026 label: Discord contact info
validations: description: Provide your Discord tag here so we can contact you in case we need more details. Be sure to join our server ([here](https://discord.gg/6CzjAG6GZk)).
required: false placeholder: ex. Lunos#4026
validations:
required: false

View File

@ -1,50 +1,52 @@
name: 🧠 Battle AI bugs 🐛 name: 🧠 Battle AI bugs 🐛
description: File a bug report related to battle AI. description: File a bug report related to battle AI.
labels: ["bug", "status: unconfirmed", "category: battle-ai"] labels: ["bug", "status: unconfirmed", "category: battle-ai"]
body: body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
Please fill in all required fields with as many details as possible. Please fill in all required fields with as many details as possible.
- type: textarea - type: textarea
id: description id: description
attributes: attributes:
label: Description label: Description
description: | description: |
Describe the issue you are experiencing. Describe the issue you are experiencing.
Attach images/videos if possible. Attach images/videos if possible.
placeholder: | placeholder: |
Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video
validations: validations:
required: true required: true
- type: dropdown - type: dropdown
id: version id: version
attributes: attributes:
label: Version label: Version
description: What version of pokeemerald-expansion are you using as a base? description: What version of pokeemerald-expansion are you using as a base?
options: options:
- 1.5.1 (Default) - 1.5.3 (Default)
- upcoming (Edge) - upcoming (Edge)
- 1.5.0 - 1.5.2
- 1.4.3 - 1.5.1
- 1.4.2 - 1.5.0
- 1.4.1 - 1.4.3
- 1.4.0 - 1.4.2
- pre-1.4.0 - 1.4.1
validations: - 1.4.0
required: true - pre-1.4.0
- type: input validations:
id: upcomingversion required: true
attributes: - type: input
label: Upcoming Version id: upcomingversion
description: If you're using the upcoming branch, please specify what was the commit hash you pulled from. attributes:
validations: label: Upcoming Version
required: false description: If you're using the upcoming branch, please specify what was the commit hash you pulled from.
- type: input validations:
id: contact required: false
attributes: - type: input
label: Discord contact info id: contact
description: Provide your Discord tag here so we can contact you in case we need more details. Be sure to join our server ([here](https://discord.gg/6CzjAG6GZk)). attributes:
placeholder: ex. Lunos#4026 label: Discord contact info
validations: description: Provide your Discord tag here so we can contact you in case we need more details. Be sure to join our server ([here](https://discord.gg/6CzjAG6GZk)).
required: false placeholder: ex. Lunos#4026
validations:
required: false

View File

@ -1,27 +1,27 @@
name: 🙏 Feature Request 🙏 name: 🙏 Feature Request 🙏
description: Do you want a feature to be added to the Expansion? Let us know! description: Do you want a feature to be added to the Expansion? Let us know!
labels: ["feature-request"] labels: ["feature-request"]
body: body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
Please fill in all required fields with as many details as possible. Please fill in all required fields with as many details as possible.
- type: textarea - type: textarea
id: description id: description
attributes: attributes:
label: Description label: Description
description: | description: |
Describe the issue you are experiencing. Describe the issue you are experiencing.
Attach images/videos if possible. Attach images/videos if possible.
placeholder: | placeholder: |
Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video
validations: validations:
required: true required: true
- type: input - type: input
id: contact id: contact
attributes: attributes:
label: Discord contact info label: Discord contact info
description: Provide your Discord tag here so we can contact you in case we need more details. Be sure to join our server ([here](https://discord.gg/6CzjAG6GZk)). description: Provide your Discord tag here so we can contact you in case we need more details. Be sure to join our server ([here](https://discord.gg/6CzjAG6GZk)).
placeholder: ex. Lunos#4026 placeholder: ex. Lunos#4026
validations: validations:
required: false required: false

View File

@ -1,50 +1,52 @@
name: 💾 Other errors 🖥️ name: 💾 Other errors 🖥️
description: Everything else that doesn't fit in the above categories. description: Everything else that doesn't fit in the above categories.
labels: ["bug", "status: unconfirmed"] labels: ["bug", "status: unconfirmed"]
body: body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
Please fill in all required fields with as many details as possible. Please fill in all required fields with as many details as possible.
- type: textarea - type: textarea
id: description id: description
attributes: attributes:
label: Description label: Description
description: | description: |
Describe the issue you are experiencing. Describe the issue you are experiencing.
Attach images/videos if possible. Attach images/videos if possible.
placeholder: | placeholder: |
Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video
validations: validations:
required: true required: true
- type: dropdown - type: dropdown
id: version id: version
attributes: attributes:
label: Version label: Version
description: What version of pokeemerald-expansion are you using as a base? description: What version of pokeemerald-expansion are you using as a base?
options: options:
- 1.5.1 (Default) - 1.5.3 (Default)
- upcoming (Edge) - upcoming (Edge)
- 1.5.0 - 1.5.2
- 1.4.3 - 1.5.1
- 1.4.2 - 1.5.0
- 1.4.1 - 1.4.3
- 1.4.0 - 1.4.2
- pre-1.4.0 - 1.4.1
validations: - 1.4.0
required: true - pre-1.4.0
- type: input validations:
id: upcomingversion required: true
attributes: - type: input
label: Upcoming Version id: upcomingversion
description: If you're using the upcoming branch, please specify what was the commit hash you pulled from. attributes:
validations: label: Upcoming Version
required: false description: If you're using the upcoming branch, please specify what was the commit hash you pulled from.
- type: input validations:
id: contact required: false
attributes: - type: input
label: Discord contact info id: contact
description: Provide your Discord tag here so we can contact you in case we need more details. Be sure to join our server ([here](https://discord.gg/6CzjAG6GZk)). attributes:
placeholder: ex. Lunos#4026 label: Discord contact info
validations: description: Provide your Discord tag here so we can contact you in case we need more details. Be sure to join our server ([here](https://discord.gg/6CzjAG6GZk)).
required: false placeholder: ex. Lunos#4026
validations:
required: false

View File

@ -125,19 +125,53 @@ Otherwise, ask for help on Discord or IRC (see [README.md](README.md)), or conti
Note that in msys2, Copy is Ctrl+Insert and Paste is Shift+Insert. Note that in msys2, Copy is Ctrl+Insert and Paste is Shift+Insert.
1. Open msys2 at C:\devkitPro\msys2\mingw64.exe or run `C:\devkitPro\msys2\msys2_shell.bat -mingw64`. 1. Open msys2 at C:\devkitPro\msys2\msys2_shell.bat.
2. Certain packages are required to build pokeemerald. Install these by running the following command: 2. Certain packages are required to build pokeemerald. Install these by running the following two commands:
```bash ```bash
pacman -S make zlib-devel git mingw-w64-x86_64-gcc mingw-w64-x86_64-libpng pacman -Sy msys2-keyring
pacman -S make gcc zlib-devel git
``` ```
<details> <details>
<summary><i>Note...</i></summary> <summary><i>Note...</i></summary>
> This command will ask for confirmation, just enter the yes action when prompted. > The commands will ask for confirmation, just enter the yes action when prompted.
</details> </details>
3. Download [libpng](https://sourceforge.net/projects/libpng/files/libpng16/1.6.37/libpng-1.6.37.tar.xz/download).
4. Change directory to where libpng was downloaded. By default, msys2 will start in the current user's profile folder, located at **C:\Users\\&#8288;_\<user>_**, where *\<user>* is your Windows username. In most cases, libpng should be saved within a subfolder of the profile folder. For example, if libpng was saved to **C:\Users\\_\<user>_\Downloads** (the Downloads location for most users), enter this command:
```bash
cd Downloads
```
<details>
<summary><i>Notes...</i></summary>
> Note 1: While not shown, msys uses forward slashes `/` instead of backwards slashes `\` as the directory separator.
> Note 2: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "Downloads/My Downloads"`.
> Note 3: Windows path names are case-insensitive so adhering to capitalization isnt needed.
> Note 4: If libpng was saved elsewhere, you will need to specify the full path to where libpng was downloaded, e.g. `cd c:/devkitpro/msys2` if it was saved there.
</details>
5. Run the following commands to uncompress and install libpng.
```bash
tar xf libpng-1.6.37.tar.xz
cd libpng-1.6.37
./configure --prefix=/usr
make check
make install
```
6. Then finally, run the following command to change back to the user profile folder.
```bash
cd
```
### Choosing where to store pokeemerald (msys2) ### Choosing where to store pokeemerald (msys2)
At this point, you can choose a folder to store pokeemerald into. If you're okay with storing pokeemerald in the user profile folder, then proceed to [Installation](#installation). Otherwise, you'll need to account for where pokeemerald is stored when changing directory to the pokeemerald folder. At this point, you can choose a folder to store pokeemerald into. If you're okay with storing pokeemerald in the user profile folder, then proceed to [Installation](#installation). Otherwise, you'll need to account for where pokeemerald is stored when changing directory to the pokeemerald folder.

View File

@ -450,7 +450,7 @@ $(OBJ_DIR)/sym_ewram.ld: sym_ewram.txt
# NOTE: Based on C_DEP above, but without NODEP and KEEP_TEMPS handling. # NOTE: Based on C_DEP above, but without NODEP and KEEP_TEMPS handling.
define TEST_DEP define TEST_DEP
$1: $2 $$(shell $(SCANINC) -I include -I tools/agbcc/include -I gflib -I test $2) $1: $2 $$(shell $(SCANINC) -I include -I tools/agbcc/include -I gflib $2)
@echo "$$(CC1) <flags> -o $$@ $$<" @echo "$$(CC1) <flags> -o $$@ $$<"
@$$(CPP) $$(CPPFLAGS) $$< | $$(PREPROC) $$< charmap.txt -i | $$(CC1) $$(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $$(AS) $$(ASFLAGS) -o $$@ - @$$(CPP) $$(CPPFLAGS) $$< | $$(PREPROC) $$< charmap.txt -i | $$(CC1) $$(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $$(AS) $$(ASFLAGS) -o $$@ -
endef endef

View File

@ -1053,8 +1053,9 @@
.byte 0xca .byte 0xca
.endm .endm
.macro setcharge .macro setcharge battler:req
.byte 0xcb .byte 0xcb
.byte \battler
.endm .endm
.macro callterrainattack .macro callterrainattack
@ -1317,7 +1318,7 @@
.2byte \holdEffect .2byte \holdEffect
.4byte \jumpInstr .4byte \jumpInstr
.endm .endm
.macro dostockpilestatchangeswearoff, battler:req, statChangeInstr:req .macro dostockpilestatchangeswearoff, battler:req, statChangeInstr:req
callnative BS_DoStockpileStatChangesWearOff callnative BS_DoStockpileStatChangesWearOff
.byte \battler .byte \battler
@ -1353,7 +1354,7 @@
.macro setsnow .macro setsnow
callnative BS_SetSnow callnative BS_SetSnow
.endm .endm
.macro setzeffect .macro setzeffect
callnative BS_SetZEffect callnative BS_SetZEffect
.endm .endm
@ -1363,12 +1364,6 @@
callnative BS_TrySymbiosis callnative BS_TrySymbiosis
.endm .endm
@ returns TRUE or FALSE to gBattleCommunication[0]
.macro canteleport battler:req
callnative BS_CanTeleport
.byte \battler
.endm
@ returns B_SIDE_x to gBattleCommunication[0] @ returns B_SIDE_x to gBattleCommunication[0]
.macro getbattlerside battler:req .macro getbattlerside battler:req
callnative BS_GetBattlerSide callnative BS_GetBattlerSide
@ -2076,7 +2071,7 @@
.macro swapsidestatuses .macro swapsidestatuses
various BS_ATTACKER, VARIOUS_SWAP_SIDE_STATUSES various BS_ATTACKER, VARIOUS_SWAP_SIDE_STATUSES
.endm .endm
.macro swapstats stat:req .macro swapstats stat:req
various BS_ATTACKER, VARIOUS_SWAP_STATS various BS_ATTACKER, VARIOUS_SWAP_STATS
.byte \stat .byte \stat
@ -2177,6 +2172,11 @@
jumpifbyte CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_NO_EFFECT, \jumpInstr jumpifbyte CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_NO_EFFECT, \jumpInstr
.endm .endm
.macro jumpifside battler:req, side:req, equalJumpInstr:req
getbattlerside \battler
jumpifbyte CMP_EQUAL, gBattleCommunication, \side, \equalJumpInstr
.endm
.macro jumpifbattletype flags:req, jumpInstr:req .macro jumpifbattletype flags:req, jumpInstr:req
jumpifword CMP_COMMON_BITS, gBattleTypeFlags, \flags, \jumpInstr jumpifword CMP_COMMON_BITS, gBattleTypeFlags, \flags, \jumpInstr
.endm .endm

View File

@ -3079,12 +3079,9 @@ BattleScript_TryTailwindAbilitiesLoop_WindRider:
BattleScript_TryTailwindAbilitiesLoop_WindPower: BattleScript_TryTailwindAbilitiesLoop_WindPower:
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
copybyte sSAVED_BATTLER, gBattlerAttacker setcharge BS_TARGET
copybyte gBattlerAttacker, gBattlerTarget
setcharge
printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
copybyte gBattlerAttacker, sSAVED_BATTLER
goto BattleScript_TryTailwindAbilitiesLoop_Increment goto BattleScript_TryTailwindAbilitiesLoop_Increment
BattleScript_EffectMircleEye: BattleScript_EffectMircleEye:
@ -4104,6 +4101,8 @@ BattleScript_MoveMissedDoDamage::
.if B_CRASH_IF_TARGET_IMMUNE < GEN_4 .if B_CRASH_IF_TARGET_IMMUNE < GEN_4
jumpifhalfword CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_DOESNT_AFFECT_FOE, BattleScript_MoveEnd jumpifhalfword CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_DOESNT_AFFECT_FOE, BattleScript_MoveEnd
.endif .endif
moveendcase MOVEEND_PROTECT_LIKE_EFFECT @ Spiky Shield's damage happens before recoil.
jumpifhasnohp BS_ATTACKER, BattleScript_MoveEnd
printstring STRINGID_PKMNCRASHED printstring STRINGID_PKMNCRASHED
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
damagecalc damagecalc
@ -5129,7 +5128,7 @@ BattleScript_EffectBatonPass::
goto BattleScript_MoveEnd goto BattleScript_MoveEnd
BattleScript_EffectRapidSpin:: BattleScript_EffectRapidSpin::
.if B_SPEED_BUFFING_RAPID_SPIN == GEN_8 .if B_SPEED_BUFFING_RAPID_SPIN >= GEN_8
attackcanceler attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring attackstring
@ -5404,15 +5403,14 @@ BattleScript_EffectHurricane:
BattleScript_EffectTeleport: BattleScript_EffectTeleport:
attackcanceler attackcanceler
attackstring attackstring
ppreduce
.if B_TELEPORT_BEHAVIOR >= GEN_7 .if B_TELEPORT_BEHAVIOR >= GEN_7
canteleport BS_ATTACKER jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_EffectBatonPass
jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_EffectTeleportNew jumpifside BS_ATTACKER, B_SIDE_PLAYER, BattleScript_EffectBatonPass
goto BattleScript_ButItFailed
.else .else
jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_ButItFailed jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_ButItFailed
.endif .endif
BattleScript_EffectTeleportTryToRunAway: BattleScript_EffectTeleportTryToRunAway:
ppreduce
getifcantrunfrombattle BS_ATTACKER getifcantrunfrombattle BS_ATTACKER
jumpifbyte CMP_EQUAL, gBattleCommunication, BATTLE_RUN_FORBIDDEN, BattleScript_ButItFailed jumpifbyte CMP_EQUAL, gBattleCommunication, BATTLE_RUN_FORBIDDEN, BattleScript_ButItFailed
jumpifbyte CMP_EQUAL, gBattleCommunication, BATTLE_RUN_FAILURE, BattleScript_PrintAbilityMadeIneffective jumpifbyte CMP_EQUAL, gBattleCommunication, BATTLE_RUN_FAILURE, BattleScript_PrintAbilityMadeIneffective
@ -5423,29 +5421,6 @@ BattleScript_EffectTeleportTryToRunAway:
setoutcomeonteleport BS_ATTACKER setoutcomeonteleport BS_ATTACKER
goto BattleScript_MoveEnd goto BattleScript_MoveEnd
BattleScript_EffectTeleportNew:
getbattlerside BS_ATTACKER
jumpifbyte CMP_EQUAL, gBattleCommunication, B_SIDE_OPPONENT, BattleScript_EffectTeleportTryToRunAway
attackanimation
waitanimation
openpartyscreen BS_ATTACKER, BattleScript_EffectTeleportNewEnd
switchoutabilities BS_ATTACKER
waitstate
switchhandleorder BS_ATTACKER, 2
returntoball BS_ATTACKER
getswitchedmondata BS_ATTACKER
switchindataupdate BS_ATTACKER
hpthresholds BS_ATTACKER
trytoclearprimalweather
printstring STRINGID_EMPTYSTRING3
waitmessage 1
printstring STRINGID_SWITCHINMON
switchinanim BS_ATTACKER, TRUE
waitstate
switchineffects BS_ATTACKER
BattleScript_EffectTeleportNewEnd:
goto BattleScript_MoveEnd
BattleScript_EffectBeatUp:: BattleScript_EffectBeatUp::
attackcanceler attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
@ -5872,7 +5847,7 @@ BattleScript_EffectCharge::
attackcanceler attackcanceler
attackstring attackstring
ppreduce ppreduce
setcharge setcharge BS_ATTACKER
attackanimation attackanimation
waitanimation waitanimation
.if B_CHARGE_SPDEF_RAISE >= GEN_5 .if B_CHARGE_SPDEF_RAISE >= GEN_5
@ -6937,27 +6912,6 @@ BattleScript_TailwindEnds::
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
end2 end2
BattleScript_WindPowerActivatesEnd2::
setbyte gBattlerAttacker, 0
BattleScript_WindPowerLoop:
printstring STRINGID_EMPTYSTRING3
jumpifability BS_ATTACKER, ABILITY_WIND_POWER, BattleScript_WindPowerLoop_Cont
goto BattleScript_WindPowerIncrement
BattleScript_WindPowerLoop_Cont:
jumpifstatus3 BS_ATTACKER, STATUS3_CHARGED_UP, BattleScript_WindPowerIncrement
goto BattleScript_WindPower_Activate
BattleScript_WindPower_Activate:
call BattleScript_AbilityPopUp
setcharge
printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER
waitmessage B_WAIT_TIME_LONG
BattleScript_WindPowerIncrement:
addbyte gBattlerAttacker, 1
jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_WindPowerLoop
BattleScript_WindPowerEnd:
destroyabilitypopup
end2
BattleScript_TrickRoomEnds:: BattleScript_TrickRoomEnds::
printstring STRINGID_TRICKROOMENDS printstring STRINGID_TRICKROOMENDS
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
@ -7419,11 +7373,8 @@ BattleScript_AngerShellRet:
return return
BattleScript_WindPowerActivates:: BattleScript_WindPowerActivates::
.if B_CHECK_IF_CHARGED_UP == TRUE
jumpifstatus3 BS_ATTACKER, STATUS3_CHARGED_UP, BattleScript_WindPowerActivates_Ret
.endif
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
setcharge setcharge BS_TARGET
printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
BattleScript_WindPowerActivates_Ret: BattleScript_WindPowerActivates_Ret:
@ -7924,7 +7875,7 @@ BattleScript_WishMegaEvolution::
BattleScript_PrimalReversion:: BattleScript_PrimalReversion::
call BattleScript_PrimalReversionRet call BattleScript_PrimalReversionRet
end2 end2
BattleScript_PrimalReversionRestoreAttacker:: BattleScript_PrimalReversionRestoreAttacker::
call BattleScript_PrimalReversionRet call BattleScript_PrimalReversionRet
copybyte gBattlerAttacker, sSAVED_BATTLER copybyte gBattlerAttacker, sSAVED_BATTLER
@ -8782,15 +8733,14 @@ BattleScript_DesolateLandActivates::
call BattleScript_ActivateWeatherAbilities call BattleScript_ActivateWeatherAbilities
end3 end3
BattleScript_DesolateLandEvaporatesWaterTypeMoves:: BattleScript_PrimalWeatherBlocksMove::
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_ATTACKSTRING_PRINTED, BattleScript_MoveEnd @in case of multi-target moves, if move fails once, no point in printing the message twice
accuracycheck BattleScript_PrintMoveMissed, NO_ACC_CALC_CHECK_LOCK_ON
attackstring attackstring
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
ppreduce ppreduce
jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_STRING_PRINTED, BattleScript_MoveEnd printfromtable gPrimalWeatherBlocksStringIds
printstring STRINGID_MOVEEVAPORATEDINTHEHARSHSUNLIGHT
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
orword gHitMarker, HITMARKER_STRING_PRINTED
goto BattleScript_MoveEnd goto BattleScript_MoveEnd
BattleScript_PrimordialSeaActivates:: BattleScript_PrimordialSeaActivates::
@ -8802,17 +8752,6 @@ BattleScript_PrimordialSeaActivates::
call BattleScript_ActivateWeatherAbilities call BattleScript_ActivateWeatherAbilities
end3 end3
BattleScript_PrimordialSeaFizzlesOutFireTypeMoves::
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
pause B_WAIT_TIME_SHORT
ppreduce
jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_STRING_PRINTED, BattleScript_MoveEnd
printstring STRINGID_MOVEFIZZLEDOUTINTHEHEAVYRAIN
waitmessage B_WAIT_TIME_LONG
orword gHitMarker, HITMARKER_STRING_PRINTED
goto BattleScript_MoveEnd
BattleScript_DeltaStreamActivates:: BattleScript_DeltaStreamActivates::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
@ -8983,7 +8922,7 @@ BattleScript_BadDreams_ShowPopUp:
goto BattleScript_BadDreams_DmgAfterPopUp goto BattleScript_BadDreams_DmgAfterPopUp
BattleScript_BadDreams_HidePopUp: BattleScript_BadDreams_HidePopUp:
destroyabilitypopup destroyabilitypopup
tryfaintmon BS_TARGET tryfaintmon BS_TARGET
goto BattleScript_BadDreamsIncrement goto BattleScript_BadDreamsIncrement
BattleScript_TookAttack:: BattleScript_TookAttack::
@ -10461,6 +10400,7 @@ BattleScript_SymbiosisActivates::
return return
BattleScript_TargetAbilityStatRaiseRet:: BattleScript_TargetAbilityStatRaiseRet::
copybyte sSAVED_BATTLER, gBattlerAttacker
copybyte gBattlerAbility, gEffectBattler copybyte gBattlerAbility, gEffectBattler
copybyte gBattlerAttacker, gBattlerTarget copybyte gBattlerAttacker, gBattlerTarget
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
@ -10468,6 +10408,7 @@ BattleScript_TargetAbilityStatRaiseRet::
setgraphicalstatchangevalues setgraphicalstatchangevalues
call BattleScript_StatUp call BattleScript_StatUp
BattleScript_TargetAbilityStatRaiseRet_End: BattleScript_TargetAbilityStatRaiseRet_End:
copybyte gBattlerAttacker, sSAVED_BATTLER
return return
BattleScript_PokemonCantUseTheMove:: BattleScript_PokemonCantUseTheMove::

View File

@ -212,6 +212,7 @@ struct SideTimer
u8 toxicSpikesAmount; u8 toxicSpikesAmount;
u8 stealthRockAmount; u8 stealthRockAmount;
u8 stickyWebAmount; u8 stickyWebAmount;
u8 stickyWebBattlerId;
u8 stickyWebBattlerSide; // Used for Court Change u8 stickyWebBattlerSide; // Used for Court Change
u8 auroraVeilTimer; u8 auroraVeilTimer;
u8 auroraVeilBattlerId; u8 auroraVeilBattlerId;
@ -644,7 +645,6 @@ struct BattleStruct
u8 forcedSwitch:4; // For each battler u8 forcedSwitch:4; // For each battler
u8 switchInAbilityPostponed:4; // To not activate against an empty field, each bit for battler u8 switchInAbilityPostponed:4; // To not activate against an empty field, each bit for battler
u8 ballSpriteIds[2]; // item gfx, window gfx u8 ballSpriteIds[2]; // item gfx, window gfx
u8 stickyWebUser;
u8 appearedInBattle; // Bitfield to track which Pokemon appeared in battle. Used for Burmy's form change u8 appearedInBattle; // Bitfield to track which Pokemon appeared in battle. Used for Burmy's form change
u8 skyDropTargets[MAX_BATTLERS_COUNT]; // For Sky Drop, to account for if multiple Pokemon use Sky Drop in a double battle. u8 skyDropTargets[MAX_BATTLERS_COUNT]; // For Sky Drop, to account for if multiple Pokemon use Sky Drop in a double battle.
// When using a move which hits multiple opponents which is then bounced by a target, we need to make sure, the move hits both opponents, the one with bounce, and the one without. // When using a move which hits multiple opponents which is then bounced by a target, we need to make sure, the move hits both opponents, the one with bounce, and the one without.

View File

@ -409,9 +409,8 @@ extern const u8 BattleScript_GulpMissileGorging[];
extern const u8 BattleScript_GulpMissileGulping[]; extern const u8 BattleScript_GulpMissileGulping[];
extern const u8 BattleScript_BattleBondActivatesOnMoveEndAttacker[]; extern const u8 BattleScript_BattleBondActivatesOnMoveEndAttacker[];
extern const u8 BattleScript_DesolateLandActivates[]; extern const u8 BattleScript_DesolateLandActivates[];
extern const u8 BattleScript_DesolateLandEvaporatesWaterTypeMoves[];
extern const u8 BattleScript_PrimordialSeaActivates[]; extern const u8 BattleScript_PrimordialSeaActivates[];
extern const u8 BattleScript_PrimordialSeaFizzlesOutFireTypeMoves[]; extern const u8 BattleScript_PrimalWeatherBlocksMove[];
extern const u8 BattleScript_DeltaStreamActivates[]; extern const u8 BattleScript_DeltaStreamActivates[];
extern const u8 BattleScript_MysteriousAirCurrentBlowsOn[]; extern const u8 BattleScript_MysteriousAirCurrentBlowsOn[];
extern const u8 BattleScript_AttackWeakenedByStrongWinds[]; extern const u8 BattleScript_AttackWeakenedByStrongWinds[];

View File

@ -136,8 +136,8 @@ u8 DoBattlerEndTurnEffects(void);
bool8 HandleWishPerishSongOnTurnEnd(void); bool8 HandleWishPerishSongOnTurnEnd(void);
bool8 HandleFaintedMonActions(void); bool8 HandleFaintedMonActions(void);
void TryClearRageAndFuryCutter(void); void TryClearRageAndFuryCutter(void);
u8 AtkCanceller_UnableToUseMove(u32 moveType);
void SetAtkCancellerForCalledMove(void); void SetAtkCancellerForCalledMove(void);
u8 AtkCanceller_UnableToUseMove(void);
u8 AtkCanceller_UnableToUseMove2(void); u8 AtkCanceller_UnableToUseMove2(void);
bool8 HasNoMonsToSwitch(u8 battlerId, u8 r1, u8 r2); bool8 HasNoMonsToSwitch(u8 battlerId, u8 r1, u8 r2);
bool32 TryChangeBattleWeather(u8 battler, u32 weatherEnumId, bool32 viaAbility); bool32 TryChangeBattleWeather(u8 battler, u32 weatherEnumId, bool32 viaAbility);

View File

@ -118,7 +118,6 @@
#define B_PLUS_MINUS_INTERACTION GEN_LATEST // In Gen5+, Plus and Minus can be activated with themselves and the opposite ability. Before, only the opposing ability could activate it. #define B_PLUS_MINUS_INTERACTION GEN_LATEST // In Gen5+, Plus and Minus can be activated with themselves and the opposite ability. Before, only the opposing ability could activate it.
#define B_WEATHER_FORMS GEN_LATEST // In Gen5+, Castform and Cherrim revert to their base form upon losing their respective ability. Cherrim needs Flower Gift to swap forms. #define B_WEATHER_FORMS GEN_LATEST // In Gen5+, Castform and Cherrim revert to their base form upon losing their respective ability. Cherrim needs Flower Gift to swap forms.
#define B_SYMBIOSIS_GEMS GEN_LATEST // In Gen7+, Symbiosis passes an item after a gem-boosted attack. Previously, items are passed before the gem-boosted attack hits, making the item effect apply. #define B_SYMBIOSIS_GEMS GEN_LATEST // In Gen7+, Symbiosis passes an item after a gem-boosted attack. Previously, items are passed before the gem-boosted attack hits, making the item effect apply.
#define B_CHECK_IF_CHARGED_UP TRUE // If set to TRUE, certain abilities such as Electromorphosis WILL check if the STATUS3_CHARGED_UP status flag is applied.
#define B_ABSORBING_ABILITY_STRING GEN_LATEST // In Gen5+, the abilities that absorb moves of a certain type use a generic string for stat increases and decreases. #define B_ABSORBING_ABILITY_STRING GEN_LATEST // In Gen5+, the abilities that absorb moves of a certain type use a generic string for stat increases and decreases.
#define B_LEAF_GUARD_PREVENTS_REST GEN_LATEST // In Gen5+, Leaf Guard prevents the use of Rest in harsh sunlight. #define B_LEAF_GUARD_PREVENTS_REST GEN_LATEST // In Gen5+, Leaf Guard prevents the use of Rest in harsh sunlight.
#define B_SNOW_WARNING GEN_LATEST // In Gen9+, Snow Warning will summon snow instead of hail. #define B_SNOW_WARNING GEN_LATEST // In Gen9+, Snow Warning will summon snow instead of hail.

View File

@ -827,6 +827,10 @@
#define B_MSG_SOMEONES_BOX_FULL 2 #define B_MSG_SOMEONES_BOX_FULL 2
#define B_MSG_LANETTES_BOX_FULL 3 #define B_MSG_LANETTES_BOX_FULL 3
// gPrimalWeatherBlocksStringIds
#define B_MSG_PRIMAL_WEATHER_FIZZLED_BY_RAIN 0
#define B_MSG_PRIMAL_WEATHER_EVAPORATED_IN_SUN 1
// gInobedientStringIds // gInobedientStringIds
#define B_MSG_LOAFING 0 #define B_MSG_LOAFING 0
#define B_MSG_WONT_OBEY 1 #define B_MSG_WONT_OBEY 1

View File

@ -3,7 +3,7 @@
#include "sprite.h" #include "sprite.h"
extern u8 gDecompressionBuffer[0x4000]; extern u8 ALIGNED(4) gDecompressionBuffer[0x4000];
void LZDecompressWram(const u32 *src, void *dest); void LZDecompressWram(const u32 *src, void *dest);
void LZDecompressVram(const u32 *src, void *dest); void LZDecompressVram(const u32 *src, void *dest);

View File

@ -213,7 +213,7 @@ struct SoundInfo
ExtVolPitFunc ExtVolPit; ExtVolPitFunc ExtVolPit;
u8 gap2[16]; u8 gap2[16];
struct SoundChannel chans[MAX_DIRECTSOUND_CHANNELS]; struct SoundChannel chans[MAX_DIRECTSOUND_CHANNELS];
s8 pcmBuffer[PCM_DMA_BUF_SIZE * 2]; s8 ALIGNED(4) pcmBuffer[PCM_DMA_BUF_SIZE * 2];
}; };
struct SongHeader struct SongHeader

View File

@ -1,7 +1,7 @@
#ifndef GUARD_GBA_MACRO_H #ifndef GUARD_GBA_MACRO_H
#define GUARD_GBA_MACRO_H #define GUARD_GBA_MACRO_H
#define CPU_FILL(value, dest, size, bit) \ #define CPU_FILL_UNCHECKED(value, dest, size, bit) \
{ \ { \
vu##bit tmp = (vu##bit)(value); \ vu##bit tmp = (vu##bit)(value); \
CpuSet((void *)&tmp, \ CpuSet((void *)&tmp, \
@ -9,10 +9,33 @@
CPU_SET_##bit##BIT | CPU_SET_SRC_FIXED | ((size)/(bit/8) & 0x1FFFFF)); \ CPU_SET_##bit##BIT | CPU_SET_SRC_FIXED | ((size)/(bit/8) & 0x1FFFFF)); \
} }
#if MODERN
#define CPU_FILL(value, dest, size, bit) \
do \
{ \
_Static_assert(_Alignof(dest) >= (bit / 8), "destination potentially unaligned"); \
CPU_FILL_UNCHECKED(value, dest, size, bit); \
} while (0)
#else
#define CPU_FILL(value, dest, size, bit) CPU_FILL_UNCHECKED(value, dest, size, bit)
#endif
#define CpuFill16(value, dest, size) CPU_FILL(value, dest, size, 16) #define CpuFill16(value, dest, size) CPU_FILL(value, dest, size, 16)
#define CpuFill32(value, dest, size) CPU_FILL(value, dest, size, 32) #define CpuFill32(value, dest, size) CPU_FILL(value, dest, size, 32)
#define CPU_COPY(src, dest, size, bit) CpuSet(src, dest, CPU_SET_##bit##BIT | ((size)/(bit/8) & 0x1FFFFF)) #define CPU_COPY_UNCHECKED(src, dest, size, bit) CpuSet(src, dest, CPU_SET_##bit##BIT | ((size)/(bit/8) & 0x1FFFFF))
#if MODERN
#define CPU_COPY(src, dest, size, bit) \
do \
{ \
_Static_assert(_Alignof(src) >= (bit / 8), "source potentially unaligned"); \
_Static_assert(_Alignof(dest) >= (bit / 8), "destination potentially unaligned"); \
CPU_COPY_UNCHECKED(src, dest, size, bit); \
} while (0)
#else
#define CPU_COPY(src, dest, size, bit) CPU_COPY_UNCHECKED(src, dest, size, bit)
#endif
#define CpuCopy16(src, dest, size) CPU_COPY(src, dest, size, 16) #define CpuCopy16(src, dest, size) CPU_COPY(src, dest, size, 16)
#define CpuCopy32(src, dest, size) CPU_COPY(src, dest, size, 32) #define CpuCopy32(src, dest, size) CPU_COPY(src, dest, size, 32)
@ -31,7 +54,7 @@
#define CpuFastCopy(src, dest, size) CpuFastSet(src, dest, ((size)/(32/8) & 0x1FFFFF)) #define CpuFastCopy(src, dest, size) CpuFastSet(src, dest, ((size)/(32/8) & 0x1FFFFF))
#define DmaSet(dmaNum, src, dest, control) \ #define DmaSetUnchecked(dmaNum, src, dest, control) \
{ \ { \
vu32 *dmaRegs = (vu32 *)REG_ADDR_DMA##dmaNum; \ vu32 *dmaRegs = (vu32 *)REG_ADDR_DMA##dmaNum; \
dmaRegs[0] = (vu32)(src); \ dmaRegs[0] = (vu32)(src); \
@ -40,7 +63,21 @@
dmaRegs[2]; \ dmaRegs[2]; \
} }
#define DMA_FILL(dmaNum, value, dest, size, bit) \ #if MODERN
// NOTE: Assumes 16-bit DMAs.
#define DmaSet(dmaNum, src, dest, control) \
do \
{ \
_Static_assert(_Alignof(src) >= __builtin_choose_expr(__builtin_constant_p(control), ((control) & (DMA_32BIT << 16)) ? 4 : 2, 2), "source potentially unaligned"); \
_Static_assert(_Alignof(dest) >= __builtin_choose_expr(__builtin_constant_p(control), ((control) & (DMA_32BIT << 16)) ? 4 : 2, 2), "destination potentially unaligned"); \
DmaSetUnchecked(dmaNum, src, dest, control); \
} while (0)
#else
#define DmaSet(dmaNum, src, dest, control) \
DmaSetUnchecked(dmaNum, src, dest, control)
#endif
#define DMA_FILL_UNCHECKED(dmaNum, value, dest, size, bit) \
{ \ { \
vu##bit tmp = (vu##bit)(value); \ vu##bit tmp = (vu##bit)(value); \
DmaSet(dmaNum, \ DmaSet(dmaNum, \
@ -50,6 +87,17 @@
| ((size)/(bit/8))); \ | ((size)/(bit/8))); \
} }
#if MODERN
#define DMA_FILL(dmaNum, value, dest, size, bit) \
do \
{ \
_Static_assert(_Alignof(dest) >= (bit / 8), "destination potentially unaligned"); \
DMA_FILL_UNCHECKED(dmaNum, value, dest, size, bit); \
} while (0)
#else
#define DMA_FILL(dmaNum, value, dest, size, bit) DMA_FILL_UNCHECKED(dmaNum, value, dest, size, bit)
#endif
#define DmaFill16(dmaNum, value, dest, size) DMA_FILL(dmaNum, value, dest, size, 16) #define DmaFill16(dmaNum, value, dest, size) DMA_FILL(dmaNum, value, dest, size, 16)
#define DmaFill32(dmaNum, value, dest, size) DMA_FILL(dmaNum, value, dest, size, 32) #define DmaFill32(dmaNum, value, dest, size) DMA_FILL(dmaNum, value, dest, size, 32)
@ -58,23 +106,46 @@
// unit size (2 or 4 bytes) and then combined with the DMA control flags using a // unit size (2 or 4 bytes) and then combined with the DMA control flags using a
// bitwise OR operation. // bitwise OR operation.
#define DMA_CLEAR(dmaNum, dest, size, bit) \ #define DMA_CLEAR_UNCHECKED(dmaNum, dest, size, bit) \
{ \ { \
vu##bit *_dest = (vu##bit *)(dest); \ vu##bit *_dest = (vu##bit *)(dest); \
u32 _size = size; \ u32 _size = size; \
DmaFill##bit(dmaNum, 0, _dest, _size); \ DmaFill##bit(dmaNum, 0, _dest, _size); \
} }
#if MODERN
#define DMA_CLEAR(dmaNum, dest, size, bit) \
do \
{ \
_Static_assert(_Alignof(dest) >= (bit / 8), "destination potentially unaligned"); \
DMA_CLEAR_UNCHECKED(dmaNum, dest, size, bit); \
} while (0)
#else
#define DMA_CLEAR(dmaNum, dest, size, bit) DMA_CLEAR_UNCHECKED(dmaNum, dest, size, bit)
#endif
#define DmaClear16(dmaNum, dest, size) DMA_CLEAR(dmaNum, dest, size, 16) #define DmaClear16(dmaNum, dest, size) DMA_CLEAR(dmaNum, dest, size, 16)
#define DmaClear32(dmaNum, dest, size) DMA_CLEAR(dmaNum, dest, size, 32) #define DmaClear32(dmaNum, dest, size) DMA_CLEAR(dmaNum, dest, size, 32)
#define DMA_COPY(dmaNum, src, dest, size, bit) \ #define DMA_COPY_UNCHECKED(dmaNum, src, dest, size, bit) \
DmaSet(dmaNum, \ DmaSet(dmaNum, \
src, \ src, \
dest, \ dest, \
(DMA_ENABLE | DMA_START_NOW | DMA_##bit##BIT | DMA_SRC_INC | DMA_DEST_INC) << 16 \ (DMA_ENABLE | DMA_START_NOW | DMA_##bit##BIT | DMA_SRC_INC | DMA_DEST_INC) << 16 \
| ((size)/(bit/8))) | ((size)/(bit/8)))
#if MODERN
#define DMA_COPY(dmaNum, src, dest, size, bit) \
do \
{ \
_Static_assert(_Alignof(src) >= (bit / 8), "source potentially unaligned"); \
_Static_assert(_Alignof(dest) >= (bit / 8), "destination potentially unaligned"); \
DMA_COPY_UNCHECKED(dmaNum, src, dest, size, bit); \
} while (0)
#else
#define DMA_COPY(dmaNum, src, dest, size, bit) DMA_COPY_UNCHECKED(dmaNum, src, dest, size, bit)
#endif
#define DmaCopy16(dmaNum, src, dest, size) DMA_COPY(dmaNum, src, dest, size, 16) #define DmaCopy16(dmaNum, src, dest, size) DMA_COPY(dmaNum, src, dest, size, 16)
#define DmaCopy32(dmaNum, src, dest, size) DMA_COPY(dmaNum, src, dest, size, 32) #define DmaCopy32(dmaNum, src, dest, size) DMA_COPY(dmaNum, src, dest, size, 32)

View File

@ -27,10 +27,32 @@ u16 ArcTan2(s16 x, s16 y);
void CpuSet(const void *src, void *dest, u32 control); void CpuSet(const void *src, void *dest, u32 control);
#if MODERN
// NOTE: Assumes 16-bit CpuSets unless control is a constant and has
// CPU_SET_32BIT set.
#define CpuSet(src, dest, control) \
do \
{ \
_Static_assert(_Alignof(src) >= __builtin_choose_expr(__builtin_constant_p(control), ((control) & CPU_SET_32BIT) ? 4 : 2, 2), "source potentially unaligned"); \
_Static_assert(_Alignof(dest) >= __builtin_choose_expr(__builtin_constant_p(control), ((control) & CPU_SET_32BIT) ? 4 : 2, 2), "destination potentially unaligned"); \
CpuSet(src, dest, control); \
} while (0)
#endif
#define CPU_FAST_SET_SRC_FIXED 0x01000000 #define CPU_FAST_SET_SRC_FIXED 0x01000000
void CpuFastSet(const void *src, void *dest, u32 control); void CpuFastSet(const void *src, void *dest, u32 control);
#if MODERN
#define CpuFastSet(src, dest, control) \
do \
{ \
_Static_assert(_Alignof(src) >= 4, "source potentially unaligned"); \
_Static_assert(_Alignof(dest) >= 4, "destination potentially unaligned"); \
CpuFastSet(src, dest, control); \
} while (0)
#endif
void BgAffineSet(struct BgAffineSrcData *src, struct BgAffineDstData *dest, s32 count); void BgAffineSet(struct BgAffineSrcData *src, struct BgAffineDstData *dest, s32 count);
void ObjAffineSet(struct ObjAffineSrcData *src, void *dest, s32 count, s32 offset); void ObjAffineSet(struct ObjAffineSrcData *src, void *dest, s32 count, s32 offset);

View File

@ -20,7 +20,6 @@
#define BLOCK_CROSS_JUMP asm(""); #define BLOCK_CROSS_JUMP asm("");
// to help in decompiling // to help in decompiling
#define asm_comment(x) asm volatile("@ -- " x " -- ")
#define asm_unified(x) asm(".syntax unified\n" x "\n.syntax divided") #define asm_unified(x) asm(".syntax unified\n" x "\n.syntax divided")
#define NAKED __attribute__((naked)) #define NAKED __attribute__((naked))
@ -141,6 +140,8 @@
// Calls m0/m1/.../m8 depending on how many arguments are passed. // Calls m0/m1/.../m8 depending on how many arguments are passed.
#define VARARG_8(m, ...) CAT(m, NARG_8(__VA_ARGS__))(__VA_ARGS__) #define VARARG_8(m, ...) CAT(m, NARG_8(__VA_ARGS__))(__VA_ARGS__)
// This returns the number of arguments passed to it (up to 8).
#define NARG_8(...) NARG_8_(_, ##__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0) #define NARG_8(...) NARG_8_(_, ##__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define NARG_8_(_, a, b, c, d, e, f, g, h, N, ...) N #define NARG_8_(_, a, b, c, d, e, f, g, h, N, ...) N
@ -856,7 +857,7 @@ struct WaldaPhrase
struct TrainerNameRecord struct TrainerNameRecord
{ {
u32 trainerId; u32 trainerId;
u8 trainerName[PLAYER_NAME_LENGTH + 1]; u8 ALIGNED(2) trainerName[PLAYER_NAME_LENGTH + 1];
}; };
struct TrainerHillSave struct TrainerHillSave

View File

@ -8923,7 +8923,7 @@ extern const u32 gIntroGroudon_Gfx[];
extern const u32 gIntroGroudon_Tilemap[]; extern const u32 gIntroGroudon_Tilemap[];
extern const u32 gIntroLegendBg_Gfx[]; extern const u32 gIntroLegendBg_Gfx[];
extern const u32 gIntroGroudonBg_Tilemap[]; extern const u32 gIntroGroudonBg_Tilemap[];
extern const u8 gIntro3Bg_Pal[0x200]; extern const u8 ALIGNED(2) gIntro3Bg_Pal[0x200];
extern const u32 gIntroKyogre_Gfx[]; extern const u32 gIntroKyogre_Gfx[];
extern const u32 gIntroKyogre_Tilemap[]; extern const u32 gIntroKyogre_Tilemap[];
extern const u32 gIntroKyogreBg_Tilemap[]; extern const u32 gIntroKyogreBg_Tilemap[];
@ -10432,8 +10432,8 @@ extern const u32 gPokenavOptions_Gfx[];
extern const u16 gPokenavOptions_Pal[]; extern const u16 gPokenavOptions_Pal[];
// Battle Factory Screen // Battle Factory Screen
extern const u8 gFrontierFactorySelectMenu_Gfx[]; extern const u16 gFrontierFactorySelectMenu_Gfx[];
extern const u8 gFrontierFactorySelectMenu_Tilemap[]; extern const u16 gFrontierFactorySelectMenu_Tilemap[];
extern const u16 gFrontierFactorySelectMenu_Pal[]; extern const u16 gFrontierFactorySelectMenu_Pal[];
// Object event pals // Object event pals

View File

@ -78,7 +78,7 @@ struct BagMenu
u8 numShownItems[POCKETS_COUNT]; u8 numShownItems[POCKETS_COUNT];
s16 graphicsLoadState; s16 graphicsLoadState;
u8 unused2[14]; u8 unused2[14];
u8 pocketNameBuffer[32][32]; u8 ALIGNED(4) pocketNameBuffer[32][32];
u8 unused3[4]; u8 unused3[4];
}; };

View File

@ -329,7 +329,7 @@ struct RfuIntrStruct
{ {
union RfuPacket rxPacketAlloc; union RfuPacket rxPacketAlloc;
union RfuPacket txPacketAlloc; union RfuPacket txPacketAlloc;
u8 block1[0x960]; // size of librfu_intr.s binary u8 ALIGNED(2) block1[0x960]; // size of librfu_intr.s binary
struct STWIStatus block2; struct STWIStatus block2;
}; };

View File

@ -238,7 +238,7 @@ struct BlockRequest
}; };
extern struct Link gLink; extern struct Link gLink;
extern u16 gRecvCmds[MAX_RFU_PLAYERS][CMD_LENGTH]; extern u16 ALIGNED(4) gRecvCmds[MAX_RFU_PLAYERS][CMD_LENGTH];
extern u8 gBlockSendBuffer[BLOCK_BUFFER_SIZE]; extern u8 gBlockSendBuffer[BLOCK_BUFFER_SIZE];
extern u16 gLinkType; extern u16 gLinkType;
extern u32 gLinkStatus; extern u32 gLinkStatus;

View File

@ -18,7 +18,7 @@ struct MonMarkingsMenu
struct Sprite *textSprite; struct Sprite *textSprite;
const u8 *frameTiles; const u8 *frameTiles;
const u16 *framePalette; const u16 *framePalette;
u8 windowSpriteTiles[0x1000]; u8 ALIGNED(2) windowSpriteTiles[0x1000];
u8 unused[0x80]; u8 unused[0x80];
u8 tileLoadState; u8 tileLoadState;
}; };

View File

@ -54,9 +54,9 @@ struct PaletteFadeControl
extern struct PaletteFadeControl gPaletteFade; extern struct PaletteFadeControl gPaletteFade;
extern u32 gPlttBufferTransferPending; extern u32 gPlttBufferTransferPending;
extern u8 gPaletteDecompressionBuffer[]; extern u8 ALIGNED(4) gPaletteDecompressionBuffer[];
extern u16 gPlttBufferUnfaded[PLTT_BUFFER_SIZE]; extern u16 ALIGNED(4) gPlttBufferUnfaded[PLTT_BUFFER_SIZE];
extern u16 gPlttBufferFaded[PLTT_BUFFER_SIZE]; extern u16 ALIGNED(4) gPlttBufferFaded[PLTT_BUFFER_SIZE];
void LoadCompressedPalette(const u32 *src, u16 offset, u16 size); void LoadCompressedPalette(const u32 *src, u16 offset, u16 size);
void LoadPalette(const void *src, u16 offset, u16 size); void LoadPalette(const void *src, u16 offset, u16 size);

View File

@ -49,7 +49,7 @@ extern const struct SpriteTemplate gBallSpriteTemplates[];
#define POKEBALL_OPPONENT_SENDOUT 0xFE #define POKEBALL_OPPONENT_SENDOUT 0xFE
u8 DoPokeballSendOutAnimation(s16 pan, u8 kindOfThrow); u8 DoPokeballSendOutAnimation(s16 pan, u8 kindOfThrow);
void CreatePokeballSpriteToReleaseMon(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subpriortiy, u8 delay, u32 fadePalettes, u16 species); void CreatePokeballSpriteToReleaseMon(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subpriority, u8 delay, u32 fadePalettes, u16 species);
u8 CreateTradePokeballSprite(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subPriority, u8 delay, u32 fadePalettes); u8 CreateTradePokeballSprite(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subPriority, u8 delay, u32 fadePalettes);
void StartHealthboxSlideIn(u8 battler); void StartHealthboxSlideIn(u8 battler);
void DoHitAnimHealthboxEffect(u8 battler); void DoHitAnimHealthboxEffect(u8 battler);

View File

@ -462,12 +462,17 @@ void SetMultiuseSpriteTemplateToPokemon(u16 speciesTag, u8 battlerPosition);
void SetMultiuseSpriteTemplateToTrainerBack(u16 trainerSpriteId, u8 battlerPosition); void SetMultiuseSpriteTemplateToTrainerBack(u16 trainerSpriteId, u8 battlerPosition);
void SetMultiuseSpriteTemplateToTrainerFront(u16 trainerPicId, u8 battlerPosition); void SetMultiuseSpriteTemplateToTrainerFront(u16 trainerPicId, u8 battlerPosition);
// These are full type signatures for GetMonData() and GetBoxMonData(), /* GameFreak called Get(Box)MonData with either 2 or 3 arguments, for
// but they are not used since some code erroneously omits the third arg. * type safety we have a Get(Box)MonData macro which dispatches to
// u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data); * either Get(Box)MonData2 or Get(Box)MonData3 based on the number of
// u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data); * arguments. The two functions are aliases of each other, but they
u32 GetMonData(); * differ for matching purposes in the caller's codegen. */
u32 GetBoxMonData(); #define GetMonData(...) CAT(GetMonData, NARG_8(__VA_ARGS__))(__VA_ARGS__)
#define GetBoxMonData(...) CAT(GetBoxMonData, NARG_8(__VA_ARGS__))(__VA_ARGS__)
u32 GetMonData3(struct Pokemon *mon, s32 field, u8 *data);
u32 GetMonData2(struct Pokemon *mon, s32 field);
u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data);
u32 GetBoxMonData2(struct BoxPokemon *boxMon, s32 field);
void SetMonData(struct Pokemon *mon, s32 field, const void *dataArg); void SetMonData(struct Pokemon *mon, s32 field, const void *dataArg);
void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg); void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg);

View File

@ -37,7 +37,7 @@ struct ScanlineEffect
extern struct ScanlineEffect gScanlineEffect; extern struct ScanlineEffect gScanlineEffect;
extern u16 gScanlineEffectRegBuffers[2][0x3C0]; extern u16 ALIGNED(4) gScanlineEffectRegBuffers[2][0x3C0];
void ScanlineEffect_Stop(void); void ScanlineEffect_Stop(void);
void ScanlineEffect_Clear(void); void ScanlineEffect_Clear(void);

View File

@ -447,13 +447,13 @@
#ifndef GUARD_TEST_BATTLE_H #ifndef GUARD_TEST_BATTLE_H
#define GUARD_TEST_BATTLE_H #define GUARD_TEST_BATTLE_H
#include "global.h"
#include "battle.h" #include "battle.h"
#include "battle_anim.h" #include "battle_anim.h"
#include "data.h" #include "data.h"
#include "item.h" #include "item.h"
#include "random.h" #include "random.h"
#include "recorded_battle.h" #include "recorded_battle.h"
#include "test.h"
#include "util.h" #include "util.h"
#include "constants/abilities.h" #include "constants/abilities.h"
#include "constants/battle_anim.h" #include "constants/battle_anim.h"
@ -462,6 +462,7 @@
#include "constants/items.h" #include "constants/items.h"
#include "constants/moves.h" #include "constants/moves.h"
#include "constants/species.h" #include "constants/species.h"
#include "test/test.h"
// NOTE: If the stack is too small the test runner will probably crash // NOTE: If the stack is too small the test runner will probably crash
// or loop. // or loop.

View File

@ -2080,6 +2080,8 @@ gCryTable::
@ Calyrex @ Calyrex
cry Cry_CalyrexIceRider cry Cry_CalyrexIceRider
cry Cry_CalyrexShadowRider cry Cry_CalyrexShadowRider
@ Basculegion
cry Cry_Basculegion
.else .else
@ Cramorant @ Cramorant
cry Cry_Unown cry Cry_Unown
@ -2118,6 +2120,8 @@ gCryTable::
@ Calyrex @ Calyrex
cry Cry_Unown cry Cry_Unown
cry Cry_Unown cry Cry_Unown
@ Basculegion
cry Cry_Unown
.endif .endif
.align 2 .align 2
@ -4163,6 +4167,8 @@ gCryTable_Reverse::
@ Calyrex @ Calyrex
cry_reverse Cry_CalyrexIceRider cry_reverse Cry_CalyrexIceRider
cry_reverse Cry_CalyrexShadowRider cry_reverse Cry_CalyrexShadowRider
@ Basculegion
cry_reverse Cry_Basculegion
.else .else
cry_reverse Cry_Unown cry_reverse Cry_Unown
cry_reverse Cry_Unown cry_reverse Cry_Unown
@ -4187,4 +4193,5 @@ gCryTable_Reverse::
cry_reverse Cry_Unown cry_reverse Cry_Unown
cry_reverse Cry_Unown cry_reverse Cry_Unown
cry_reverse Cry_Unown cry_reverse Cry_Unown
cry_reverse Cry_Unown
.endif .endif

View File

@ -152,7 +152,7 @@ static void InitSinglePlayerBtlControllers(void)
gBattlerPartyIndexes[0] = 0; gBattlerPartyIndexes[0] = 0;
gBattlerPartyIndexes[1] = 0; gBattlerPartyIndexes[1] = 0;
if (BATTLE_TWO_VS_ONE_OPPONENT) if (BATTLE_TWO_VS_ONE_OPPONENT || WILD_DOUBLE_BATTLE)
{ {
gBattlerPartyIndexes[2] = 3; gBattlerPartyIndexes[2] = 3;
gBattlerPartyIndexes[3] = 1; gBattlerPartyIndexes[3] = 1;

View File

@ -268,7 +268,7 @@ static const u8 sActionHighlightMiddle_Gfx[] = INCBIN_U8( "graphics/battle_front
static const u8 sActionHighlightRight_Gfx[] = INCBIN_U8( "graphics/battle_frontier/factory_screen/action_highlight_right.4bpp"); static const u8 sActionHighlightRight_Gfx[] = INCBIN_U8( "graphics/battle_frontier/factory_screen/action_highlight_right.4bpp");
static const u8 sMonPicBgAnim_Gfx[] = INCBIN_U8( "graphics/battle_frontier/factory_screen/mon_pic_bg_anim.4bpp"); static const u8 sMonPicBgAnim_Gfx[] = INCBIN_U8( "graphics/battle_frontier/factory_screen/mon_pic_bg_anim.4bpp");
static const u8 sMonPicBg_Tilemap[] = INCBIN_U8( "graphics/battle_frontier/factory_screen/mon_pic_bg.bin"); static const u8 sMonPicBg_Tilemap[] = INCBIN_U8( "graphics/battle_frontier/factory_screen/mon_pic_bg.bin");
static const u8 sMonPicBg_Gfx[] = INCBIN_U8( "graphics/battle_frontier/factory_screen/mon_pic_bg.4bpp"); static const u16 sMonPicBg_Gfx[] = INCBIN_U16("graphics/battle_frontier/factory_screen/mon_pic_bg.4bpp");
static const u16 sMonPicBg_Pal[] = INCBIN_U16("graphics/battle_frontier/factory_screen/mon_pic_bg.gbapal"); static const u16 sMonPicBg_Pal[] = INCBIN_U16("graphics/battle_frontier/factory_screen/mon_pic_bg.gbapal");
static const struct SpriteSheet sSelect_SpriteSheets[] = static const struct SpriteSheet sSelect_SpriteSheets[] =

View File

@ -1409,11 +1409,10 @@ bool32 IsMegaTriggerSpriteActive(void)
void HideMegaTriggerSprite(void) void HideMegaTriggerSprite(void)
{ {
if (gBattleStruct->mega.triggerSpriteId != 0xFF) if (gBattleStruct->mega.triggerSpriteId >= MAX_SPRITES)
{ return;
ChangeMegaTriggerSprite(gBattleStruct->mega.triggerSpriteId, 0); ChangeMegaTriggerSprite(gBattleStruct->mega.triggerSpriteId, 0);
gSprites[gBattleStruct->mega.triggerSpriteId].tHide = TRUE; gSprites[gBattleStruct->mega.triggerSpriteId].tHide = TRUE;
}
} }
void HideTriggerSprites(void) void HideTriggerSprites(void)

View File

@ -1964,7 +1964,6 @@ u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer
u8 fixedIV; u8 fixedIV;
s32 i, j; s32 i, j;
u8 monsCount; u8 monsCount;
s32 ball = -1;
if (battleTypeFlags & BATTLE_TYPE_TRAINER && !(battleTypeFlags & (BATTLE_TYPE_FRONTIER if (battleTypeFlags & BATTLE_TYPE_TRAINER && !(battleTypeFlags & (BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_TRAINER_HILL))) | BATTLE_TYPE_TRAINER_HILL)))
@ -1986,6 +1985,7 @@ u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer
for (i = 0; i < monsCount; i++) for (i = 0; i < monsCount; i++)
{ {
s32 ball = -1;
u32 personalityHash = GeneratePartyHash(trainer, i); u32 personalityHash = GeneratePartyHash(trainer, i);
if (trainer->doubleBattle == TRUE) if (trainer->doubleBattle == TRUE)
personalityValue = 0x80; personalityValue = 0x80;
@ -3170,7 +3170,10 @@ static void BattleStartClearSetData(void)
gBattleStruct->mega.triggerSpriteId = 0xFF; gBattleStruct->mega.triggerSpriteId = 0xFF;
gBattleStruct->stickyWebUser = 0xFF; for (i = 0; i < ARRAY_COUNT(gSideTimers); i++)
{
gSideTimers[i].stickyWebBattlerId = 0xFF;
}
gBattleStruct->appearedInBattle = 0; gBattleStruct->appearedInBattle = 0;
gBattleStruct->beatUpSlot = 0; gBattleStruct->beatUpSlot = 0;
@ -3276,8 +3279,12 @@ void SwitchInClearSetData(void)
gBattleStruct->lastMoveFailed &= ~(gBitTable[gActiveBattler]); gBattleStruct->lastMoveFailed &= ~(gBitTable[gActiveBattler]);
gBattleStruct->palaceFlags &= ~(gBitTable[gActiveBattler]); gBattleStruct->palaceFlags &= ~(gBitTable[gActiveBattler]);
if (gActiveBattler == gBattleStruct->stickyWebUser) for (i = 0; i < ARRAY_COUNT(gSideTimers); i++)
gBattleStruct->stickyWebUser = 0xFF; // Switched into sticky web user slot so reset it {
// Switched into sticky web user slot, so reset stored battler ID
if (gSideTimers[i].stickyWebBattlerId == gActiveBattler)
gSideTimers[i].stickyWebBattlerId = 0xFF;
}
for (i = 0; i < gBattlersCount; i++) for (i = 0; i < gBattlersCount; i++)
{ {
@ -3390,8 +3397,12 @@ void FaintClearSetData(void)
gBattleStruct->palaceFlags &= ~(gBitTable[gActiveBattler]); gBattleStruct->palaceFlags &= ~(gBitTable[gActiveBattler]);
if (gActiveBattler == gBattleStruct->stickyWebUser) for (i = 0; i < ARRAY_COUNT(gSideTimers); i++)
gBattleStruct->stickyWebUser = 0xFF; // User of sticky web fainted, so reset the stored battler ID {
// User of sticky web fainted, so reset the stored battler ID
if (gSideTimers[i].stickyWebBattlerId == gActiveBattler)
gSideTimers[i].stickyWebBattlerId = 0xFF;
}
for (i = 0; i < gBattlersCount; i++) for (i = 0; i < gBattlersCount; i++)
{ {
@ -4584,7 +4595,11 @@ static void HandleTurnActionSelectionState(void)
{ {
// if we choose to throw a ball with our second mon, skip the action of the first // if we choose to throw a ball with our second mon, skip the action of the first
// (if we have chosen throw ball with first, second's is already skipped) // (if we have chosen throw ball with first, second's is already skipped)
gChosenActionByBattler[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)] = B_ACTION_NOTHING_FAINTED; // if throwing a ball in a wild battle with an in-game partner, skip partner's turn when throwing a ball
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
gChosenActionByBattler[GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT)] = B_ACTION_NOTHING_FAINTED;
else
gChosenActionByBattler[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)] = B_ACTION_NOTHING_FAINTED;
} }
gBattleMainFunc = SetActionsAndBattlersTurnOrder; gBattleMainFunc = SetActionsAndBattlersTurnOrder;

View File

@ -143,8 +143,8 @@ static const u8 sText_PkmnRaisedSpDefALittle[] = _("{B_ATK_PREFIX2}'s {B_CURRENT
static const u8 sText_PkmnRaisedDef[] = _("{B_ATK_PREFIX2}'s {B_CURRENT_MOVE}\nraised DEFENSE!"); static const u8 sText_PkmnRaisedDef[] = _("{B_ATK_PREFIX2}'s {B_CURRENT_MOVE}\nraised DEFENSE!");
static const u8 sText_PkmnRaisedDefALittle[] = _("{B_ATK_PREFIX2}'s {B_CURRENT_MOVE}\nraised DEFENSE a little!"); static const u8 sText_PkmnRaisedDefALittle[] = _("{B_ATK_PREFIX2}'s {B_CURRENT_MOVE}\nraised DEFENSE a little!");
static const u8 sText_PkmnCoveredByVeil[] = _("{B_ATK_PREFIX2}'s party is covered\nby a veil!"); static const u8 sText_PkmnCoveredByVeil[] = _("{B_ATK_PREFIX2}'s party is covered\nby a veil!");
static const u8 sText_PkmnUsedSafeguard[] = _("{B_DEF_NAME_WITH_PREFIX}'s party is protected\nby SAFEGUARD!"); static const u8 sText_PkmnUsedSafeguard[] = _("{B_DEF_NAME_WITH_PREFIX}'s party is protected\nby Safeguard!");
static const u8 sText_PkmnSafeguardExpired[] = _("{B_ATK_PREFIX3}'s party is no longer\nprotected by SAFEGUARD!"); static const u8 sText_PkmnSafeguardExpired[] = _("{B_ATK_PREFIX3}'s party is no longer\nprotected by Safeguard!");
static const u8 sText_PkmnWentToSleep[] = _("{B_ATK_NAME_WITH_PREFIX} went\nto sleep!"); static const u8 sText_PkmnWentToSleep[] = _("{B_ATK_NAME_WITH_PREFIX} went\nto sleep!");
static const u8 sText_PkmnSleptHealthy[] = _("{B_ATK_NAME_WITH_PREFIX} slept and\nbecame healthy!"); static const u8 sText_PkmnSleptHealthy[] = _("{B_ATK_NAME_WITH_PREFIX} slept and\nbecame healthy!");
static const u8 sText_PkmnWhippedWhirlwind[] = _("{B_ATK_NAME_WITH_PREFIX} whipped\nup a whirlwind!"); static const u8 sText_PkmnWhippedWhirlwind[] = _("{B_ATK_NAME_WITH_PREFIX} whipped\nup a whirlwind!");
@ -784,7 +784,7 @@ static const u8 sText_AttackerMeltedTheIce[] = _("{B_ATK_NAME_WITH_PREFIX} melte
static const u8 sText_TargetToughedItOut[] = _("{B_DEF_NAME_WITH_PREFIX} toughed it out\nto show you its best side!"); static const u8 sText_TargetToughedItOut[] = _("{B_DEF_NAME_WITH_PREFIX} toughed it out\nto show you its best side!");
static const u8 sText_AttackerLostElectricType[] = _("{B_ATK_NAME_WITH_PREFIX} used up all\nof its electricity!"); static const u8 sText_AttackerLostElectricType[] = _("{B_ATK_NAME_WITH_PREFIX} used up all\nof its electricity!");
static const u8 sText_AttackerSwitchedStatWithTarget[] = _("{B_ATK_NAME_WITH_PREFIX} switched {B_BUFF1}\nwith its target!"); static const u8 sText_AttackerSwitchedStatWithTarget[] = _("{B_ATK_NAME_WITH_PREFIX} switched {B_BUFF1}\nwith its target!");
static const u8 sText_BeingHitChargedPkmnWithPower[] = _("Being hit by {B_CURRENT_MOVE}\ncharged {B_ATK_NAME_WITH_PREFIX} with power!"); static const u8 sText_BeingHitChargedPkmnWithPower[] = _("Being hit by {B_CURRENT_MOVE}\ncharged {B_DEF_NAME_WITH_PREFIX} with power!");
static const u8 sText_SunlightActivatedAbility[] = _("The harsh sunlight activated\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ABILITY}!"); static const u8 sText_SunlightActivatedAbility[] = _("The harsh sunlight activated\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ABILITY}!");
static const u8 sText_StatWasHeightened[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_BUFF1} was heightened!"); static const u8 sText_StatWasHeightened[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_BUFF1} was heightened!");
static const u8 sText_ElectricTerrainActivatedAbility[] = _("The Electric Terrain activated\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ABILITY}!"); static const u8 sText_ElectricTerrainActivatedAbility[] = _("The Electric Terrain activated\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ABILITY}!");
@ -1851,6 +1851,12 @@ const u16 gWeatherStartsStringIds[] =
[WEATHER_ABNORMAL] = STRINGID_ITISRAINING [WEATHER_ABNORMAL] = STRINGID_ITISRAINING
}; };
const u16 gPrimalWeatherBlocksStringIds[] =
{
[B_MSG_PRIMAL_WEATHER_FIZZLED_BY_RAIN] = STRINGID_MOVEFIZZLEDOUTINTHEHEAVYRAIN,
[B_MSG_PRIMAL_WEATHER_EVAPORATED_IN_SUN] = STRINGID_MOVEEVAPORATEDINTHEHARSHSUNLIGHT,
};
const u16 gInobedientStringIds[] = const u16 gInobedientStringIds[] =
{ {
[B_MSG_LOAFING] = STRINGID_PKMNLOAFING, [B_MSG_LOAFING] = STRINGID_PKMNLOAFING,
@ -2693,7 +2699,7 @@ void BufferStringBattle(u16 stringID)
{ {
if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY)
stringPtr = sText_LegendaryPkmnAppeared; stringPtr = sText_LegendaryPkmnAppeared;
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[BATTLE_PARTNER(gActiveBattler)]])) // interesting, looks like they had something planned for wild double battles else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)]]))
stringPtr = sText_TwoWildPkmnAppeared; stringPtr = sText_TwoWildPkmnAppeared;
else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL) else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL)
stringPtr = sText_WildPkmnAppearedPause; stringPtr = sText_WildPkmnAppearedPause;

View File

@ -1503,25 +1503,8 @@ static void Cmd_attackcanceler(void)
s32 i, moveType; s32 i, moveType;
u16 attackerAbility = GetBattlerAbility(gBattlerAttacker); u16 attackerAbility = GetBattlerAbility(gBattlerAttacker);
GET_MOVE_TYPE(gCurrentMove, moveType); GET_MOVE_TYPE(gCurrentMove, moveType);
if (WEATHER_HAS_EFFECT && gBattleMoves[gCurrentMove].power)
{
if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL))
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_PrimordialSeaFizzlesOutFireTypeMoves;
return;
}
else if (moveType == TYPE_WATER && (gBattleWeather & B_WEATHER_SUN_PRIMAL))
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_DesolateLandEvaporatesWaterTypeMoves;
return;
}
}
if (gBattleOutcome != 0) if (gBattleOutcome != 0)
{ {
gCurrentActionFuncId = B_ACTION_FINISHED; gCurrentActionFuncId = B_ACTION_FINISHED;
@ -1537,9 +1520,27 @@ static void Cmd_attackcanceler(void)
if (TryAegiFormChange()) if (TryAegiFormChange())
return; return;
#endif #endif
if (AtkCanceller_UnableToUseMove()) if (AtkCanceller_UnableToUseMove(moveType))
return; return;
if (WEATHER_HAS_EFFECT && gBattleMoves[gCurrentMove].power)
{
if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL))
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_FIZZLED_BY_RAIN;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_PrimalWeatherBlocksMove;
return;
}
else if (moveType == TYPE_WATER && (gBattleWeather & B_WEATHER_SUN_PRIMAL))
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_EVAPORATED_IN_SUN;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_PrimalWeatherBlocksMove;
return;
}
}
if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_OFF if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_OFF
&& GetBattlerAbility(gBattlerAttacker) == ABILITY_PARENTAL_BOND && GetBattlerAbility(gBattlerAttacker) == ABILITY_PARENTAL_BOND
&& IsMoveAffectedByParentalBond(gCurrentMove, gBattlerAttacker) && IsMoveAffectedByParentalBond(gCurrentMove, gBattlerAttacker)
@ -1852,6 +1853,8 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u
s8 buff, accStage, evasionStage; s8 buff, accStage, evasionStage;
u8 atkParam = GetBattlerHoldEffectParam(battlerAtk); u8 atkParam = GetBattlerHoldEffectParam(battlerAtk);
u8 defParam = GetBattlerHoldEffectParam(battlerDef); u8 defParam = GetBattlerHoldEffectParam(battlerDef);
u8 atkAlly = BATTLE_PARTNER(battlerAtk);
u16 atkAllyAbility = GetBattlerAbility(atkAlly);
gPotentialItemEffectBattler = battlerDef; gPotentialItemEffectBattler = battlerDef;
accStage = gBattleMons[battlerAtk].statStages[STAT_ACC]; accStage = gBattleMons[battlerAtk].statStages[STAT_ACC];
@ -1885,30 +1888,66 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u
calc = gAccuracyStageRatios[buff].dividend * moveAcc; calc = gAccuracyStageRatios[buff].dividend * moveAcc;
calc /= gAccuracyStageRatios[buff].divisor; calc /= gAccuracyStageRatios[buff].divisor;
if (atkAbility == ABILITY_COMPOUND_EYES) // Attacker's ability
switch (atkAbility)
{
case ABILITY_COMPOUND_EYES:
calc = (calc * 130) / 100; // 1.3 compound eyes boost calc = (calc * 130) / 100; // 1.3 compound eyes boost
else if (atkAbility == ABILITY_VICTORY_STAR) break;
case ABILITY_VICTORY_STAR:
calc = (calc * 110) / 100; // 1.1 victory star boost calc = (calc * 110) / 100; // 1.1 victory star boost
if (IsBattlerAlive(BATTLE_PARTNER(battlerAtk)) && GetBattlerAbility(BATTLE_PARTNER(battlerAtk)) == ABILITY_VICTORY_STAR) break;
calc = (calc * 110) / 100; // 1.1 ally's victory star boost case ABILITY_HUSTLE:
if (IS_MOVE_PHYSICAL(move))
calc = (calc * 80) / 100; // 1.2 hustle loss
break;
}
if (defAbility == ABILITY_SAND_VEIL && WEATHER_HAS_EFFECT && gBattleWeather & B_WEATHER_SANDSTORM) // Target's ability
calc = (calc * 80) / 100; // 1.2 sand veil loss switch (defAbility)
else if (defAbility == ABILITY_SNOW_CLOAK && WEATHER_HAS_EFFECT && (gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW))) {
calc = (calc * 80) / 100; // 1.2 snow cloak loss case ABILITY_SAND_VEIL:
else if (defAbility == ABILITY_TANGLED_FEET && gBattleMons[battlerDef].status2 & STATUS2_CONFUSION) if (WEATHER_HAS_EFFECT && gBattleWeather & B_WEATHER_SANDSTORM)
calc = (calc * 50) / 100; // 1.5 tangled feet loss calc = (calc * 80) / 100; // 1.2 sand veil loss
break;
case ABILITY_SNOW_CLOAK:
if (WEATHER_HAS_EFFECT && (gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW)))
calc = (calc * 80) / 100; // 1.2 snow cloak loss
break;
case ABILITY_TANGLED_FEET:
if (gBattleMons[battlerDef].status2 & STATUS2_CONFUSION)
calc = (calc * 50) / 100; // 1.5 tangled feet loss
break;
}
if (atkAbility == ABILITY_HUSTLE && IS_MOVE_PHYSICAL(move)) // Attacker's ally's ability
calc = (calc * 80) / 100; // 1.2 hustle loss switch (atkAllyAbility)
{
case ABILITY_VICTORY_STAR:
if (IsBattlerAlive(atkAlly))
calc = (calc * 110) / 100; // 1.1 ally's victory star boost
break;
}
if (defHoldEffect == HOLD_EFFECT_EVASION_UP) // Attacker's hold effect
switch (atkHoldEffect)
{
case HOLD_EFFECT_WIDE_LENS:
calc = (calc * (100 + atkParam)) / 100;
break;
case HOLD_EFFECT_ZOOM_LENS:
if (GetBattlerTurnOrderNum(battlerAtk) > GetBattlerTurnOrderNum(battlerDef))
calc = (calc * (100 + atkParam)) / 100;
break;
}
// Target's hold effect
switch (defHoldEffect)
{
case HOLD_EFFECT_EVASION_UP:
calc = (calc * (100 - defParam)) / 100; calc = (calc * (100 - defParam)) / 100;
break;
if (atkHoldEffect == HOLD_EFFECT_WIDE_LENS) }
calc = (calc * (100 + atkParam)) / 100;
else if (atkHoldEffect == HOLD_EFFECT_ZOOM_LENS && GetBattlerTurnOrderNum(battlerAtk) > GetBattlerTurnOrderNum(battlerDef))
calc = (calc * (100 + atkParam)) / 100;
if (gProtectStructs[battlerAtk].usedMicleBerry) if (gProtectStructs[battlerAtk].usedMicleBerry)
{ {
@ -4144,11 +4183,7 @@ static void Cmd_jumpifsideaffecting(void)
u32 flags; u32 flags;
const u8 *jumpInstr; const u8 *jumpInstr;
if (cmd->battler == BS_ATTACKER) side = GET_BATTLER_SIDE(GetBattlerForBattleScript(cmd->battler));
side = GET_BATTLER_SIDE(gBattlerAttacker);
else
side = GET_BATTLER_SIDE(gBattlerTarget);
flags = cmd->flags; flags = cmd->flags;
jumpInstr = cmd->jumpInstr; jumpInstr = cmd->jumpInstr;
@ -8725,8 +8760,9 @@ static bool32 IsTeatimeAffected(u32 battlerId)
#define UPDATE_COURTCHANGED_BATTLER(structField)\ #define UPDATE_COURTCHANGED_BATTLER(structField)\
{ \ { \
sideTimerPlayer->structField ^= BIT_SIDE; \ temp = sideTimerPlayer->structField; \
sideTimerOpp->structField ^= BIT_SIDE; \ sideTimerPlayer->structField = BATTLE_OPPOSITE(sideTimerOpp->structField); \
sideTimerOpp->structField = BATTLE_OPPOSITE(temp); \
} \ } \
static bool32 CourtChangeSwapSideStatuses(void) static bool32 CourtChangeSwapSideStatuses(void)
@ -8761,9 +8797,7 @@ static bool32 CourtChangeSwapSideStatuses(void)
UPDATE_COURTCHANGED_BATTLER(auroraVeilBattlerId); UPDATE_COURTCHANGED_BATTLER(auroraVeilBattlerId);
UPDATE_COURTCHANGED_BATTLER(tailwindBattlerId); UPDATE_COURTCHANGED_BATTLER(tailwindBattlerId);
UPDATE_COURTCHANGED_BATTLER(luckyChantBattlerId); UPDATE_COURTCHANGED_BATTLER(luckyChantBattlerId);
UPDATE_COURTCHANGED_BATTLER(stickyWebBattlerId);
// For Mirror Armor only
gBattleStruct->stickyWebUser = gBattlerAttacker;
// Track which side originally set the Sticky Web // Track which side originally set the Sticky Web
SWAP(sideTimerPlayer->stickyWebBattlerSide, sideTimerOpp->stickyWebBattlerSide, temp); SWAP(sideTimerPlayer->stickyWebBattlerSide, sideTimerOpp->stickyWebBattlerSide, temp);
@ -8803,33 +8837,6 @@ static void HandleScriptMegaPrimal(u32 caseId, u32 battlerId, bool32 isMega)
} }
} }
static bool32 CanTeleport(u8 battlerId)
{
struct Pokemon *party = GetBattlerParty(battlerId);
u32 species, count, i;
for (i = 0; i < PARTY_SIZE; i++)
{
species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG);
if (species != SPECIES_NONE && species != SPECIES_EGG && GetMonData(&party[i], MON_DATA_HP) != 0)
count++;
}
switch (GetBattlerSide(battlerId))
{
case B_SIDE_OPPONENT:
if (count == 1 || gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
return FALSE;
break;
case B_SIDE_PLAYER:
if (count == 1 || (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && count <= 2))
return FALSE;
break;
}
return TRUE;
}
// Return True if the order was changed, and false if the order was not changed(for example because the target would move after the attacker anyway). // Return True if the order was changed, and false if the order was not changed(for example because the target would move after the attacker anyway).
static bool32 ChangeOrderTargetAfterAttacker(void) static bool32 ChangeOrderTargetAfterAttacker(void)
{ {
@ -10795,8 +10802,8 @@ static void Cmd_various(void)
// If Pokémon which set up Sticky Web is not on the field, no Pokémon have their Speed lowered." // If Pokémon which set up Sticky Web is not on the field, no Pokémon have their Speed lowered."
gBattlerAttacker = gBattlerTarget; // Initialize 'fail' condition gBattlerAttacker = gBattlerTarget; // Initialize 'fail' condition
SET_STATCHANGER(STAT_SPEED, 1, TRUE); SET_STATCHANGER(STAT_SPEED, 1, TRUE);
if (gBattleStruct->stickyWebUser != 0xFF) if (gSideTimers[GetBattlerSide(gActiveBattler)].stickyWebBattlerId != 0xFF)
gBattlerAttacker = gBattleStruct->stickyWebUser; gBattlerAttacker = gSideTimers[GetBattlerSide(gActiveBattler)].stickyWebBattlerId;
break; break;
} }
case VARIOUS_CUT_1_3_HP_RAISE_STATS: case VARIOUS_CUT_1_3_HP_RAISE_STATS:
@ -14057,9 +14064,9 @@ static void Cmd_setstickyweb(void)
else else
{ {
gSideStatuses[targetSide] |= SIDE_STATUS_STICKY_WEB; gSideStatuses[targetSide] |= SIDE_STATUS_STICKY_WEB;
gSideTimers[targetSide].stickyWebBattlerId = gBattlerAttacker; // For Mirror Armor
gSideTimers[targetSide].stickyWebBattlerSide = GetBattlerSide(gBattlerAttacker); // For Court Change/Defiant - set this to the user's side gSideTimers[targetSide].stickyWebBattlerSide = GetBattlerSide(gBattlerAttacker); // For Court Change/Defiant - set this to the user's side
gSideTimers[targetSide].stickyWebAmount = 1; gSideTimers[targetSide].stickyWebAmount = 1;
gBattleStruct->stickyWebUser = gBattlerAttacker; // For Mirror Armor
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
} }
} }
@ -14254,10 +14261,11 @@ static void Cmd_setforcedtarget(void)
static void Cmd_setcharge(void) static void Cmd_setcharge(void)
{ {
CMD_ARGS(); CMD_ARGS(u8 battler);
gStatuses3[gBattlerAttacker] |= STATUS3_CHARGED_UP; u8 battler = GetBattlerForBattleScript(cmd->battler);
gDisableStructs[gBattlerAttacker].chargeTimer = 2; gStatuses3[battler] |= STATUS3_CHARGED_UP;
gDisableStructs[battler].chargeTimer = 2;
gBattlescriptCurrInstr++; gBattlescriptCurrInstr++;
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
} }
@ -16292,13 +16300,6 @@ void BS_GetBattlerSide(void)
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
} }
void BS_CanTeleport(void)
{
NATIVE_ARGS(u8 battler);
gBattleCommunication[0] = CanTeleport(cmd->battler);
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_TrySymbiosis(void) void BS_TrySymbiosis(void)
{ {
NATIVE_ARGS(); NATIVE_ARGS();

View File

@ -3389,10 +3389,9 @@ void SetAtkCancellerForCalledMove(void)
gBattleStruct->isAtkCancelerForCalledMove = TRUE; gBattleStruct->isAtkCancelerForCalledMove = TRUE;
} }
u8 AtkCanceller_UnableToUseMove(void) u8 AtkCanceller_UnableToUseMove(u32 moveType)
{ {
u8 effect = 0; u8 effect = 0;
s32 *bideDmg = &gBattleScripting.bideDmg;
do do
{ {
switch (gBattleStruct->atkCancellerTracker) switch (gBattleStruct->atkCancellerTracker)
@ -3653,7 +3652,7 @@ u8 AtkCanceller_UnableToUseMove(void)
if (gTakenDmg[gBattlerAttacker]) if (gTakenDmg[gBattlerAttacker])
{ {
gCurrentMove = MOVE_BIDE; gCurrentMove = MOVE_BIDE;
*bideDmg = gTakenDmg[gBattlerAttacker] * 2; gBattleScripting.bideDmg = gTakenDmg[gBattlerAttacker] * 2;
gBattlerTarget = gTakenDmgByBattler[gBattlerAttacker]; gBattlerTarget = gTakenDmgByBattler[gBattlerAttacker];
if (gAbsentBattlerFlags & gBitTable[gBattlerTarget]) if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
gBattlerTarget = GetMoveTarget(MOVE_BIDE, MOVE_TARGET_SELECTED + 1); gBattlerTarget = GetMoveTarget(MOVE_BIDE, MOVE_TARGET_SELECTED + 1);
@ -3723,8 +3722,6 @@ u8 AtkCanceller_UnableToUseMove(void)
case CANCELLER_POWDER_STATUS: case CANCELLER_POWDER_STATUS:
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_POWDER) if (gBattleMons[gBattlerAttacker].status2 & STATUS2_POWDER)
{ {
u32 moveType;
GET_MOVE_TYPE(gCurrentMove, moveType);
if (moveType == TYPE_FIRE) if (moveType == TYPE_FIRE)
{ {
gProtectStructs[gBattlerAttacker].powderSelfDmg = TRUE; gProtectStructs[gBattlerAttacker].powderSelfDmg = TRUE;
@ -3880,14 +3877,15 @@ u8 AtkCanceller_UnableToUseMove2(void)
bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2) bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2)
{ {
u8 playerId, flankId; u32 i, side, playerId, flankId;
struct Pokemon *party; struct Pokemon *party;
s32 i;
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
return FALSE; return FALSE;
if (BATTLE_TWO_VS_ONE_OPPONENT && GetBattlerSide(battler) == B_SIDE_OPPONENT) side = GetBattlerSide(battler);
if (BATTLE_TWO_VS_ONE_OPPONENT && side == B_SIDE_OPPONENT)
{ {
flankId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); flankId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
playerId = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); playerId = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
@ -3900,9 +3898,7 @@ bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2)
for (i = 0; i < PARTY_SIZE; i++) for (i = 0; i < PARTY_SIZE; i++)
{ {
if (GetMonData(&party[i], MON_DATA_HP) != 0 if (IsValidForBattle(&party[i])
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG
&& i != partyIdBattlerOn1 && i != partyIdBattlerOn2 && i != partyIdBattlerOn1 && i != partyIdBattlerOn2
&& i != *(gBattleStruct->monToSwitchIntoId + flankId) && i != playerId[gBattleStruct->monToSwitchIntoId]) && i != *(gBattleStruct->monToSwitchIntoId + flankId) && i != playerId[gBattleStruct->monToSwitchIntoId])
break; break;
@ -3912,22 +3908,41 @@ bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2)
else if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) else if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
{ {
party = GetBattlerParty(battler); party = GetBattlerParty(battler);
if (side == B_SIDE_OPPONENT && WILD_DOUBLE_BATTLE)
playerId = ((battler & BIT_FLANK) / 2);
for (i = playerId * MULTI_PARTY_SIZE; i < playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE; i++)
{ {
if (GetMonData(&party[i], MON_DATA_HP) != 0 flankId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE playerId = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG)
break; if (partyIdBattlerOn1 == PARTY_SIZE)
partyIdBattlerOn1 = gBattlerPartyIndexes[flankId];
if (partyIdBattlerOn2 == PARTY_SIZE)
partyIdBattlerOn2 = gBattlerPartyIndexes[playerId];
for (i = 0; i < PARTY_SIZE; i++)
{
if (IsValidForBattle(&party[i])
&& i != partyIdBattlerOn1 && i != partyIdBattlerOn2
&& i != *(gBattleStruct->monToSwitchIntoId + flankId) && i != playerId[gBattleStruct->monToSwitchIntoId])
break;
}
return (i == PARTY_SIZE);
}
else
{
playerId = ((battler & BIT_FLANK) / 2);
for (i = playerId * MULTI_PARTY_SIZE; i < playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE; i++)
{
if (IsValidForBattle(&party[i]))
break;
}
return (i == playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE);
} }
return (i == playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE);
} }
else if (gBattleTypeFlags & BATTLE_TYPE_MULTI) else if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
{ {
if (gBattleTypeFlags & BATTLE_TYPE_TOWER_LINK_MULTI) if (gBattleTypeFlags & BATTLE_TYPE_TOWER_LINK_MULTI)
{ {
if (GetBattlerSide(battler) == B_SIDE_PLAYER) if (side == B_SIDE_PLAYER)
{ {
party = gPlayerParty; party = gPlayerParty;
flankId = GetBattlerMultiplayerId(battler); flankId = GetBattlerMultiplayerId(battler);
@ -3951,14 +3966,12 @@ bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2)
for (i = playerId * MULTI_PARTY_SIZE; i < playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE; i++) for (i = playerId * MULTI_PARTY_SIZE; i < playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE; i++)
{ {
if (GetMonData(&party[i], MON_DATA_HP) != 0 if (IsValidForBattle(&party[i]))
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG)
break; break;
} }
return (i == playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE); return (i == playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE);
} }
else if ((gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) && GetBattlerSide(battler) == B_SIDE_OPPONENT) else if ((gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) && side == B_SIDE_OPPONENT)
{ {
party = gEnemyParty; party = gEnemyParty;
@ -3969,16 +3982,14 @@ bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2)
for (i = playerId; i < playerId + MULTI_PARTY_SIZE; i++) for (i = playerId; i < playerId + MULTI_PARTY_SIZE; i++)
{ {
if (GetMonData(&party[i], MON_DATA_HP) != 0 if (IsValidForBattle(&party[i]))
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG)
break; break;
} }
return (i == playerId + 3); return (i == playerId + 3);
} }
else else
{ {
if (GetBattlerSide(battler) == B_SIDE_OPPONENT) if (side == B_SIDE_OPPONENT)
{ {
flankId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); flankId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
playerId = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); playerId = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
@ -3998,9 +4009,7 @@ bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2)
for (i = 0; i < PARTY_SIZE; i++) for (i = 0; i < PARTY_SIZE; i++)
{ {
if (GetMonData(&party[i], MON_DATA_HP) != 0 if (IsValidForBattle(&party[i])
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG
&& i != partyIdBattlerOn1 && i != partyIdBattlerOn2 && i != partyIdBattlerOn1 && i != partyIdBattlerOn2
&& i != *(gBattleStruct->monToSwitchIntoId + flankId) && i != playerId[gBattleStruct->monToSwitchIntoId]) && i != *(gBattleStruct->monToSwitchIntoId + flankId) && i != playerId[gBattleStruct->monToSwitchIntoId])
break; break;
@ -5691,7 +5700,6 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
&& TARGET_TURN_DAMAGED && TARGET_TURN_DAMAGED
&& IsBattlerAlive(gBattlerTarget)) && IsBattlerAlive(gBattlerTarget))
{ {
gBattlerAttacker = gBattlerTarget;
BattleScriptPushCursor(); BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_WindPowerActivates; gBattlescriptCurrInstr = BattleScript_WindPowerActivates;
effect++; effect++;
@ -8004,7 +8012,7 @@ u8 IsMonDisobedient(void)
if (IsBattlerModernFatefulEncounter(gBattlerAttacker)) // only false if illegal Mew or Deoxys if (IsBattlerModernFatefulEncounter(gBattlerAttacker)) // only false if illegal Mew or Deoxys
{ {
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && GetBattlerPosition(gBattlerAttacker) == 2) if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && GetBattlerPosition(gBattlerAttacker) == B_POSITION_PLAYER_RIGHT)
return 0; return 0;
if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
return 0; return 0;
@ -10068,19 +10076,19 @@ bool32 CanMegaEvolve(u8 battlerId)
species = GetMonData(mon, MON_DATA_SPECIES); species = GetMonData(mon, MON_DATA_SPECIES);
itemId = GetMonData(mon, MON_DATA_HELD_ITEM); itemId = GetMonData(mon, MON_DATA_HELD_ITEM);
#if DEBUG_BATTLE_MENU == TRUE
if (gBattleStruct->debugHoldEffects[battlerId])
holdEffect = gBattleStruct->debugHoldEffects[battlerId];
else
#endif
if (itemId == ITEM_ENIGMA_BERRY_E_READER)
holdEffect = gEnigmaBerries[battlerId].holdEffect;
else
holdEffect = ItemId_GetHoldEffect(itemId);
// Check if there is an entry in the evolution table for regular Mega Evolution. // Check if there is an entry in the evolution table for regular Mega Evolution.
if (GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM) != SPECIES_NONE) if (GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM) != SPECIES_NONE)
{ {
#if DEBUG_BATTLE_MENU == TRUE
if (gBattleStruct->debugHoldEffects[battlerId])
holdEffect = gBattleStruct->debugHoldEffects[battlerId];
else
#endif
if (itemId == ITEM_ENIGMA_BERRY_E_READER)
holdEffect = gEnigmaBerries[battlerId].holdEffect;
else
holdEffect = ItemId_GetHoldEffect(itemId);
// Can Mega Evolve via Mega Stone. // Can Mega Evolve via Mega Stone.
if (holdEffect == HOLD_EFFECT_MEGA_STONE) if (holdEffect == HOLD_EFFECT_MEGA_STONE)
return TRUE; return TRUE;
@ -10088,7 +10096,11 @@ bool32 CanMegaEvolve(u8 battlerId)
// Check if there is an entry in the evolution table for Wish Mega Evolution. // Check if there is an entry in the evolution table for Wish Mega Evolution.
if (GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE) != SPECIES_NONE) if (GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE) != SPECIES_NONE)
return TRUE; {
// Can't Wish Mega Evolve if holding a Z Crystal.
if (holdEffect != HOLD_EFFECT_Z_CRYSTAL)
return TRUE;
}
// No checks passed, the mon CAN'T mega evolve. // No checks passed, the mon CAN'T mega evolve.
return FALSE; return FALSE;

View File

@ -159,7 +159,6 @@ void QueueZMove(u8 battlerId, u16 baseMove)
bool32 IsViableZMove(u8 battlerId, u16 move) bool32 IsViableZMove(u8 battlerId, u16 move)
{ {
struct Pokemon *mon; struct Pokemon *mon;
struct MegaEvolutionData *mega = &(((struct ChooseMoveStruct *)(&gBattleResources->bufferA[gActiveBattler][4]))->mega);
u8 battlerPosition = GetBattlerPosition(battlerId); u8 battlerPosition = GetBattlerPosition(battlerId);
u8 partnerPosition = GetBattlerPosition(BATTLE_PARTNER(battlerId)); u8 partnerPosition = GetBattlerPosition(BATTLE_PARTNER(battlerId));
u32 item; u32 item;
@ -185,15 +184,6 @@ bool32 IsViableZMove(u8 battlerId, u16 move)
if ((GetBattlerPosition(battlerId) == B_POSITION_PLAYER_LEFT || (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) && GetBattlerPosition(battlerId) == B_POSITION_PLAYER_RIGHT)) && !CheckBagHasItem(ITEM_Z_POWER_RING, 1)) if ((GetBattlerPosition(battlerId) == B_POSITION_PLAYER_LEFT || (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) && GetBattlerPosition(battlerId) == B_POSITION_PLAYER_RIGHT)) && !CheckBagHasItem(ITEM_Z_POWER_RING, 1))
return FALSE; return FALSE;
if (mega->alreadyEvolved[battlerPosition])
return FALSE; // Trainer has mega evolved
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
if (IsPartnerMonFromSameTrainer(battlerId) && (mega->alreadyEvolved[partnerPosition] || (mega->toEvolve & gBitTable[BATTLE_PARTNER(battlerId)])))
return FALSE; // Partner has mega evolved or is about to mega evolve
}
#if DEBUG_BATTLE_MENU == TRUE #if DEBUG_BATTLE_MENU == TRUE
if (gBattleStruct->debugHoldEffects[battlerId]) if (gBattleStruct->debugHoldEffects[battlerId])
holdEffect = gBattleStruct->debugHoldEffects[battlerId]; holdEffect = gBattleStruct->debugHoldEffects[battlerId];
@ -355,9 +345,12 @@ bool32 IsZMoveTriggerSpriteActive(void)
void HideZMoveTriggerSprite(void) void HideZMoveTriggerSprite(void)
{ {
struct Sprite *sprite = &gSprites[gBattleStruct->zmove.triggerSpriteId]; struct Sprite *sprite;
sprite->tHide = TRUE;
gBattleStruct->zmove.viable = FALSE; gBattleStruct->zmove.viable = FALSE;
if (gBattleStruct->zmove.triggerSpriteId >= MAX_SPRITES)
return;
sprite = &gSprites[gBattleStruct->zmove.triggerSpriteId];
sprite->tHide = TRUE;
} }
static void ShowZMoveTriggerSprite(u8 battlerId) static void ShowZMoveTriggerSprite(u8 battlerId)

View File

@ -117,7 +117,7 @@ static const struct WindowTemplate sBerryFixWindowTemplates[] = {
DUMMY_WIN_TEMPLATE DUMMY_WIN_TEMPLATE
}; };
static const u16 sBerryFixPalColors[] = { static const u16 ALIGNED(4) sBerryFixPalColors[] = {
RGB_WHITE, RGB_WHITE, RGB(12, 12, 12), RGB(26, 26, 25), RGB_WHITE, RGB_WHITE, RGB(12, 12, 12), RGB(26, 26, 25),
RGB(28, 1, 1), RGB(31, 23, 14), RGB(4, 19, 1), RGB(18, 30, 18), RGB(28, 1, 1), RGB(31, 23, 14), RGB(4, 19, 1), RGB(18, 30, 18),
RGB(6, 10, 25), RGB(20, 24, 30), RGB_WHITE, RGB(12, 12, 12), RGB(6, 10, 25), RGB(20, 24, 30), RGB_WHITE, RGB(12, 12, 12),

View File

@ -1301,8 +1301,8 @@ static void Task_ReadyStartLinkContest(u8 taskId)
static bool8 SetupContestGraphics(u8 *stateVar) static bool8 SetupContestGraphics(u8 *stateVar)
{ {
u16 tempPalette1[16]; u16 ALIGNED(4) tempPalette1[16];
u16 tempPalette2[16]; u16 ALIGNED(4) tempPalette2[16];
switch (*stateVar) switch (*stateVar)
{ {

View File

@ -6,7 +6,7 @@
#define EVO_HELD_ITEM_FIELD_FUNC ItemUseOutOfBattle_CannotUse #define EVO_HELD_ITEM_FIELD_FUNC ItemUseOutOfBattle_CannotUse
#endif #endif
#if I_GEM_BOOST_POWER >= GEN_5 #if I_GEM_BOOST_POWER >= GEN_6
#define GEM_BOOST_PARAM 30 #define GEM_BOOST_PARAM 30
#else #else
#define GEM_BOOST_PARAM 50 #define GEM_BOOST_PARAM 50

View File

@ -412,7 +412,7 @@ static void Debug_AddDaycareSteps(u16 numSteps)
u8 GetNumLevelsGainedFromDaycare(void) u8 GetNumLevelsGainedFromDaycare(void)
{ {
if (GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[gSpecialVar_0x8004], MON_DATA_SPECIES) != 0) if (GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[gSpecialVar_0x8004].mon, MON_DATA_SPECIES) != 0)
return GetNumLevelsGainedForDaycareMon(&gSaveBlock1Ptr->daycare.mons[gSpecialVar_0x8004]); return GetNumLevelsGainedForDaycareMon(&gSaveBlock1Ptr->daycare.mons[gSpecialVar_0x8004]);
return 0; return 0;

View File

@ -1916,7 +1916,7 @@ static void CopyPalette(u16 *dest, u16 pal)
static void CopyTile(u8 *dest, u16 tile) static void CopyTile(u8 *dest, u16 tile)
{ {
u8 buffer[TILE_SIZE_4BPP]; u8 ALIGNED(4) buffer[TILE_SIZE_4BPP];
u16 mode; u16 mode;
u16 i; u16 i;

View File

@ -61,7 +61,7 @@ static void None_Main(void);
static u8 None_Finish(void); static u8 None_Finish(void);
EWRAM_DATA struct Weather gWeather = {0}; EWRAM_DATA struct Weather gWeather = {0};
EWRAM_DATA static u8 sFieldEffectPaletteColorMapTypes[32] = {0}; EWRAM_DATA static u8 ALIGNED(2) sFieldEffectPaletteColorMapTypes[32] = {0};
static const u8 *sPaletteColorMapTypes; static const u8 *sPaletteColorMapTypes;
@ -111,7 +111,7 @@ void (*const gWeatherPalStateFuncs[])(void) =
// This table specifies which of the color maps should be // This table specifies which of the color maps should be
// applied to each of the background and sprite palettes. // applied to each of the background and sprite palettes.
static const u8 sBasePaletteColorMapTypes[32] = static const u8 ALIGNED(2) sBasePaletteColorMapTypes[32] =
{ {
// background palettes // background palettes
COLOR_MAP_DARK_CONTRAST, COLOR_MAP_DARK_CONTRAST,
@ -149,7 +149,7 @@ static const u8 sBasePaletteColorMapTypes[32] =
COLOR_MAP_DARK_CONTRAST, COLOR_MAP_DARK_CONTRAST,
}; };
const u16 gFogPalette[] = INCBIN_U16("graphics/weather/fog.gbapal"); const u16 ALIGNED(4) gFogPalette[] = INCBIN_U16("graphics/weather/fog.gbapal");
void StartWeather(void) void StartWeather(void)
{ {

View File

@ -25,7 +25,7 @@ struct ConnectionFlags
u8 east:1; u8 east:1;
}; };
EWRAM_DATA static u16 sBackupMapData[MAX_MAP_DATA_SIZE] = {0}; EWRAM_DATA static u16 ALIGNED(4) sBackupMapData[MAX_MAP_DATA_SIZE] = {0};
EWRAM_DATA struct MapHeader gMapHeader = {0}; EWRAM_DATA struct MapHeader gMapHeader = {0};
EWRAM_DATA struct Camera gCamera = {0}; EWRAM_DATA struct Camera gCamera = {0};
EWRAM_DATA static struct ConnectionFlags sMapConnectionFlags = {0}; EWRAM_DATA static struct ConnectionFlags sMapConnectionFlags = {0};

View File

@ -1709,8 +1709,8 @@ const u32 gRouletteMultiplier_Gfx[] = INCBIN_U32("graphics/roulette/multiplier.4
const u16 gFrontierFactorySelectMenu_Pal[] = INCBIN_U16("graphics/battle_frontier/factory_menu1.gbapal"); const u16 gFrontierFactorySelectMenu_Pal[] = INCBIN_U16("graphics/battle_frontier/factory_menu1.gbapal");
const u16 gFrontierFactorySelectMenu_Pal2[] = INCBIN_U16("graphics/battle_frontier/factory_menu2.gbapal"); const u16 gFrontierFactorySelectMenu_Pal2[] = INCBIN_U16("graphics/battle_frontier/factory_menu2.gbapal");
const u8 gFrontierFactorySelectMenu_Gfx[] = INCBIN_U8("graphics/battle_frontier/factory_menu1.4bpp"); const u16 gFrontierFactorySelectMenu_Gfx[] = INCBIN_U16("graphics/battle_frontier/factory_menu1.4bpp");
const u8 gFrontierFactorySelectMenu_Gfx2[] = INCBIN_U8("graphics/battle_frontier/factory_menu2.4bpp"); const u16 gFrontierFactorySelectMenu_Gfx2[] = INCBIN_U16("graphics/battle_frontier/factory_menu2.4bpp");
const u16 gFrontierFactorySelectMenu_Tilemap[] = INCBIN_U16("graphics/battle_frontier/factory_menu.bin"); const u16 gFrontierFactorySelectMenu_Tilemap[] = INCBIN_U16("graphics/battle_frontier/factory_menu.bin");

View File

@ -1096,6 +1096,10 @@ static u8 SetUpCopyrightScreen(void)
REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON; REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON;
SetSerialCallback(SerialCB_CopyrightScreen); SetSerialCallback(SerialCB_CopyrightScreen);
GameCubeMultiBoot_Init(&gMultibootProgramStruct); GameCubeMultiBoot_Init(&gMultibootProgramStruct);
// REG_DISPCNT needs to be overwritten the second time, because otherwise the intro won't show up on VBA 1.7.2 and John GBA Lite emulators.
// The REG_DISPCNT overwrite is NOT needed in m-GBA, No$GBA, VBA 1.8.0, My Boy and Pizza Boy GBA emulators.
case 1:
REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON;
default: default:
UpdatePaletteFade(); UpdatePaletteFade();
gMain.state++; gMain.state++;

View File

@ -2436,16 +2436,16 @@ static void PrintPocketNames(const u8 *pocketName1, const u8 *pocketName2)
static void CopyPocketNameToWindow(u32 a) static void CopyPocketNameToWindow(u32 a)
{ {
u8 (* tileDataBuffer)[32][32]; u8 (*tileDataBuffer)[32][32];
u8 *windowTileData; u8 *windowTileData;
int b; int b;
if (a > 8) if (a > 8)
a = 8; a = 8;
tileDataBuffer = &gBagMenu->pocketNameBuffer; tileDataBuffer = &gBagMenu->pocketNameBuffer;
windowTileData = (u8 *)GetWindowAttribute(2, WINDOW_TILE_DATA); windowTileData = (u8 *)GetWindowAttribute(2, WINDOW_TILE_DATA);
CpuCopy32(tileDataBuffer[0][a], windowTileData, 0x100); // Top half of pocket name CpuCopy32(&tileDataBuffer[0][a], windowTileData, 0x100); // Top half of pocket name
b = a + 16; b = a + 16;
CpuCopy32(tileDataBuffer[0][b], windowTileData + 0x100, 0x100); // Bottom half of pocket name CpuCopy32(&tileDataBuffer[0][b], windowTileData + 0x100, 0x100); // Bottom half of pocket name
CopyWindowToVram(WIN_POCKET_NAME, COPYWIN_GFX); CopyWindowToVram(WIN_POCKET_NAME, COPYWIN_GFX);
} }

View File

@ -78,7 +78,7 @@ bool8 gRemoteLinkPlayersNotReceived[MAX_LINK_PLAYERS];
u8 gBlockReceivedStatus[MAX_LINK_PLAYERS]; u8 gBlockReceivedStatus[MAX_LINK_PLAYERS];
u32 gLinkFiller2; u32 gLinkFiller2;
u16 gLinkHeldKeys; u16 gLinkHeldKeys;
u16 gRecvCmds[MAX_RFU_PLAYERS][CMD_LENGTH]; u16 ALIGNED(4) gRecvCmds[MAX_RFU_PLAYERS][CMD_LENGTH];
u32 gLinkStatus; u32 gLinkStatus;
bool8 gLinkDummy1; // Never read bool8 gLinkDummy1; // Never read
bool8 gLinkDummy2; // Never read bool8 gLinkDummy2; // Never read

View File

@ -75,7 +75,7 @@ static void Task_FossilFallAndSink(u8);
static void SpriteCB_FallingFossil(struct Sprite *); static void SpriteCB_FallingFossil(struct Sprite *);
static void UpdateDisintegrationEffect(u8 *, u16, u8, u8, u8); static void UpdateDisintegrationEffect(u8 *, u16, u8, u8, u8);
static const u8 sBlankTile_Gfx[32] = {0}; static const u8 ALIGNED(2) sBlankTile_Gfx[32] = {0};
static const u8 sMirageTower_Gfx[] = INCBIN_U8("graphics/misc/mirage_tower.4bpp"); static const u8 sMirageTower_Gfx[] = INCBIN_U8("graphics/misc/mirage_tower.4bpp");
static const u16 sMirageTowerTilemap[] = INCBIN_U16("graphics/misc/mirage_tower.bin"); static const u16 sMirageTowerTilemap[] = INCBIN_U16("graphics/misc/mirage_tower.bin");
static const u16 sFossil_Pal[] = INCBIN_U16("graphics/object_events/pics/misc/fossil.gbapal"); // Unused static const u16 sFossil_Pal[] = INCBIN_U16("graphics/object_events/pics/misc/fossil.gbapal"); // Unused

View File

@ -64,7 +64,7 @@ static EWRAM_DATA struct PaletteStruct sPaletteStructs[NUM_PALETTE_STRUCTS] = {0
EWRAM_DATA struct PaletteFadeControl gPaletteFade = {0}; EWRAM_DATA struct PaletteFadeControl gPaletteFade = {0};
static EWRAM_DATA u32 sFiller = 0; static EWRAM_DATA u32 sFiller = 0;
static EWRAM_DATA u32 sPlttBufferTransferPending = 0; static EWRAM_DATA u32 sPlttBufferTransferPending = 0;
EWRAM_DATA u8 gPaletteDecompressionBuffer[PLTT_SIZE] = {0}; EWRAM_DATA u8 ALIGNED(2) gPaletteDecompressionBuffer[PLTT_SIZE] = {0};
static const struct PaletteStructTemplate sDummyPaletteStructTemplate = { static const struct PaletteStructTemplate sDummyPaletteStructTemplate = {
.id = 0xFFFF, .id = 0xFFFF,

View File

@ -1218,13 +1218,13 @@ static u8 LaunchBallFadeMonTaskForPokeball(bool8 unFadeLater, u8 spritePalNum, u
#define sTrigIdx data[7] #define sTrigIdx data[7]
// Pokeball in Birch intro, and when receiving via trade // Pokeball in Birch intro, and when receiving via trade
void CreatePokeballSpriteToReleaseMon(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subpriortiy, u8 delay, u32 fadePalettes, u16 species) void CreatePokeballSpriteToReleaseMon(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subpriority, u8 delay, u32 fadePalettes, u16 species)
{ {
u8 spriteId; u8 spriteId;
LoadCompressedSpriteSheetUsingHeap(&gBallSpriteSheets[BALL_POKE]); LoadCompressedSpriteSheetUsingHeap(&gBallSpriteSheets[BALL_POKE]);
LoadCompressedSpritePaletteUsingHeap(&gBallSpritePalettes[BALL_POKE]); LoadCompressedSpritePaletteUsingHeap(&gBallSpritePalettes[BALL_POKE]);
spriteId = CreateSprite(&gBallSpriteTemplates[BALL_POKE], x, y, subpriortiy); spriteId = CreateSprite(&gBallSpriteTemplates[BALL_POKE], x, y, subpriority);
gSprites[spriteId].sMonSpriteId = monSpriteId; gSprites[spriteId].sMonSpriteId = monSpriteId;
gSprites[spriteId].sFinalMonX = gSprites[monSpriteId].x; gSprites[spriteId].sFinalMonX = gSprites[monSpriteId].x;

View File

@ -4537,7 +4537,7 @@ static void PrintDecimalNum(u8 windowId, u16 num, u8 left, u8 top)
static void DrawFootprint(u8 windowId, u16 dexNum) static void DrawFootprint(u8 windowId, u16 dexNum)
{ {
u8 footprint4bpp[TILE_SIZE_4BPP * NUM_FOOTPRINT_TILES]; u8 ALIGNED(4) footprint4bpp[TILE_SIZE_4BPP * NUM_FOOTPRINT_TILES];
const u8 *footprintGfx = gMonFootprintTable[NationalPokedexNumToSpecies(dexNum)]; const u8 *footprintGfx = gMonFootprintTable[NationalPokedexNumToSpecies(dexNum)];
u32 i, j, tileIdx = 0; u32 i, j, tileIdx = 0;

View File

@ -8,7 +8,7 @@
static EWRAM_DATA u8 *sPokedexAreaMapBgNum = NULL; static EWRAM_DATA u8 *sPokedexAreaMapBgNum = NULL;
static const u16 sPokedexAreaMap_Pal[] = INCBIN_U16("graphics/pokedex/region_map.gbapal"); static const u16 ALIGNED(4) sPokedexAreaMap_Pal[] = INCBIN_U16("graphics/pokedex/region_map.gbapal");
static const u32 sPokedexAreaMap_Gfx[] = INCBIN_U32("graphics/pokedex/region_map.8bpp.lz"); static const u32 sPokedexAreaMap_Gfx[] = INCBIN_U32("graphics/pokedex/region_map.8bpp.lz");
static const u32 sPokedexAreaMap_Tilemap[] = INCBIN_U32("graphics/pokedex/region_map.bin.lz"); static const u32 sPokedexAreaMap_Tilemap[] = INCBIN_U32("graphics/pokedex/region_map.bin.lz");
static const u32 sPokedexAreaMapAffine_Gfx[] = INCBIN_U32("graphics/pokedex/region_map_affine.8bpp.lz"); static const u32 sPokedexAreaMapAffine_Gfx[] = INCBIN_U32("graphics/pokedex/region_map_affine.8bpp.lz");

View File

@ -4627,7 +4627,11 @@ static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 perso
return substruct; return substruct;
} }
u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data) /* GameFreak called GetMonData with either 2 or 3 arguments, for type
* safety we have a GetMonData macro (in include/pokemon.h) which
* dispatches to either GetMonData2 or GetMonData3 based on the number
* of arguments. */
u32 GetMonData3(struct Pokemon *mon, s32 field, u8 *data)
{ {
u32 ret; u32 ret;
@ -4685,7 +4689,13 @@ u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data)
return ret; return ret;
} }
u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data) u32 GetMonData2(struct Pokemon *mon, s32 field) __attribute__((alias("GetMonData3")));
/* GameFreak called GetBoxMonData with either 2 or 3 arguments, for type
* safety we have a GetBoxMonData macro (in include/pokemon.h) which
* dispatches to either GetBoxMonData2 or GetBoxMonData3 based on the
* number of arguments. */
u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data)
{ {
s32 i; s32 i;
u32 retVal = 0; u32 retVal = 0;
@ -5041,6 +5051,8 @@ u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data)
return retVal; return retVal;
} }
u32 GetBoxMonData2(struct BoxPokemon *boxMon, s32 field) __attribute__((alias("GetBoxMonData3")));
#define SET8(lhs) (lhs) = *data #define SET8(lhs) (lhs) = *data
#define SET16(lhs) (lhs) = data[0] + (data[1] << 8) #define SET16(lhs) (lhs) = data[0] + (data[1] << 8)
#define SET32(lhs) (lhs) = data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24) #define SET32(lhs) (lhs) = data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24)

View File

@ -552,8 +552,8 @@ struct PokemonStorageSystemData
u16 *displayMonTilePtr; u16 *displayMonTilePtr;
struct Sprite *displayMonSprite; struct Sprite *displayMonSprite;
u16 displayMonPalBuffer[0x40]; u16 displayMonPalBuffer[0x40];
u8 tileBuffer[MON_PIC_SIZE * MAX_MON_PIC_FRAMES]; u8 ALIGNED(4) tileBuffer[MON_PIC_SIZE * MAX_MON_PIC_FRAMES];
u8 itemIconBuffer[0x800]; u8 ALIGNED(4) itemIconBuffer[0x800];
u8 wallpaperBgTilemapBuffer[0x1000]; u8 wallpaperBgTilemapBuffer[0x1000];
u8 displayMenuTilemapBuffer[0x800]; u8 displayMenuTilemapBuffer[0x800];
}; };
@ -10150,7 +10150,7 @@ void UpdateSpeciesSpritePSS(struct BoxPokemon *boxMon)
{ {
DestroyBoxMonIcon(sStorage->boxMonsSprites[sCursorPosition]); DestroyBoxMonIcon(sStorage->boxMonsSprites[sCursorPosition]);
CreateBoxMonIconAtPos(sCursorPosition); CreateBoxMonIconAtPos(sCursorPosition);
SetBoxMonIconObjMode(sCursorPosition, GetMonData(boxMon, MON_DATA_HELD_ITEM) == ITEM_NONE); SetBoxMonIconObjMode(sCursorPosition, GetBoxMonData(boxMon, MON_DATA_HELD_ITEM) == ITEM_NONE);
} }
} }
sJustOpenedBag = FALSE; sJustOpenedBag = FALSE;

View File

@ -116,10 +116,12 @@ static const LoopedTask sLoopedTaskFuncs[] =
[CONDITION_FUNC_CLOSE_MARKINGS] = LoopedTask_CloseMonMarkingsWindow [CONDITION_FUNC_CLOSE_MARKINGS] = LoopedTask_CloseMonMarkingsWindow
}; };
typedef u8 ALIGNED(4) TilemapBuffer[BG_SCREEN_SIZE];
struct Pokenav_ConditionMenuGfx struct Pokenav_ConditionMenuGfx
{ {
u32 loopedTaskId; u32 loopedTaskId;
u8 tilemapBuffers[3][BG_SCREEN_SIZE]; TilemapBuffer tilemapBuffers[3];
u8 filler[2]; u8 filler[2];
u8 partyPokeballSpriteIds[PARTY_SIZE + 1]; u8 partyPokeballSpriteIds[PARTY_SIZE + 1];
u32 (*callback)(void); u32 (*callback)(void);

View File

@ -35,7 +35,7 @@ struct Pokenav_RegionMapGfx
u32 loopTaskId; u32 loopTaskId;
u16 infoWindowId; u16 infoWindowId;
struct Sprite *cityZoomTextSprites[3]; struct Sprite *cityZoomTextSprites[3];
u8 tilemapBuffer[BG_SCREEN_SIZE]; u8 ALIGNED(2) tilemapBuffer[BG_SCREEN_SIZE];
u8 cityZoomPics[NUM_CITY_MAPS][200]; u8 cityZoomPics[NUM_CITY_MAPS][200];
}; };

View File

@ -60,10 +60,12 @@ enum
#define MAX_SMOKE 10 #define MAX_SMOKE 10
typedef u8 ALIGNED(4) TilemapBuffer[BG_SCREEN_SIZE];
struct RayquazaScene struct RayquazaScene
{ {
MainCallback exitCallback; MainCallback exitCallback;
u8 tilemapBuffers[4][BG_SCREEN_SIZE]; TilemapBuffer tilemapBuffers[4];
u16 unk; // never read u16 unk; // never read
u8 animId; u8 animId;
bool8 endEarly; bool8 endEarly;

View File

@ -13,7 +13,7 @@ static void CopyValue32Bit(void);
// Per-scanline register values. // Per-scanline register values.
// This is double buffered so that it can be safely written to at any time // This is double buffered so that it can be safely written to at any time
// without overwriting the buffer that the DMA is currently reading // without overwriting the buffer that the DMA is currently reading
EWRAM_DATA u16 gScanlineEffectRegBuffers[2][0x3C0] = {0}; EWRAM_DATA u16 ALIGNED(4) gScanlineEffectRegBuffers[2][0x3C0] = {0};
EWRAM_DATA struct ScanlineEffect gScanlineEffect = {0}; EWRAM_DATA struct ScanlineEffect gScanlineEffect = {0};
EWRAM_DATA static bool8 sShouldStopWaveTask = FALSE; EWRAM_DATA static bool8 sShouldStopWaveTask = FALSE;

0
src/script_pokemon_util.c Executable file → Normal file
View File

View File

@ -158,7 +158,7 @@ void CopySpriteTiles(u8 shape, u8 size, u8 *tiles, u16 *tilemap, u8 *output)
{ {
u8 x, y; u8 x, y;
s8 i, j; s8 i, j;
u8 xflip[32]; u8 ALIGNED(4) xflip[32];
u8 h = sSpriteDimensions[shape][size][1]; u8 h = sSpriteDimensions[shape][size][1];
u8 w = sSpriteDimensions[shape][size][0]; u8 w = sSpriteDimensions[shape][size][0];

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
ASSUMPTIONS ASSUMPTIONS
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
ASSUMPTIONS ASSUMPTIONS
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Blaze boosts Fire-type moves in a pinch", s16 damage) SINGLE_BATTLE_TEST("Blaze boosts Fire-type moves in a pinch", s16 damage)
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Clear Body prevents intimidate") SINGLE_BATTLE_TEST("Clear Body prevents intimidate")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Cloud Nine prevents weather effects") SINGLE_BATTLE_TEST("Cloud Nine prevents weather effects")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Compound Eyes raises accuracy") SINGLE_BATTLE_TEST("Compound Eyes raises accuracy")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
ASSUMPTIONS ASSUMPTIONS
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Cute Charm inflicts infatuation on contact") SINGLE_BATTLE_TEST("Cute Charm inflicts infatuation on contact")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Damp prevents explosion-like moves from enemies") SINGLE_BATTLE_TEST("Damp prevents explosion-like moves from enemies")
{ {

View File

@ -0,0 +1,67 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_WATER_GUN].power != 0);
ASSUME(gBattleMoves[MOVE_WATER_GUN].type == TYPE_WATER);
}
SINGLE_BATTLE_TEST("Desolate Land blocks damaging Water-type moves")
{
GIVEN {
PLAYER(SPECIES_GROUDON) {Item(ITEM_RED_ORB);}
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_WATER_GUN); }
TURN { MOVE(opponent, MOVE_WATER_GUN); }
} SCENE {
MESSAGE("Foe Wobbuffet used Water Gun!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, opponent);
MESSAGE("The Water-type attack evaporated in the harsh sunlight!");
NOT HP_BAR(player);
MESSAGE("Foe Wobbuffet used Water Gun!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, opponent);
MESSAGE("The Water-type attack evaporated in the harsh sunlight!");
NOT HP_BAR(player);
} THEN {
EXPECT_EQ(player->hp, player->maxHP);
}
}
DOUBLE_BATTLE_TEST("Desolate Land blocks damaging Water-type moves and prints the message only once with moves hitting multiple targets")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_SURF].power != 0);
ASSUME(gBattleMoves[MOVE_SURF].type == TYPE_WATER);
ASSUME(gBattleMoves[MOVE_SURF].target == MOVE_TARGET_FOES_AND_ALLY);
PLAYER(SPECIES_GROUDON) {Item(ITEM_RED_ORB); {Speed(5);}}
PLAYER(SPECIES_WOBBUFFET) {Speed(5);}
OPPONENT(SPECIES_WOBBUFFET) {Speed(10);}
OPPONENT(SPECIES_WOBBUFFET) {Speed(8);}
} WHEN {
TURN { MOVE(opponentLeft, MOVE_SURF); }
} SCENE {
MESSAGE("Foe Wobbuffet used Surf!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SURF, opponentLeft);
MESSAGE("The Water-type attack evaporated in the harsh sunlight!");
NOT MESSAGE("The Water-type attack evaporated in the harsh sunlight!");
} THEN {
EXPECT_EQ(playerLeft->hp, playerLeft->maxHP);
EXPECT_EQ(playerRight->hp, playerRight->maxHP);
EXPECT_EQ(opponentRight->hp, opponentRight->maxHP);
}
}
SINGLE_BATTLE_TEST("Desolate Land does not block a move if pokemon is asleep and uses a Water-type move") // Sleep/confusion/paralysis all happen before the check for primal weather
{
GIVEN {
PLAYER(SPECIES_GROUDON) {Item(ITEM_RED_ORB);}
OPPONENT(SPECIES_WOBBUFFET) {Status1(STATUS1_SLEEP);}
} WHEN {
TURN { MOVE(opponent, MOVE_WATER_GUN); }
} SCENE {
NOT MESSAGE("The Water-type attack evaporated in the harsh sunlight!");
MESSAGE("Foe Wobbuffet is fast asleep.");
}
}

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
ASSUMPTIONS ASSUMPTIONS
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Drizzle summons rain", s16 damage) SINGLE_BATTLE_TEST("Drizzle summons rain", s16 damage)
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Dry Skin causes 1/8th Max HP damage in Sun") SINGLE_BATTLE_TEST("Dry Skin causes 1/8th Max HP damage in Sun")
{ {

View File

@ -0,0 +1,56 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Electromorphosis sets up Charge when hit by any move")
{
s16 dmgBefore, dmgAfter;
u16 move;
PARAMETRIZE {move = MOVE_TACKLE; }
PARAMETRIZE {move = MOVE_GUST; }
GIVEN {
ASSUME(gBattleMoves[MOVE_TACKLE].power != 0);
ASSUME(gBattleMoves[MOVE_GUST].power != 0);
ASSUME(gBattleMoves[MOVE_GUST].split == SPLIT_SPECIAL);
ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL);
ASSUME(gBattleMoves[MOVE_THUNDERBOLT].power != 0);
ASSUME(gBattleMoves[MOVE_THUNDERBOLT].type == TYPE_ELECTRIC);
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_ELECTROMORPHOSIS); Speed(10); }
OPPONENT(SPECIES_WOBBUFFET) {Ability(ABILITY_LIMBER); Speed(5) ;} // Limber, so it doesn't get paralyzed.
}
WHEN {
TURN { MOVE(player, MOVE_THUNDERBOLT), MOVE(opponent, move); }
TURN { MOVE(player, MOVE_THUNDERBOLT), MOVE(opponent, move); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
HP_BAR(opponent, captureDamage: &dmgBefore);
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
HP_BAR(player);
ABILITY_POPUP(player, ABILITY_ELECTROMORPHOSIS);
if (move == MOVE_TACKLE) {
MESSAGE("Being hit by Tackle charged Wobbuffet with power!");
}
else {
MESSAGE("Being hit by Gust charged Wobbuffet with power!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
HP_BAR(opponent, captureDamage: &dmgAfter);
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
HP_BAR(player);
ABILITY_POPUP(player, ABILITY_ELECTROMORPHOSIS);
if (move == MOVE_TACKLE) {
MESSAGE("Being hit by Tackle charged Wobbuffet with power!");
}
else {
MESSAGE("Being hit by Gust charged Wobbuffet with power!");
}
}
THEN {
EXPECT_MUL_EQ(dmgBefore, Q_4_12(2.0), dmgAfter);
}
}

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Flame Body inflicts burn on contact") SINGLE_BATTLE_TEST("Flame Body inflicts burn on contact")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Flower Gift transforms Cherrim in harsh sunlight") SINGLE_BATTLE_TEST("Flower Gift transforms Cherrim in harsh sunlight")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Forecast transforms Castform in weather from an opponent's move") SINGLE_BATTLE_TEST("Forecast transforms Castform in weather from an opponent's move")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Full Metal Body prevents intimidate") SINGLE_BATTLE_TEST("Full Metal Body prevents intimidate")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Hunger Switch switches Morpeko's forms at the end of the turn") SINGLE_BATTLE_TEST("Hunger Switch switches Morpeko's forms at the end of the turn")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Hydration cures non-volatile Status conditions if it is raining") SINGLE_BATTLE_TEST("Hydration cures non-volatile Status conditions if it is raining")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Hyper Cutter prevents intimidate") SINGLE_BATTLE_TEST("Hyper Cutter prevents intimidate")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Ice Body prevents damage from hail") SINGLE_BATTLE_TEST("Ice Body prevents damage from hail")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Immunity prevents Poison Sting poison") SINGLE_BATTLE_TEST("Immunity prevents Poison Sting poison")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Inner Focus prevents intimidate") SINGLE_BATTLE_TEST("Inner Focus prevents intimidate")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Insomnia prevents sleep") SINGLE_BATTLE_TEST("Insomnia prevents sleep")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
ASSUMPTIONS ASSUMPTIONS
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Leaf Guard prevents non-volatile status conditions in sun") SINGLE_BATTLE_TEST("Leaf Guard prevents non-volatile status conditions in sun")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Limber prevents paralysis") SINGLE_BATTLE_TEST("Limber prevents paralysis")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Magic Bounce bounces back status moves") SINGLE_BATTLE_TEST("Magic Bounce bounces back status moves")

View File

@ -0,0 +1,202 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(P_GEN_8_POKEMON == TRUE);
}
SINGLE_BATTLE_TEST("Mirror Armor lowers a stat of the attacking pokemon")
{
u16 move, statId;
PARAMETRIZE { move = MOVE_LEER; statId = STAT_DEF; }
PARAMETRIZE { move = MOVE_GROWL; statId = STAT_ATK; }
PARAMETRIZE { move = MOVE_SWEET_SCENT; statId = STAT_EVASION; }
PARAMETRIZE { move = MOVE_SAND_ATTACK; statId = STAT_ACC; }
PARAMETRIZE { move = MOVE_CONFIDE; statId = STAT_SPATK; }
PARAMETRIZE { move = MOVE_FAKE_TEARS; statId = STAT_SPDEF; }
GIVEN {
PLAYER(SPECIES_CORVIKNIGHT) {Ability(ABILITY_MIRROR_ARMOR);}
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(opponent, move); }
} SCENE {
ABILITY_POPUP(player, ABILITY_MIRROR_ARMOR);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
switch (statId)
{
case STAT_DEF:
MESSAGE("Foe Wynaut's Defense fell!");
break;
case STAT_ATK:
MESSAGE("Foe Wynaut's Attack fell!");
break;
case STAT_EVASION:
MESSAGE("Foe Wynaut's evasiveness harshly fell!");
break;
case STAT_ACC:
MESSAGE("Foe Wynaut's accuracy fell!");
break;
case STAT_SPATK:
MESSAGE("Foe Wynaut's Sp. Atk fell!");
break;
case STAT_SPDEF:
MESSAGE("Foe Wynaut's Sp. Def harshly fell!");
break;
}
} THEN {
EXPECT_EQ(player->statStages[statId], DEFAULT_STAT_STAGE);
EXPECT_EQ(opponent->statStages[statId], (statId == STAT_SPDEF || statId == STAT_EVASION) ? DEFAULT_STAT_STAGE - 2 : DEFAULT_STAT_STAGE - 1);
}
}
SINGLE_BATTLE_TEST("Mirror Armor triggers even if the attacking Pokemon also has Mirror Armor ability")
{
GIVEN {
PLAYER(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); }
OPPONENT(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); }
} WHEN {
TURN { MOVE(opponent, MOVE_LEER); }
} SCENE {
MESSAGE("Foe Corviknigh used Leer!");
ABILITY_POPUP(player, ABILITY_MIRROR_ARMOR);
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Corviknigh's Defense fell!");
} THEN {
EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE);
EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE - 1);
}
}
SINGLE_BATTLE_TEST("Mirror Armor doesn't lower the stats of an attacking Pokemon with the Clear Body ability")
{
GIVEN {
PLAYER(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); }
OPPONENT(SPECIES_WYNAUT) { Ability(ABILITY_CLEAR_BODY); }
} WHEN {
TURN { MOVE(opponent, MOVE_LEER); }
} SCENE {
MESSAGE("Foe Wynaut used Leer!");
ABILITY_POPUP(player, ABILITY_MIRROR_ARMOR);
ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY);
MESSAGE("Foe Wynaut's Clear Body prevents stat loss!");
} THEN {
EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE);
EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE);
}
}
SINGLE_BATTLE_TEST("Mirror Armor lowers the Attack of Pokemon with Intimidate")
{
GIVEN {
PLAYER(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); }
OPPONENT(SPECIES_GYARADOS) { Ability(ABILITY_INTIMIDATE); }
} WHEN {
TURN {}
} SCENE {
ABILITY_POPUP(opponent, ABILITY_INTIMIDATE);
ABILITY_POPUP(player, ABILITY_MIRROR_ARMOR);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Gyarados's Attack fell!");
} THEN {
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1);
}
}
// Unsure whether this should or should not fail, as Showdown has conflicting information. Needs testing in gen8 games.
SINGLE_BATTLE_TEST("Mirror Armor doesn't lower the stats of an attacking Pokemon behind Substitute")
{
KNOWN_FAILING;
GIVEN {
PLAYER(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); }
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(opponent, MOVE_SUBSTITUTE); }
TURN { MOVE(opponent, MOVE_LEER); }
} SCENE {
MESSAGE("Foe Wynaut used Substitute!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, opponent);
MESSAGE("Foe Wynaut used Leer!");
ABILITY_POPUP(player, ABILITY_MIRROR_ARMOR);
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
} THEN {
EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE);
EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE);
}
}
SINGLE_BATTLE_TEST("Mirror Armor raises the stat of an attacking Pokemon with Contrary")
{
GIVEN {
PLAYER(SPECIES_CORVIKNIGHT) {Ability(ABILITY_MIRROR_ARMOR);}
OPPONENT(SPECIES_SHUCKLE) {Ability(ABILITY_CONTRARY);}
} WHEN {
TURN { MOVE(opponent, MOVE_LEER); }
} SCENE {
MESSAGE("Foe Shuckle used Leer!");
ABILITY_POPUP(player, ABILITY_MIRROR_ARMOR);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Shuckle's Defense rose!");
} THEN {
EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE);
EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1);
}
}
SINGLE_BATTLE_TEST("Mirror Armor doesn't lower the stat of the attacking Pokemon if it is already at -6")
{
GIVEN {
PLAYER(SPECIES_CORVIKNIGHT) {Ability(ABILITY_MIRROR_ARMOR);}
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(player, MOVE_SCREECH); }
TURN { MOVE(player, MOVE_SCREECH); }
TURN { MOVE(player, MOVE_SCREECH); }
TURN { MOVE(opponent, MOVE_LEER); }
} SCENE {
MESSAGE("Corviknigh used Screech!");
MESSAGE("Corviknigh used Screech!");
MESSAGE("Corviknigh used Screech!");
MESSAGE("Foe Wynaut used Leer!");
ABILITY_POPUP(player, ABILITY_MIRROR_ARMOR);
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Wynaut's Defense won't go lower!");
} THEN {
EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE);
EXPECT_EQ(opponent->statStages[STAT_DEF], MIN_STAT_STAGE);
}
}
// This behaviour needs to be verified in the actual games. Currently it's written to follow Showdown's logic.
DOUBLE_BATTLE_TEST("Mirror Armor lowers Speed of the partner Pokemon after Court Change was used by the opponent after it set up Sticky Web")
{
KNOWN_FAILING;
GIVEN {
ASSUME(gBattleMoves[MOVE_STICKY_WEB].effect == EFFECT_STICKY_WEB);
ASSUME(gBattleMoves[MOVE_COURT_CHANGE].effect == EFFECT_COURT_CHANGE);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_CORVIKNIGHT) {Ability(ABILITY_MIRROR_ARMOR); Item(ITEM_IRON_BALL); }
OPPONENT(SPECIES_WYNAUT);
OPPONENT(SPECIES_WYNAUT);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(playerLeft, MOVE_STICKY_WEB); }
TURN { MOVE(opponentLeft, MOVE_COURT_CHANGE); }
TURN { SWITCH(playerRight, 2);}
TURN { }
} SCENE {
MESSAGE("Wobbuffet used Sticky Web!");
MESSAGE("Foe Wynaut used Court Change!");
MESSAGE("Foe Wynaut swapped the battle effects affecting each side!");
MESSAGE("Go! Corviknigh!");
MESSAGE("Corviknigh was caught in a Sticky Web!");
ABILITY_POPUP(playerRight, ABILITY_MIRROR_ARMOR);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
MESSAGE("Wobbuffet's Speed fell!");
}
}

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Oblivious prevents Infatuation") SINGLE_BATTLE_TEST("Oblivious prevents Infatuation")
{ {

View File

@ -0,0 +1,21 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Overcoat blocks powder and spore moves")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_STUN_SPORE].flags & FLAG_POWDER);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_PINECO) { Ability(ABILITY_OVERCOAT); }
} WHEN {
TURN { MOVE(player, MOVE_STUN_SPORE); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_OVERCOAT);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STUN_SPORE, player);
MESSAGE("It doesn't affect Foe Pineco…");
}
}
TO_DO_BATTLE_TEST("Overcoat blocks damage from hail");
TO_DO_BATTLE_TEST("Overcoat blocks damage from sandstorm");
TO_DO_BATTLE_TEST("Overcoat blocks Effect Spore's effect");

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Overgrow boosts Grass-type moves in a pinch", s16 damage) SINGLE_BATTLE_TEST("Overgrow boosts Grass-type moves in a pinch", s16 damage)
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Own Tempo prevents intimidate") SINGLE_BATTLE_TEST("Own Tempo prevents intimidate")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Pastel Veil prevents Poison Sting poison") SINGLE_BATTLE_TEST("Pastel Veil prevents Poison Sting poison")
{ {

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
SINGLE_BATTLE_TEST("Poison Point inflicts poison on contact") SINGLE_BATTLE_TEST("Poison Point inflicts poison on contact")
{ {

View File

@ -0,0 +1,66 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_EMBER].power != 0);
ASSUME(gBattleMoves[MOVE_EMBER].type == TYPE_FIRE);
}
SINGLE_BATTLE_TEST("Primordial Sea blocks damaging Fire-type moves")
{
GIVEN {
PLAYER(SPECIES_KYOGRE) {Item(ITEM_BLUE_ORB);}
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_EMBER); }
TURN { MOVE(opponent, MOVE_EMBER); }
} SCENE {
MESSAGE("Foe Wobbuffet used Ember!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent);
MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!");
NOT HP_BAR(player);
MESSAGE("Foe Wobbuffet used Ember!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent);
MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!");
NOT HP_BAR(player);
} THEN {
EXPECT_EQ(player->hp, player->maxHP);
}
}
DOUBLE_BATTLE_TEST("Primordial Sea blocks damaging Fire-type moves and prints the message only once with moves hitting multiple targets")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_ERUPTION].power != 0);
ASSUME(gBattleMoves[MOVE_ERUPTION].type == TYPE_FIRE);
ASSUME(gBattleMoves[MOVE_ERUPTION].target == MOVE_TARGET_BOTH);
PLAYER(SPECIES_KYOGRE) {Item(ITEM_BLUE_ORB); {Speed(5);}}
PLAYER(SPECIES_WOBBUFFET) {Speed(5);}
OPPONENT(SPECIES_WOBBUFFET) {Speed(10);}
OPPONENT(SPECIES_WOBBUFFET) {Speed(8);}
} WHEN {
TURN { MOVE(opponentLeft, MOVE_ERUPTION); }
} SCENE {
MESSAGE("Foe Wobbuffet used Eruption!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_ERUPTION, opponentLeft);
MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!");
NOT MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!");
} THEN {
EXPECT_EQ(playerLeft->hp, playerLeft->maxHP);
EXPECT_EQ(playerRight->hp, playerRight->maxHP);
}
}
SINGLE_BATTLE_TEST("Primordial Sea does not block a move if pokemon is asleep and uses a Fire-type move") // Sleep/confusion/paralysis all happen before the check for primal weather
{
GIVEN {
PLAYER(SPECIES_KYOGRE) {Item(ITEM_BLUE_ORB);}
OPPONENT(SPECIES_WOBBUFFET) {Status1(STATUS1_SLEEP);}
} WHEN {
TURN { MOVE(opponent, MOVE_EMBER); }
} SCENE {
NOT MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!");
MESSAGE("Foe Wobbuffet is fast asleep.");
}
}

View File

@ -1,5 +1,5 @@
#include "global.h" #include "global.h"
#include "test_battle.h" #include "test/battle.h"
ASSUMPTIONS ASSUMPTIONS
{ {

Some files were not shown because too many files have changed in this diff Show More