mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-12-26 03:34:15 +01:00
Merge branch 'RHH/master' into RHH/pr/master/opponentName
This commit is contained in:
commit
be152fbee8
102
.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml
vendored
102
.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml
vendored
@ -1,50 +1,52 @@
|
||||
name: ⚔️ Battle Engine mechanical bugs 🐛
|
||||
description: File a bug report related to battle mechanic, be it moves, abilities and/or items.
|
||||
labels: ["bug", "status: unconfirmed", "category: battle-mechanic"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please fill in all required fields with as many details as possible.
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: |
|
||||
Describe the issue you are experiencing.
|
||||
Attach images/videos if possible.
|
||||
placeholder: |
|
||||
Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of pokeemerald-expansion are you using as a base?
|
||||
options:
|
||||
- 1.5.1 (Default)
|
||||
- upcoming (Edge)
|
||||
- 1.5.0
|
||||
- 1.4.3
|
||||
- 1.4.2
|
||||
- 1.4.1
|
||||
- 1.4.0
|
||||
- pre-1.4.0
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: upcomingversion
|
||||
attributes:
|
||||
label: Upcoming Version
|
||||
description: If you're using the upcoming branch, please specify what was the commit hash you pulled from.
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
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)).
|
||||
placeholder: ex. Lunos#4026
|
||||
validations:
|
||||
required: false
|
||||
name: ⚔️ Battle Engine mechanical bugs 🐛
|
||||
description: File a bug report related to battle mechanic, be it moves, abilities and/or items.
|
||||
labels: ["bug", "status: unconfirmed", "category: battle-mechanic"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please fill in all required fields with as many details as possible.
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: |
|
||||
Describe the issue you are experiencing.
|
||||
Attach images/videos if possible.
|
||||
placeholder: |
|
||||
Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of pokeemerald-expansion are you using as a base?
|
||||
options:
|
||||
- 1.5.3 (Default)
|
||||
- upcoming (Edge)
|
||||
- 1.5.2
|
||||
- 1.5.1
|
||||
- 1.5.0
|
||||
- 1.4.3
|
||||
- 1.4.2
|
||||
- 1.4.1
|
||||
- 1.4.0
|
||||
- pre-1.4.0
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: upcomingversion
|
||||
attributes:
|
||||
label: Upcoming Version
|
||||
description: If you're using the upcoming branch, please specify what was the commit hash you pulled from.
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
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)).
|
||||
placeholder: ex. Lunos#4026
|
||||
validations:
|
||||
required: false
|
||||
|
102
.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml
vendored
102
.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml
vendored
@ -1,50 +1,52 @@
|
||||
name: 🧠 Battle AI bugs 🐛
|
||||
description: File a bug report related to battle AI.
|
||||
labels: ["bug", "status: unconfirmed", "category: battle-ai"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please fill in all required fields with as many details as possible.
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: |
|
||||
Describe the issue you are experiencing.
|
||||
Attach images/videos if possible.
|
||||
placeholder: |
|
||||
Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of pokeemerald-expansion are you using as a base?
|
||||
options:
|
||||
- 1.5.1 (Default)
|
||||
- upcoming (Edge)
|
||||
- 1.5.0
|
||||
- 1.4.3
|
||||
- 1.4.2
|
||||
- 1.4.1
|
||||
- 1.4.0
|
||||
- pre-1.4.0
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: upcomingversion
|
||||
attributes:
|
||||
label: Upcoming Version
|
||||
description: If you're using the upcoming branch, please specify what was the commit hash you pulled from.
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
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)).
|
||||
placeholder: ex. Lunos#4026
|
||||
validations:
|
||||
required: false
|
||||
name: 🧠 Battle AI bugs 🐛
|
||||
description: File a bug report related to battle AI.
|
||||
labels: ["bug", "status: unconfirmed", "category: battle-ai"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please fill in all required fields with as many details as possible.
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: |
|
||||
Describe the issue you are experiencing.
|
||||
Attach images/videos if possible.
|
||||
placeholder: |
|
||||
Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of pokeemerald-expansion are you using as a base?
|
||||
options:
|
||||
- 1.5.3 (Default)
|
||||
- upcoming (Edge)
|
||||
- 1.5.2
|
||||
- 1.5.1
|
||||
- 1.5.0
|
||||
- 1.4.3
|
||||
- 1.4.2
|
||||
- 1.4.1
|
||||
- 1.4.0
|
||||
- pre-1.4.0
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: upcomingversion
|
||||
attributes:
|
||||
label: Upcoming Version
|
||||
description: If you're using the upcoming branch, please specify what was the commit hash you pulled from.
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
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)).
|
||||
placeholder: ex. Lunos#4026
|
||||
validations:
|
||||
required: false
|
||||
|
54
.github/ISSUE_TEMPLATE/03_feature_requests.yaml
vendored
54
.github/ISSUE_TEMPLATE/03_feature_requests.yaml
vendored
@ -1,27 +1,27 @@
|
||||
name: 🙏 Feature Request 🙏
|
||||
description: Do you want a feature to be added to the Expansion? Let us know!
|
||||
labels: ["feature-request"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please fill in all required fields with as many details as possible.
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: |
|
||||
Describe the issue you are experiencing.
|
||||
Attach images/videos if possible.
|
||||
placeholder: |
|
||||
Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
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)).
|
||||
placeholder: ex. Lunos#4026
|
||||
validations:
|
||||
required: false
|
||||
name: 🙏 Feature Request 🙏
|
||||
description: Do you want a feature to be added to the Expansion? Let us know!
|
||||
labels: ["feature-request"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please fill in all required fields with as many details as possible.
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: |
|
||||
Describe the issue you are experiencing.
|
||||
Attach images/videos if possible.
|
||||
placeholder: |
|
||||
Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
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)).
|
||||
placeholder: ex. Lunos#4026
|
||||
validations:
|
||||
required: false
|
||||
|
102
.github/ISSUE_TEMPLATE/04_other_errors.yaml
vendored
102
.github/ISSUE_TEMPLATE/04_other_errors.yaml
vendored
@ -1,50 +1,52 @@
|
||||
name: 💾 Other errors 🖥️
|
||||
description: Everything else that doesn't fit in the above categories.
|
||||
labels: ["bug", "status: unconfirmed"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please fill in all required fields with as many details as possible.
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: |
|
||||
Describe the issue you are experiencing.
|
||||
Attach images/videos if possible.
|
||||
placeholder: |
|
||||
Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of pokeemerald-expansion are you using as a base?
|
||||
options:
|
||||
- 1.5.1 (Default)
|
||||
- upcoming (Edge)
|
||||
- 1.5.0
|
||||
- 1.4.3
|
||||
- 1.4.2
|
||||
- 1.4.1
|
||||
- 1.4.0
|
||||
- pre-1.4.0
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: upcomingversion
|
||||
attributes:
|
||||
label: Upcoming Version
|
||||
description: If you're using the upcoming branch, please specify what was the commit hash you pulled from.
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
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)).
|
||||
placeholder: ex. Lunos#4026
|
||||
validations:
|
||||
required: false
|
||||
name: 💾 Other errors 🖥️
|
||||
description: Everything else that doesn't fit in the above categories.
|
||||
labels: ["bug", "status: unconfirmed"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please fill in all required fields with as many details as possible.
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: |
|
||||
Describe the issue you are experiencing.
|
||||
Attach images/videos if possible.
|
||||
placeholder: |
|
||||
Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of pokeemerald-expansion are you using as a base?
|
||||
options:
|
||||
- 1.5.3 (Default)
|
||||
- upcoming (Edge)
|
||||
- 1.5.2
|
||||
- 1.5.1
|
||||
- 1.5.0
|
||||
- 1.4.3
|
||||
- 1.4.2
|
||||
- 1.4.1
|
||||
- 1.4.0
|
||||
- pre-1.4.0
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: upcomingversion
|
||||
attributes:
|
||||
label: Upcoming Version
|
||||
description: If you're using the upcoming branch, please specify what was the commit hash you pulled from.
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
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)).
|
||||
placeholder: ex. Lunos#4026
|
||||
validations:
|
||||
required: false
|
||||
|
42
INSTALL.md
42
INSTALL.md
@ -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.
|
||||
|
||||
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
|
||||
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>
|
||||
<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>
|
||||
|
||||
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\\⁠_\<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 isn’t 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)
|
||||
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.
|
||||
|
||||
|
2
Makefile
2
Makefile
@ -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.
|
||||
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 $$@ $$<"
|
||||
@$$(CPP) $$(CPPFLAGS) $$< | $$(PREPROC) $$< charmap.txt -i | $$(CC1) $$(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $$(AS) $$(ASFLAGS) -o $$@ -
|
||||
endef
|
||||
|
@ -1053,8 +1053,9 @@
|
||||
.byte 0xca
|
||||
.endm
|
||||
|
||||
.macro setcharge
|
||||
.macro setcharge battler:req
|
||||
.byte 0xcb
|
||||
.byte \battler
|
||||
.endm
|
||||
|
||||
.macro callterrainattack
|
||||
@ -1317,7 +1318,7 @@
|
||||
.2byte \holdEffect
|
||||
.4byte \jumpInstr
|
||||
.endm
|
||||
|
||||
|
||||
.macro dostockpilestatchangeswearoff, battler:req, statChangeInstr:req
|
||||
callnative BS_DoStockpileStatChangesWearOff
|
||||
.byte \battler
|
||||
@ -1353,7 +1354,7 @@
|
||||
.macro setsnow
|
||||
callnative BS_SetSnow
|
||||
.endm
|
||||
|
||||
|
||||
.macro setzeffect
|
||||
callnative BS_SetZEffect
|
||||
.endm
|
||||
@ -1363,12 +1364,6 @@
|
||||
callnative BS_TrySymbiosis
|
||||
.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]
|
||||
.macro getbattlerside battler:req
|
||||
callnative BS_GetBattlerSide
|
||||
@ -2076,7 +2071,7 @@
|
||||
.macro swapsidestatuses
|
||||
various BS_ATTACKER, VARIOUS_SWAP_SIDE_STATUSES
|
||||
.endm
|
||||
|
||||
|
||||
.macro swapstats stat:req
|
||||
various BS_ATTACKER, VARIOUS_SWAP_STATS
|
||||
.byte \stat
|
||||
@ -2177,6 +2172,11 @@
|
||||
jumpifbyte CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_NO_EFFECT, \jumpInstr
|
||||
.endm
|
||||
|
||||
.macro jumpifside battler:req, side:req, equalJumpInstr:req
|
||||
getbattlerside \battler
|
||||
jumpifbyte CMP_EQUAL, gBattleCommunication, \side, \equalJumpInstr
|
||||
.endm
|
||||
|
||||
.macro jumpifbattletype flags:req, jumpInstr:req
|
||||
jumpifword CMP_COMMON_BITS, gBattleTypeFlags, \flags, \jumpInstr
|
||||
.endm
|
||||
|
@ -3079,12 +3079,9 @@ BattleScript_TryTailwindAbilitiesLoop_WindRider:
|
||||
|
||||
BattleScript_TryTailwindAbilitiesLoop_WindPower:
|
||||
call BattleScript_AbilityPopUp
|
||||
copybyte sSAVED_BATTLER, gBattlerAttacker
|
||||
copybyte gBattlerAttacker, gBattlerTarget
|
||||
setcharge
|
||||
setcharge BS_TARGET
|
||||
printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
copybyte gBattlerAttacker, sSAVED_BATTLER
|
||||
goto BattleScript_TryTailwindAbilitiesLoop_Increment
|
||||
|
||||
BattleScript_EffectMircleEye:
|
||||
@ -4104,6 +4101,8 @@ BattleScript_MoveMissedDoDamage::
|
||||
.if B_CRASH_IF_TARGET_IMMUNE < GEN_4
|
||||
jumpifhalfword CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_DOESNT_AFFECT_FOE, BattleScript_MoveEnd
|
||||
.endif
|
||||
moveendcase MOVEEND_PROTECT_LIKE_EFFECT @ Spiky Shield's damage happens before recoil.
|
||||
jumpifhasnohp BS_ATTACKER, BattleScript_MoveEnd
|
||||
printstring STRINGID_PKMNCRASHED
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
damagecalc
|
||||
@ -5129,7 +5128,7 @@ BattleScript_EffectBatonPass::
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectRapidSpin::
|
||||
.if B_SPEED_BUFFING_RAPID_SPIN == GEN_8
|
||||
.if B_SPEED_BUFFING_RAPID_SPIN >= GEN_8
|
||||
attackcanceler
|
||||
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
|
||||
attackstring
|
||||
@ -5404,15 +5403,14 @@ BattleScript_EffectHurricane:
|
||||
BattleScript_EffectTeleport:
|
||||
attackcanceler
|
||||
attackstring
|
||||
ppreduce
|
||||
.if B_TELEPORT_BEHAVIOR >= GEN_7
|
||||
canteleport BS_ATTACKER
|
||||
jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_EffectTeleportNew
|
||||
goto BattleScript_ButItFailed
|
||||
jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_EffectBatonPass
|
||||
jumpifside BS_ATTACKER, B_SIDE_PLAYER, BattleScript_EffectBatonPass
|
||||
.else
|
||||
jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_ButItFailed
|
||||
.endif
|
||||
BattleScript_EffectTeleportTryToRunAway:
|
||||
ppreduce
|
||||
getifcantrunfrombattle BS_ATTACKER
|
||||
jumpifbyte CMP_EQUAL, gBattleCommunication, BATTLE_RUN_FORBIDDEN, BattleScript_ButItFailed
|
||||
jumpifbyte CMP_EQUAL, gBattleCommunication, BATTLE_RUN_FAILURE, BattleScript_PrintAbilityMadeIneffective
|
||||
@ -5423,29 +5421,6 @@ BattleScript_EffectTeleportTryToRunAway:
|
||||
setoutcomeonteleport BS_ATTACKER
|
||||
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::
|
||||
attackcanceler
|
||||
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
|
||||
@ -5872,7 +5847,7 @@ BattleScript_EffectCharge::
|
||||
attackcanceler
|
||||
attackstring
|
||||
ppreduce
|
||||
setcharge
|
||||
setcharge BS_ATTACKER
|
||||
attackanimation
|
||||
waitanimation
|
||||
.if B_CHARGE_SPDEF_RAISE >= GEN_5
|
||||
@ -6937,27 +6912,6 @@ BattleScript_TailwindEnds::
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
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::
|
||||
printstring STRINGID_TRICKROOMENDS
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
@ -7419,11 +7373,8 @@ BattleScript_AngerShellRet:
|
||||
return
|
||||
|
||||
BattleScript_WindPowerActivates::
|
||||
.if B_CHECK_IF_CHARGED_UP == TRUE
|
||||
jumpifstatus3 BS_ATTACKER, STATUS3_CHARGED_UP, BattleScript_WindPowerActivates_Ret
|
||||
.endif
|
||||
call BattleScript_AbilityPopUp
|
||||
setcharge
|
||||
setcharge BS_TARGET
|
||||
printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_WindPowerActivates_Ret:
|
||||
@ -7924,7 +7875,7 @@ BattleScript_WishMegaEvolution::
|
||||
BattleScript_PrimalReversion::
|
||||
call BattleScript_PrimalReversionRet
|
||||
end2
|
||||
|
||||
|
||||
BattleScript_PrimalReversionRestoreAttacker::
|
||||
call BattleScript_PrimalReversionRet
|
||||
copybyte gBattlerAttacker, sSAVED_BATTLER
|
||||
@ -8782,15 +8733,14 @@ BattleScript_DesolateLandActivates::
|
||||
call BattleScript_ActivateWeatherAbilities
|
||||
end3
|
||||
|
||||
BattleScript_DesolateLandEvaporatesWaterTypeMoves::
|
||||
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
|
||||
BattleScript_PrimalWeatherBlocksMove::
|
||||
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
|
||||
pause B_WAIT_TIME_SHORT
|
||||
ppreduce
|
||||
jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_STRING_PRINTED, BattleScript_MoveEnd
|
||||
printstring STRINGID_MOVEEVAPORATEDINTHEHARSHSUNLIGHT
|
||||
printfromtable gPrimalWeatherBlocksStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
orword gHitMarker, HITMARKER_STRING_PRINTED
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_PrimordialSeaActivates::
|
||||
@ -8802,17 +8752,6 @@ BattleScript_PrimordialSeaActivates::
|
||||
call BattleScript_ActivateWeatherAbilities
|
||||
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::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
call BattleScript_AbilityPopUp
|
||||
@ -8983,7 +8922,7 @@ BattleScript_BadDreams_ShowPopUp:
|
||||
goto BattleScript_BadDreams_DmgAfterPopUp
|
||||
BattleScript_BadDreams_HidePopUp:
|
||||
destroyabilitypopup
|
||||
tryfaintmon BS_TARGET
|
||||
tryfaintmon BS_TARGET
|
||||
goto BattleScript_BadDreamsIncrement
|
||||
|
||||
BattleScript_TookAttack::
|
||||
@ -10461,6 +10400,7 @@ BattleScript_SymbiosisActivates::
|
||||
return
|
||||
|
||||
BattleScript_TargetAbilityStatRaiseRet::
|
||||
copybyte sSAVED_BATTLER, gBattlerAttacker
|
||||
copybyte gBattlerAbility, gEffectBattler
|
||||
copybyte gBattlerAttacker, gBattlerTarget
|
||||
call BattleScript_AbilityPopUp
|
||||
@ -10468,6 +10408,7 @@ BattleScript_TargetAbilityStatRaiseRet::
|
||||
setgraphicalstatchangevalues
|
||||
call BattleScript_StatUp
|
||||
BattleScript_TargetAbilityStatRaiseRet_End:
|
||||
copybyte gBattlerAttacker, sSAVED_BATTLER
|
||||
return
|
||||
|
||||
BattleScript_PokemonCantUseTheMove::
|
||||
|
@ -212,6 +212,7 @@ struct SideTimer
|
||||
u8 toxicSpikesAmount;
|
||||
u8 stealthRockAmount;
|
||||
u8 stickyWebAmount;
|
||||
u8 stickyWebBattlerId;
|
||||
u8 stickyWebBattlerSide; // Used for Court Change
|
||||
u8 auroraVeilTimer;
|
||||
u8 auroraVeilBattlerId;
|
||||
@ -644,7 +645,6 @@ struct BattleStruct
|
||||
u8 forcedSwitch:4; // For each battler
|
||||
u8 switchInAbilityPostponed:4; // To not activate against an empty field, each bit for battler
|
||||
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 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.
|
||||
|
@ -409,9 +409,8 @@ extern const u8 BattleScript_GulpMissileGorging[];
|
||||
extern const u8 BattleScript_GulpMissileGulping[];
|
||||
extern const u8 BattleScript_BattleBondActivatesOnMoveEndAttacker[];
|
||||
extern const u8 BattleScript_DesolateLandActivates[];
|
||||
extern const u8 BattleScript_DesolateLandEvaporatesWaterTypeMoves[];
|
||||
extern const u8 BattleScript_PrimordialSeaActivates[];
|
||||
extern const u8 BattleScript_PrimordialSeaFizzlesOutFireTypeMoves[];
|
||||
extern const u8 BattleScript_PrimalWeatherBlocksMove[];
|
||||
extern const u8 BattleScript_DeltaStreamActivates[];
|
||||
extern const u8 BattleScript_MysteriousAirCurrentBlowsOn[];
|
||||
extern const u8 BattleScript_AttackWeakenedByStrongWinds[];
|
||||
|
@ -136,8 +136,8 @@ u8 DoBattlerEndTurnEffects(void);
|
||||
bool8 HandleWishPerishSongOnTurnEnd(void);
|
||||
bool8 HandleFaintedMonActions(void);
|
||||
void TryClearRageAndFuryCutter(void);
|
||||
u8 AtkCanceller_UnableToUseMove(u32 moveType);
|
||||
void SetAtkCancellerForCalledMove(void);
|
||||
u8 AtkCanceller_UnableToUseMove(void);
|
||||
u8 AtkCanceller_UnableToUseMove2(void);
|
||||
bool8 HasNoMonsToSwitch(u8 battlerId, u8 r1, u8 r2);
|
||||
bool32 TryChangeBattleWeather(u8 battler, u32 weatherEnumId, bool32 viaAbility);
|
||||
|
@ -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_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_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_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.
|
||||
|
@ -827,6 +827,10 @@
|
||||
#define B_MSG_SOMEONES_BOX_FULL 2
|
||||
#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
|
||||
#define B_MSG_LOAFING 0
|
||||
#define B_MSG_WONT_OBEY 1
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "sprite.h"
|
||||
|
||||
extern u8 gDecompressionBuffer[0x4000];
|
||||
extern u8 ALIGNED(4) gDecompressionBuffer[0x4000];
|
||||
|
||||
void LZDecompressWram(const u32 *src, void *dest);
|
||||
void LZDecompressVram(const u32 *src, void *dest);
|
||||
|
@ -213,7 +213,7 @@ struct SoundInfo
|
||||
ExtVolPitFunc ExtVolPit;
|
||||
u8 gap2[16];
|
||||
struct SoundChannel chans[MAX_DIRECTSOUND_CHANNELS];
|
||||
s8 pcmBuffer[PCM_DMA_BUF_SIZE * 2];
|
||||
s8 ALIGNED(4) pcmBuffer[PCM_DMA_BUF_SIZE * 2];
|
||||
};
|
||||
|
||||
struct SongHeader
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef 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); \
|
||||
CpuSet((void *)&tmp, \
|
||||
@ -9,10 +9,33 @@
|
||||
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 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 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 DmaSet(dmaNum, src, dest, control) \
|
||||
#define DmaSetUnchecked(dmaNum, src, dest, control) \
|
||||
{ \
|
||||
vu32 *dmaRegs = (vu32 *)REG_ADDR_DMA##dmaNum; \
|
||||
dmaRegs[0] = (vu32)(src); \
|
||||
@ -40,7 +63,21 @@
|
||||
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); \
|
||||
DmaSet(dmaNum, \
|
||||
@ -50,6 +87,17 @@
|
||||
| ((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 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
|
||||
// bitwise OR operation.
|
||||
|
||||
#define DMA_CLEAR(dmaNum, dest, size, bit) \
|
||||
#define DMA_CLEAR_UNCHECKED(dmaNum, dest, size, bit) \
|
||||
{ \
|
||||
vu##bit *_dest = (vu##bit *)(dest); \
|
||||
u32 _size = 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 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, \
|
||||
src, \
|
||||
dest, \
|
||||
(DMA_ENABLE | DMA_START_NOW | DMA_##bit##BIT | DMA_SRC_INC | DMA_DEST_INC) << 16 \
|
||||
| ((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 DmaCopy32(dmaNum, src, dest, size) DMA_COPY(dmaNum, src, dest, size, 32)
|
||||
|
||||
|
@ -27,10 +27,32 @@ u16 ArcTan2(s16 x, s16 y);
|
||||
|
||||
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
|
||||
|
||||
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 ObjAffineSet(struct ObjAffineSrcData *src, void *dest, s32 count, s32 offset);
|
||||
|
@ -20,7 +20,6 @@
|
||||
#define BLOCK_CROSS_JUMP asm("");
|
||||
|
||||
// to help in decompiling
|
||||
#define asm_comment(x) asm volatile("@ -- " x " -- ")
|
||||
#define asm_unified(x) asm(".syntax unified\n" x "\n.syntax divided")
|
||||
#define NAKED __attribute__((naked))
|
||||
|
||||
@ -141,6 +140,8 @@
|
||||
|
||||
// Calls m0/m1/.../m8 depending on how many arguments are passed.
|
||||
#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_(_, a, b, c, d, e, f, g, h, N, ...) N
|
||||
|
||||
@ -856,7 +857,7 @@ struct WaldaPhrase
|
||||
struct TrainerNameRecord
|
||||
{
|
||||
u32 trainerId;
|
||||
u8 trainerName[PLAYER_NAME_LENGTH + 1];
|
||||
u8 ALIGNED(2) trainerName[PLAYER_NAME_LENGTH + 1];
|
||||
};
|
||||
|
||||
struct TrainerHillSave
|
||||
|
@ -8923,7 +8923,7 @@ extern const u32 gIntroGroudon_Gfx[];
|
||||
extern const u32 gIntroGroudon_Tilemap[];
|
||||
extern const u32 gIntroLegendBg_Gfx[];
|
||||
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_Tilemap[];
|
||||
extern const u32 gIntroKyogreBg_Tilemap[];
|
||||
@ -10432,8 +10432,8 @@ extern const u32 gPokenavOptions_Gfx[];
|
||||
extern const u16 gPokenavOptions_Pal[];
|
||||
|
||||
// Battle Factory Screen
|
||||
extern const u8 gFrontierFactorySelectMenu_Gfx[];
|
||||
extern const u8 gFrontierFactorySelectMenu_Tilemap[];
|
||||
extern const u16 gFrontierFactorySelectMenu_Gfx[];
|
||||
extern const u16 gFrontierFactorySelectMenu_Tilemap[];
|
||||
extern const u16 gFrontierFactorySelectMenu_Pal[];
|
||||
|
||||
// Object event pals
|
||||
|
@ -78,7 +78,7 @@ struct BagMenu
|
||||
u8 numShownItems[POCKETS_COUNT];
|
||||
s16 graphicsLoadState;
|
||||
u8 unused2[14];
|
||||
u8 pocketNameBuffer[32][32];
|
||||
u8 ALIGNED(4) pocketNameBuffer[32][32];
|
||||
u8 unused3[4];
|
||||
};
|
||||
|
||||
|
@ -329,7 +329,7 @@ struct RfuIntrStruct
|
||||
{
|
||||
union RfuPacket rxPacketAlloc;
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -238,7 +238,7 @@ struct BlockRequest
|
||||
};
|
||||
|
||||
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 u16 gLinkType;
|
||||
extern u32 gLinkStatus;
|
||||
|
@ -18,7 +18,7 @@ struct MonMarkingsMenu
|
||||
struct Sprite *textSprite;
|
||||
const u8 *frameTiles;
|
||||
const u16 *framePalette;
|
||||
u8 windowSpriteTiles[0x1000];
|
||||
u8 ALIGNED(2) windowSpriteTiles[0x1000];
|
||||
u8 unused[0x80];
|
||||
u8 tileLoadState;
|
||||
};
|
||||
|
@ -54,9 +54,9 @@ struct PaletteFadeControl
|
||||
|
||||
extern struct PaletteFadeControl gPaletteFade;
|
||||
extern u32 gPlttBufferTransferPending;
|
||||
extern u8 gPaletteDecompressionBuffer[];
|
||||
extern u16 gPlttBufferUnfaded[PLTT_BUFFER_SIZE];
|
||||
extern u16 gPlttBufferFaded[PLTT_BUFFER_SIZE];
|
||||
extern u8 ALIGNED(4) gPaletteDecompressionBuffer[];
|
||||
extern u16 ALIGNED(4) gPlttBufferUnfaded[PLTT_BUFFER_SIZE];
|
||||
extern u16 ALIGNED(4) gPlttBufferFaded[PLTT_BUFFER_SIZE];
|
||||
|
||||
void LoadCompressedPalette(const u32 *src, u16 offset, u16 size);
|
||||
void LoadPalette(const void *src, u16 offset, u16 size);
|
||||
|
@ -49,7 +49,7 @@ extern const struct SpriteTemplate gBallSpriteTemplates[];
|
||||
#define POKEBALL_OPPONENT_SENDOUT 0xFE
|
||||
|
||||
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);
|
||||
void StartHealthboxSlideIn(u8 battler);
|
||||
void DoHitAnimHealthboxEffect(u8 battler);
|
||||
|
@ -462,12 +462,17 @@ void SetMultiuseSpriteTemplateToPokemon(u16 speciesTag, u8 battlerPosition);
|
||||
void SetMultiuseSpriteTemplateToTrainerBack(u16 trainerSpriteId, u8 battlerPosition);
|
||||
void SetMultiuseSpriteTemplateToTrainerFront(u16 trainerPicId, u8 battlerPosition);
|
||||
|
||||
// These are full type signatures for GetMonData() and GetBoxMonData(),
|
||||
// but they are not used since some code erroneously omits the third arg.
|
||||
// u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data);
|
||||
// u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data);
|
||||
u32 GetMonData();
|
||||
u32 GetBoxMonData();
|
||||
/* GameFreak called Get(Box)MonData with either 2 or 3 arguments, for
|
||||
* type safety we have a Get(Box)MonData macro which dispatches to
|
||||
* either Get(Box)MonData2 or Get(Box)MonData3 based on the number of
|
||||
* arguments. The two functions are aliases of each other, but they
|
||||
* differ for matching purposes in the caller's codegen. */
|
||||
#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 SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg);
|
||||
|
@ -37,7 +37,7 @@ struct ScanlineEffect
|
||||
|
||||
extern struct ScanlineEffect gScanlineEffect;
|
||||
|
||||
extern u16 gScanlineEffectRegBuffers[2][0x3C0];
|
||||
extern u16 ALIGNED(4) gScanlineEffectRegBuffers[2][0x3C0];
|
||||
|
||||
void ScanlineEffect_Stop(void);
|
||||
void ScanlineEffect_Clear(void);
|
||||
|
@ -447,13 +447,13 @@
|
||||
#ifndef GUARD_TEST_BATTLE_H
|
||||
#define GUARD_TEST_BATTLE_H
|
||||
|
||||
#include "global.h"
|
||||
#include "battle.h"
|
||||
#include "battle_anim.h"
|
||||
#include "data.h"
|
||||
#include "item.h"
|
||||
#include "random.h"
|
||||
#include "recorded_battle.h"
|
||||
#include "test.h"
|
||||
#include "util.h"
|
||||
#include "constants/abilities.h"
|
||||
#include "constants/battle_anim.h"
|
||||
@ -462,6 +462,7 @@
|
||||
#include "constants/items.h"
|
||||
#include "constants/moves.h"
|
||||
#include "constants/species.h"
|
||||
#include "test/test.h"
|
||||
|
||||
// NOTE: If the stack is too small the test runner will probably crash
|
||||
// or loop.
|
@ -2080,6 +2080,8 @@ gCryTable::
|
||||
@ Calyrex
|
||||
cry Cry_CalyrexIceRider
|
||||
cry Cry_CalyrexShadowRider
|
||||
@ Basculegion
|
||||
cry Cry_Basculegion
|
||||
.else
|
||||
@ Cramorant
|
||||
cry Cry_Unown
|
||||
@ -2118,6 +2120,8 @@ gCryTable::
|
||||
@ Calyrex
|
||||
cry Cry_Unown
|
||||
cry Cry_Unown
|
||||
@ Basculegion
|
||||
cry Cry_Unown
|
||||
.endif
|
||||
|
||||
.align 2
|
||||
@ -4163,6 +4167,8 @@ gCryTable_Reverse::
|
||||
@ Calyrex
|
||||
cry_reverse Cry_CalyrexIceRider
|
||||
cry_reverse Cry_CalyrexShadowRider
|
||||
@ Basculegion
|
||||
cry_reverse Cry_Basculegion
|
||||
.else
|
||||
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
|
||||
.endif
|
||||
|
@ -152,7 +152,7 @@ static void InitSinglePlayerBtlControllers(void)
|
||||
|
||||
gBattlerPartyIndexes[0] = 0;
|
||||
gBattlerPartyIndexes[1] = 0;
|
||||
if (BATTLE_TWO_VS_ONE_OPPONENT)
|
||||
if (BATTLE_TWO_VS_ONE_OPPONENT || WILD_DOUBLE_BATTLE)
|
||||
{
|
||||
gBattlerPartyIndexes[2] = 3;
|
||||
gBattlerPartyIndexes[3] = 1;
|
||||
|
@ -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 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_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 struct SpriteSheet sSelect_SpriteSheets[] =
|
||||
|
@ -1409,11 +1409,10 @@ bool32 IsMegaTriggerSpriteActive(void)
|
||||
|
||||
void HideMegaTriggerSprite(void)
|
||||
{
|
||||
if (gBattleStruct->mega.triggerSpriteId != 0xFF)
|
||||
{
|
||||
ChangeMegaTriggerSprite(gBattleStruct->mega.triggerSpriteId, 0);
|
||||
gSprites[gBattleStruct->mega.triggerSpriteId].tHide = TRUE;
|
||||
}
|
||||
if (gBattleStruct->mega.triggerSpriteId >= MAX_SPRITES)
|
||||
return;
|
||||
ChangeMegaTriggerSprite(gBattleStruct->mega.triggerSpriteId, 0);
|
||||
gSprites[gBattleStruct->mega.triggerSpriteId].tHide = TRUE;
|
||||
}
|
||||
|
||||
void HideTriggerSprites(void)
|
||||
|
@ -1964,7 +1964,6 @@ u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer
|
||||
u8 fixedIV;
|
||||
s32 i, j;
|
||||
u8 monsCount;
|
||||
s32 ball = -1;
|
||||
if (battleTypeFlags & BATTLE_TYPE_TRAINER && !(battleTypeFlags & (BATTLE_TYPE_FRONTIER
|
||||
| BATTLE_TYPE_EREADER_TRAINER
|
||||
| BATTLE_TYPE_TRAINER_HILL)))
|
||||
@ -1986,6 +1985,7 @@ u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer
|
||||
|
||||
for (i = 0; i < monsCount; i++)
|
||||
{
|
||||
s32 ball = -1;
|
||||
u32 personalityHash = GeneratePartyHash(trainer, i);
|
||||
if (trainer->doubleBattle == TRUE)
|
||||
personalityValue = 0x80;
|
||||
@ -3170,7 +3170,10 @@ static void BattleStartClearSetData(void)
|
||||
|
||||
gBattleStruct->mega.triggerSpriteId = 0xFF;
|
||||
|
||||
gBattleStruct->stickyWebUser = 0xFF;
|
||||
for (i = 0; i < ARRAY_COUNT(gSideTimers); i++)
|
||||
{
|
||||
gSideTimers[i].stickyWebBattlerId = 0xFF;
|
||||
}
|
||||
gBattleStruct->appearedInBattle = 0;
|
||||
gBattleStruct->beatUpSlot = 0;
|
||||
|
||||
@ -3276,8 +3279,12 @@ void SwitchInClearSetData(void)
|
||||
gBattleStruct->lastMoveFailed &= ~(gBitTable[gActiveBattler]);
|
||||
gBattleStruct->palaceFlags &= ~(gBitTable[gActiveBattler]);
|
||||
|
||||
if (gActiveBattler == gBattleStruct->stickyWebUser)
|
||||
gBattleStruct->stickyWebUser = 0xFF; // Switched into sticky web user slot so reset it
|
||||
for (i = 0; i < ARRAY_COUNT(gSideTimers); i++)
|
||||
{
|
||||
// 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++)
|
||||
{
|
||||
@ -3390,8 +3397,12 @@ void FaintClearSetData(void)
|
||||
|
||||
gBattleStruct->palaceFlags &= ~(gBitTable[gActiveBattler]);
|
||||
|
||||
if (gActiveBattler == gBattleStruct->stickyWebUser)
|
||||
gBattleStruct->stickyWebUser = 0xFF; // User of sticky web fainted, so reset the stored battler ID
|
||||
for (i = 0; i < ARRAY_COUNT(gSideTimers); i++)
|
||||
{
|
||||
// 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++)
|
||||
{
|
||||
@ -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 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;
|
||||
|
@ -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_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_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_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_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_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_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_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_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}!");
|
||||
@ -1851,6 +1851,12 @@ const u16 gWeatherStartsStringIds[] =
|
||||
[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[] =
|
||||
{
|
||||
[B_MSG_LOAFING] = STRINGID_PKMNLOAFING,
|
||||
@ -2693,7 +2699,7 @@ void BufferStringBattle(u16 stringID)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY)
|
||||
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;
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL)
|
||||
stringPtr = sText_WildPkmnAppearedPause;
|
||||
|
@ -1503,25 +1503,8 @@ static void Cmd_attackcanceler(void)
|
||||
|
||||
s32 i, moveType;
|
||||
u16 attackerAbility = GetBattlerAbility(gBattlerAttacker);
|
||||
|
||||
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)
|
||||
{
|
||||
gCurrentActionFuncId = B_ACTION_FINISHED;
|
||||
@ -1537,9 +1520,27 @@ static void Cmd_attackcanceler(void)
|
||||
if (TryAegiFormChange())
|
||||
return;
|
||||
#endif
|
||||
if (AtkCanceller_UnableToUseMove())
|
||||
if (AtkCanceller_UnableToUseMove(moveType))
|
||||
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
|
||||
&& GetBattlerAbility(gBattlerAttacker) == ABILITY_PARENTAL_BOND
|
||||
&& IsMoveAffectedByParentalBond(gCurrentMove, gBattlerAttacker)
|
||||
@ -1852,6 +1853,8 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u
|
||||
s8 buff, accStage, evasionStage;
|
||||
u8 atkParam = GetBattlerHoldEffectParam(battlerAtk);
|
||||
u8 defParam = GetBattlerHoldEffectParam(battlerDef);
|
||||
u8 atkAlly = BATTLE_PARTNER(battlerAtk);
|
||||
u16 atkAllyAbility = GetBattlerAbility(atkAlly);
|
||||
|
||||
gPotentialItemEffectBattler = battlerDef;
|
||||
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].divisor;
|
||||
|
||||
if (atkAbility == ABILITY_COMPOUND_EYES)
|
||||
// Attacker's ability
|
||||
switch (atkAbility)
|
||||
{
|
||||
case ABILITY_COMPOUND_EYES:
|
||||
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
|
||||
if (IsBattlerAlive(BATTLE_PARTNER(battlerAtk)) && GetBattlerAbility(BATTLE_PARTNER(battlerAtk)) == ABILITY_VICTORY_STAR)
|
||||
calc = (calc * 110) / 100; // 1.1 ally's victory star boost
|
||||
break;
|
||||
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)
|
||||
calc = (calc * 80) / 100; // 1.2 sand veil loss
|
||||
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
|
||||
else if (defAbility == ABILITY_TANGLED_FEET && gBattleMons[battlerDef].status2 & STATUS2_CONFUSION)
|
||||
calc = (calc * 50) / 100; // 1.5 tangled feet loss
|
||||
// Target's ability
|
||||
switch (defAbility)
|
||||
{
|
||||
case ABILITY_SAND_VEIL:
|
||||
if (WEATHER_HAS_EFFECT && gBattleWeather & B_WEATHER_SANDSTORM)
|
||||
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))
|
||||
calc = (calc * 80) / 100; // 1.2 hustle loss
|
||||
// Attacker's ally's ability
|
||||
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;
|
||||
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
||||
if (gProtectStructs[battlerAtk].usedMicleBerry)
|
||||
{
|
||||
@ -4144,11 +4183,7 @@ static void Cmd_jumpifsideaffecting(void)
|
||||
u32 flags;
|
||||
const u8 *jumpInstr;
|
||||
|
||||
if (cmd->battler == BS_ATTACKER)
|
||||
side = GET_BATTLER_SIDE(gBattlerAttacker);
|
||||
else
|
||||
side = GET_BATTLER_SIDE(gBattlerTarget);
|
||||
|
||||
side = GET_BATTLER_SIDE(GetBattlerForBattleScript(cmd->battler));
|
||||
flags = cmd->flags;
|
||||
jumpInstr = cmd->jumpInstr;
|
||||
|
||||
@ -8725,8 +8760,9 @@ static bool32 IsTeatimeAffected(u32 battlerId)
|
||||
|
||||
#define UPDATE_COURTCHANGED_BATTLER(structField)\
|
||||
{ \
|
||||
sideTimerPlayer->structField ^= BIT_SIDE; \
|
||||
sideTimerOpp->structField ^= BIT_SIDE; \
|
||||
temp = sideTimerPlayer->structField; \
|
||||
sideTimerPlayer->structField = BATTLE_OPPOSITE(sideTimerOpp->structField); \
|
||||
sideTimerOpp->structField = BATTLE_OPPOSITE(temp); \
|
||||
} \
|
||||
|
||||
static bool32 CourtChangeSwapSideStatuses(void)
|
||||
@ -8761,9 +8797,7 @@ static bool32 CourtChangeSwapSideStatuses(void)
|
||||
UPDATE_COURTCHANGED_BATTLER(auroraVeilBattlerId);
|
||||
UPDATE_COURTCHANGED_BATTLER(tailwindBattlerId);
|
||||
UPDATE_COURTCHANGED_BATTLER(luckyChantBattlerId);
|
||||
|
||||
// For Mirror Armor only
|
||||
gBattleStruct->stickyWebUser = gBattlerAttacker;
|
||||
UPDATE_COURTCHANGED_BATTLER(stickyWebBattlerId);
|
||||
|
||||
// Track which side originally set the Sticky Web
|
||||
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).
|
||||
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."
|
||||
gBattlerAttacker = gBattlerTarget; // Initialize 'fail' condition
|
||||
SET_STATCHANGER(STAT_SPEED, 1, TRUE);
|
||||
if (gBattleStruct->stickyWebUser != 0xFF)
|
||||
gBattlerAttacker = gBattleStruct->stickyWebUser;
|
||||
if (gSideTimers[GetBattlerSide(gActiveBattler)].stickyWebBattlerId != 0xFF)
|
||||
gBattlerAttacker = gSideTimers[GetBattlerSide(gActiveBattler)].stickyWebBattlerId;
|
||||
break;
|
||||
}
|
||||
case VARIOUS_CUT_1_3_HP_RAISE_STATS:
|
||||
@ -14057,9 +14064,9 @@ static void Cmd_setstickyweb(void)
|
||||
else
|
||||
{
|
||||
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].stickyWebAmount = 1;
|
||||
gBattleStruct->stickyWebUser = gBattlerAttacker; // For Mirror Armor
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
}
|
||||
@ -14254,10 +14261,11 @@ static void Cmd_setforcedtarget(void)
|
||||
|
||||
static void Cmd_setcharge(void)
|
||||
{
|
||||
CMD_ARGS();
|
||||
CMD_ARGS(u8 battler);
|
||||
|
||||
gStatuses3[gBattlerAttacker] |= STATUS3_CHARGED_UP;
|
||||
gDisableStructs[gBattlerAttacker].chargeTimer = 2;
|
||||
u8 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
gStatuses3[battler] |= STATUS3_CHARGED_UP;
|
||||
gDisableStructs[battler].chargeTimer = 2;
|
||||
gBattlescriptCurrInstr++;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
@ -16292,13 +16300,6 @@ void BS_GetBattlerSide(void)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
void BS_CanTeleport(void)
|
||||
{
|
||||
NATIVE_ARGS(u8 battler);
|
||||
gBattleCommunication[0] = CanTeleport(cmd->battler);
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
void BS_TrySymbiosis(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
|
@ -3389,10 +3389,9 @@ void SetAtkCancellerForCalledMove(void)
|
||||
gBattleStruct->isAtkCancelerForCalledMove = TRUE;
|
||||
}
|
||||
|
||||
u8 AtkCanceller_UnableToUseMove(void)
|
||||
u8 AtkCanceller_UnableToUseMove(u32 moveType)
|
||||
{
|
||||
u8 effect = 0;
|
||||
s32 *bideDmg = &gBattleScripting.bideDmg;
|
||||
do
|
||||
{
|
||||
switch (gBattleStruct->atkCancellerTracker)
|
||||
@ -3653,7 +3652,7 @@ u8 AtkCanceller_UnableToUseMove(void)
|
||||
if (gTakenDmg[gBattlerAttacker])
|
||||
{
|
||||
gCurrentMove = MOVE_BIDE;
|
||||
*bideDmg = gTakenDmg[gBattlerAttacker] * 2;
|
||||
gBattleScripting.bideDmg = gTakenDmg[gBattlerAttacker] * 2;
|
||||
gBattlerTarget = gTakenDmgByBattler[gBattlerAttacker];
|
||||
if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
|
||||
gBattlerTarget = GetMoveTarget(MOVE_BIDE, MOVE_TARGET_SELECTED + 1);
|
||||
@ -3723,8 +3722,6 @@ u8 AtkCanceller_UnableToUseMove(void)
|
||||
case CANCELLER_POWDER_STATUS:
|
||||
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_POWDER)
|
||||
{
|
||||
u32 moveType;
|
||||
GET_MOVE_TYPE(gCurrentMove, moveType);
|
||||
if (moveType == TYPE_FIRE)
|
||||
{
|
||||
gProtectStructs[gBattlerAttacker].powderSelfDmg = TRUE;
|
||||
@ -3880,14 +3877,15 @@ u8 AtkCanceller_UnableToUseMove2(void)
|
||||
|
||||
bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2)
|
||||
{
|
||||
u8 playerId, flankId;
|
||||
u32 i, side, playerId, flankId;
|
||||
struct Pokemon *party;
|
||||
s32 i;
|
||||
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
|
||||
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);
|
||||
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++)
|
||||
{
|
||||
if (GetMonData(&party[i], MON_DATA_HP) != 0
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG
|
||||
if (IsValidForBattle(&party[i])
|
||||
&& i != partyIdBattlerOn1 && i != partyIdBattlerOn2
|
||||
&& i != *(gBattleStruct->monToSwitchIntoId + flankId) && i != playerId[gBattleStruct->monToSwitchIntoId])
|
||||
break;
|
||||
@ -3912,22 +3908,41 @@ bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2)
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
|
||||
{
|
||||
party = GetBattlerParty(battler);
|
||||
|
||||
playerId = ((battler & BIT_FLANK) / 2);
|
||||
for (i = playerId * MULTI_PARTY_SIZE; i < playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE; i++)
|
||||
if (side == B_SIDE_OPPONENT && WILD_DOUBLE_BATTLE)
|
||||
{
|
||||
if (GetMonData(&party[i], MON_DATA_HP) != 0
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG)
|
||||
break;
|
||||
flankId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
||||
playerId = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
|
||||
|
||||
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)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TOWER_LINK_MULTI)
|
||||
{
|
||||
if (GetBattlerSide(battler) == B_SIDE_PLAYER)
|
||||
if (side == B_SIDE_PLAYER)
|
||||
{
|
||||
party = gPlayerParty;
|
||||
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++)
|
||||
{
|
||||
if (GetMonData(&party[i], MON_DATA_HP) != 0
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG)
|
||||
if (IsValidForBattle(&party[i]))
|
||||
break;
|
||||
}
|
||||
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;
|
||||
|
||||
@ -3969,16 +3982,14 @@ bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2)
|
||||
|
||||
for (i = playerId; i < playerId + MULTI_PARTY_SIZE; i++)
|
||||
{
|
||||
if (GetMonData(&party[i], MON_DATA_HP) != 0
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG)
|
||||
if (IsValidForBattle(&party[i]))
|
||||
break;
|
||||
}
|
||||
return (i == playerId + 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetBattlerSide(battler) == B_SIDE_OPPONENT)
|
||||
if (side == B_SIDE_OPPONENT)
|
||||
{
|
||||
flankId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
||||
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++)
|
||||
{
|
||||
if (GetMonData(&party[i], MON_DATA_HP) != 0
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG
|
||||
if (IsValidForBattle(&party[i])
|
||||
&& i != partyIdBattlerOn1 && i != partyIdBattlerOn2
|
||||
&& i != *(gBattleStruct->monToSwitchIntoId + flankId) && i != playerId[gBattleStruct->monToSwitchIntoId])
|
||||
break;
|
||||
@ -5691,7 +5700,6 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& IsBattlerAlive(gBattlerTarget))
|
||||
{
|
||||
gBattlerAttacker = gBattlerTarget;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_WindPowerActivates;
|
||||
effect++;
|
||||
@ -8004,7 +8012,7 @@ u8 IsMonDisobedient(void)
|
||||
|
||||
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;
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
|
||||
return 0;
|
||||
@ -10068,19 +10076,19 @@ bool32 CanMegaEvolve(u8 battlerId)
|
||||
species = GetMonData(mon, MON_DATA_SPECIES);
|
||||
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.
|
||||
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.
|
||||
if (holdEffect == HOLD_EFFECT_MEGA_STONE)
|
||||
return TRUE;
|
||||
@ -10088,7 +10096,11 @@ bool32 CanMegaEvolve(u8 battlerId)
|
||||
|
||||
// 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)
|
||||
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.
|
||||
return FALSE;
|
||||
|
@ -159,7 +159,6 @@ void QueueZMove(u8 battlerId, u16 baseMove)
|
||||
bool32 IsViableZMove(u8 battlerId, u16 move)
|
||||
{
|
||||
struct Pokemon *mon;
|
||||
struct MegaEvolutionData *mega = &(((struct ChooseMoveStruct *)(&gBattleResources->bufferA[gActiveBattler][4]))->mega);
|
||||
u8 battlerPosition = GetBattlerPosition(battlerId);
|
||||
u8 partnerPosition = GetBattlerPosition(BATTLE_PARTNER(battlerId));
|
||||
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))
|
||||
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 (gBattleStruct->debugHoldEffects[battlerId])
|
||||
holdEffect = gBattleStruct->debugHoldEffects[battlerId];
|
||||
@ -355,9 +345,12 @@ bool32 IsZMoveTriggerSpriteActive(void)
|
||||
|
||||
void HideZMoveTriggerSprite(void)
|
||||
{
|
||||
struct Sprite *sprite = &gSprites[gBattleStruct->zmove.triggerSpriteId];
|
||||
sprite->tHide = TRUE;
|
||||
struct Sprite *sprite;
|
||||
gBattleStruct->zmove.viable = FALSE;
|
||||
if (gBattleStruct->zmove.triggerSpriteId >= MAX_SPRITES)
|
||||
return;
|
||||
sprite = &gSprites[gBattleStruct->zmove.triggerSpriteId];
|
||||
sprite->tHide = TRUE;
|
||||
}
|
||||
|
||||
static void ShowZMoveTriggerSprite(u8 battlerId)
|
||||
|
@ -117,7 +117,7 @@ static const struct WindowTemplate sBerryFixWindowTemplates[] = {
|
||||
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(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),
|
||||
|
@ -1301,8 +1301,8 @@ static void Task_ReadyStartLinkContest(u8 taskId)
|
||||
|
||||
static bool8 SetupContestGraphics(u8 *stateVar)
|
||||
{
|
||||
u16 tempPalette1[16];
|
||||
u16 tempPalette2[16];
|
||||
u16 ALIGNED(4) tempPalette1[16];
|
||||
u16 ALIGNED(4) tempPalette2[16];
|
||||
|
||||
switch (*stateVar)
|
||||
{
|
||||
|
@ -6,7 +6,7 @@
|
||||
#define EVO_HELD_ITEM_FIELD_FUNC ItemUseOutOfBattle_CannotUse
|
||||
#endif
|
||||
|
||||
#if I_GEM_BOOST_POWER >= GEN_5
|
||||
#if I_GEM_BOOST_POWER >= GEN_6
|
||||
#define GEM_BOOST_PARAM 30
|
||||
#else
|
||||
#define GEM_BOOST_PARAM 50
|
||||
|
@ -412,7 +412,7 @@ static void Debug_AddDaycareSteps(u16 numSteps)
|
||||
|
||||
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 0;
|
||||
|
@ -1916,7 +1916,7 @@ static void CopyPalette(u16 *dest, u16 pal)
|
||||
|
||||
static void CopyTile(u8 *dest, u16 tile)
|
||||
{
|
||||
u8 buffer[TILE_SIZE_4BPP];
|
||||
u8 ALIGNED(4) buffer[TILE_SIZE_4BPP];
|
||||
u16 mode;
|
||||
u16 i;
|
||||
|
||||
|
@ -61,7 +61,7 @@ static void None_Main(void);
|
||||
static u8 None_Finish(void);
|
||||
|
||||
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;
|
||||
|
||||
@ -111,7 +111,7 @@ void (*const gWeatherPalStateFuncs[])(void) =
|
||||
|
||||
// This table specifies which of the color maps should be
|
||||
// applied to each of the background and sprite palettes.
|
||||
static const u8 sBasePaletteColorMapTypes[32] =
|
||||
static const u8 ALIGNED(2) sBasePaletteColorMapTypes[32] =
|
||||
{
|
||||
// background palettes
|
||||
COLOR_MAP_DARK_CONTRAST,
|
||||
@ -149,7 +149,7 @@ static const u8 sBasePaletteColorMapTypes[32] =
|
||||
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)
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ struct ConnectionFlags
|
||||
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 Camera gCamera = {0};
|
||||
EWRAM_DATA static struct ConnectionFlags sMapConnectionFlags = {0};
|
||||
|
@ -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_Pal2[] = INCBIN_U16("graphics/battle_frontier/factory_menu2.gbapal");
|
||||
|
||||
const u8 gFrontierFactorySelectMenu_Gfx[] = INCBIN_U8("graphics/battle_frontier/factory_menu1.4bpp");
|
||||
const u8 gFrontierFactorySelectMenu_Gfx2[] = INCBIN_U8("graphics/battle_frontier/factory_menu2.4bpp");
|
||||
const u16 gFrontierFactorySelectMenu_Gfx[] = INCBIN_U16("graphics/battle_frontier/factory_menu1.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");
|
||||
|
||||
|
@ -1096,6 +1096,10 @@ static u8 SetUpCopyrightScreen(void)
|
||||
REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON;
|
||||
SetSerialCallback(SerialCB_CopyrightScreen);
|
||||
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:
|
||||
UpdatePaletteFade();
|
||||
gMain.state++;
|
||||
|
@ -2436,16 +2436,16 @@ static void PrintPocketNames(const u8 *pocketName1, const u8 *pocketName2)
|
||||
|
||||
static void CopyPocketNameToWindow(u32 a)
|
||||
{
|
||||
u8 (* tileDataBuffer)[32][32];
|
||||
u8 (*tileDataBuffer)[32][32];
|
||||
u8 *windowTileData;
|
||||
int b;
|
||||
if (a > 8)
|
||||
a = 8;
|
||||
tileDataBuffer = &gBagMenu->pocketNameBuffer;
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ bool8 gRemoteLinkPlayersNotReceived[MAX_LINK_PLAYERS];
|
||||
u8 gBlockReceivedStatus[MAX_LINK_PLAYERS];
|
||||
u32 gLinkFiller2;
|
||||
u16 gLinkHeldKeys;
|
||||
u16 gRecvCmds[MAX_RFU_PLAYERS][CMD_LENGTH];
|
||||
u16 ALIGNED(4) gRecvCmds[MAX_RFU_PLAYERS][CMD_LENGTH];
|
||||
u32 gLinkStatus;
|
||||
bool8 gLinkDummy1; // Never read
|
||||
bool8 gLinkDummy2; // Never read
|
||||
|
@ -75,7 +75,7 @@ static void Task_FossilFallAndSink(u8);
|
||||
static void SpriteCB_FallingFossil(struct Sprite *);
|
||||
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 u16 sMirageTowerTilemap[] = INCBIN_U16("graphics/misc/mirage_tower.bin");
|
||||
static const u16 sFossil_Pal[] = INCBIN_U16("graphics/object_events/pics/misc/fossil.gbapal"); // Unused
|
||||
|
@ -64,7 +64,7 @@ static EWRAM_DATA struct PaletteStruct sPaletteStructs[NUM_PALETTE_STRUCTS] = {0
|
||||
EWRAM_DATA struct PaletteFadeControl gPaletteFade = {0};
|
||||
static EWRAM_DATA u32 sFiller = 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 = {
|
||||
.id = 0xFFFF,
|
||||
|
@ -1218,13 +1218,13 @@ static u8 LaunchBallFadeMonTaskForPokeball(bool8 unFadeLater, u8 spritePalNum, u
|
||||
#define sTrigIdx data[7]
|
||||
|
||||
// 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;
|
||||
|
||||
LoadCompressedSpriteSheetUsingHeap(&gBallSpriteSheets[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].sFinalMonX = gSprites[monSpriteId].x;
|
||||
|
@ -4537,7 +4537,7 @@ static void PrintDecimalNum(u8 windowId, u16 num, u8 left, u8 top)
|
||||
|
||||
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)];
|
||||
u32 i, j, tileIdx = 0;
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
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_Tilemap[] = INCBIN_U32("graphics/pokedex/region_map.bin.lz");
|
||||
static const u32 sPokedexAreaMapAffine_Gfx[] = INCBIN_U32("graphics/pokedex/region_map_affine.8bpp.lz");
|
||||
|
@ -4627,7 +4627,11 @@ static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 perso
|
||||
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;
|
||||
|
||||
@ -4685,7 +4689,13 @@ u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data)
|
||||
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;
|
||||
u32 retVal = 0;
|
||||
@ -5041,6 +5051,8 @@ u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data)
|
||||
return retVal;
|
||||
}
|
||||
|
||||
u32 GetBoxMonData2(struct BoxPokemon *boxMon, s32 field) __attribute__((alias("GetBoxMonData3")));
|
||||
|
||||
#define SET8(lhs) (lhs) = *data
|
||||
#define SET16(lhs) (lhs) = data[0] + (data[1] << 8)
|
||||
#define SET32(lhs) (lhs) = data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24)
|
||||
|
@ -552,8 +552,8 @@ struct PokemonStorageSystemData
|
||||
u16 *displayMonTilePtr;
|
||||
struct Sprite *displayMonSprite;
|
||||
u16 displayMonPalBuffer[0x40];
|
||||
u8 tileBuffer[MON_PIC_SIZE * MAX_MON_PIC_FRAMES];
|
||||
u8 itemIconBuffer[0x800];
|
||||
u8 ALIGNED(4) tileBuffer[MON_PIC_SIZE * MAX_MON_PIC_FRAMES];
|
||||
u8 ALIGNED(4) itemIconBuffer[0x800];
|
||||
u8 wallpaperBgTilemapBuffer[0x1000];
|
||||
u8 displayMenuTilemapBuffer[0x800];
|
||||
};
|
||||
@ -10150,7 +10150,7 @@ void UpdateSpeciesSpritePSS(struct BoxPokemon *boxMon)
|
||||
{
|
||||
DestroyBoxMonIcon(sStorage->boxMonsSprites[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;
|
||||
|
@ -116,10 +116,12 @@ static const LoopedTask sLoopedTaskFuncs[] =
|
||||
[CONDITION_FUNC_CLOSE_MARKINGS] = LoopedTask_CloseMonMarkingsWindow
|
||||
};
|
||||
|
||||
typedef u8 ALIGNED(4) TilemapBuffer[BG_SCREEN_SIZE];
|
||||
|
||||
struct Pokenav_ConditionMenuGfx
|
||||
{
|
||||
u32 loopedTaskId;
|
||||
u8 tilemapBuffers[3][BG_SCREEN_SIZE];
|
||||
TilemapBuffer tilemapBuffers[3];
|
||||
u8 filler[2];
|
||||
u8 partyPokeballSpriteIds[PARTY_SIZE + 1];
|
||||
u32 (*callback)(void);
|
||||
|
@ -35,7 +35,7 @@ struct Pokenav_RegionMapGfx
|
||||
u32 loopTaskId;
|
||||
u16 infoWindowId;
|
||||
struct Sprite *cityZoomTextSprites[3];
|
||||
u8 tilemapBuffer[BG_SCREEN_SIZE];
|
||||
u8 ALIGNED(2) tilemapBuffer[BG_SCREEN_SIZE];
|
||||
u8 cityZoomPics[NUM_CITY_MAPS][200];
|
||||
};
|
||||
|
||||
|
@ -60,10 +60,12 @@ enum
|
||||
|
||||
#define MAX_SMOKE 10
|
||||
|
||||
typedef u8 ALIGNED(4) TilemapBuffer[BG_SCREEN_SIZE];
|
||||
|
||||
struct RayquazaScene
|
||||
{
|
||||
MainCallback exitCallback;
|
||||
u8 tilemapBuffers[4][BG_SCREEN_SIZE];
|
||||
TilemapBuffer tilemapBuffers[4];
|
||||
u16 unk; // never read
|
||||
u8 animId;
|
||||
bool8 endEarly;
|
||||
|
@ -13,7 +13,7 @@ static void CopyValue32Bit(void);
|
||||
// Per-scanline register values.
|
||||
// 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
|
||||
EWRAM_DATA u16 gScanlineEffectRegBuffers[2][0x3C0] = {0};
|
||||
EWRAM_DATA u16 ALIGNED(4) gScanlineEffectRegBuffers[2][0x3C0] = {0};
|
||||
|
||||
EWRAM_DATA struct ScanlineEffect gScanlineEffect = {0};
|
||||
EWRAM_DATA static bool8 sShouldStopWaveTask = FALSE;
|
||||
|
0
src/script_pokemon_util.c
Executable file → Normal file
0
src/script_pokemon_util.c
Executable file → Normal file
@ -158,7 +158,7 @@ void CopySpriteTiles(u8 shape, u8 size, u8 *tiles, u16 *tilemap, u8 *output)
|
||||
{
|
||||
u8 x, y;
|
||||
s8 i, j;
|
||||
u8 xflip[32];
|
||||
u8 ALIGNED(4) xflip[32];
|
||||
u8 h = sSpriteDimensions[shape][size][1];
|
||||
u8 w = sSpriteDimensions[shape][size][0];
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Blaze boosts Fire-type moves in a pinch", s16 damage)
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Clear Body prevents intimidate")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Cloud Nine prevents weather effects")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Compound Eyes raises accuracy")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Cute Charm inflicts infatuation on contact")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Damp prevents explosion-like moves from enemies")
|
||||
{
|
67
test/battle/ability/desolate_land.c
Normal file
67
test/battle/ability/desolate_land.c
Normal 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.");
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Drizzle summons rain", s16 damage)
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Dry Skin causes 1/8th Max HP damage in Sun")
|
||||
{
|
56
test/battle/ability/electromorphosis.c
Normal file
56
test/battle/ability/electromorphosis.c
Normal 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);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Flame Body inflicts burn on contact")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Flower Gift transforms Cherrim in harsh sunlight")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Forecast transforms Castform in weather from an opponent's move")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Full Metal Body prevents intimidate")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#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")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Hydration cures non-volatile Status conditions if it is raining")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Hyper Cutter prevents intimidate")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Ice Body prevents damage from hail")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Immunity prevents Poison Sting poison")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Inner Focus prevents intimidate")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Insomnia prevents sleep")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Leaf Guard prevents non-volatile status conditions in sun")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Limber prevents paralysis")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
|
||||
SINGLE_BATTLE_TEST("Magic Bounce bounces back status moves")
|
202
test/battle/ability/mirror_armor.c
Normal file
202
test/battle/ability/mirror_armor.c
Normal 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!");
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Oblivious prevents Infatuation")
|
||||
{
|
21
test/battle/ability/overcoat.c
Normal file
21
test/battle/ability/overcoat.c
Normal 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");
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Overgrow boosts Grass-type moves in a pinch", s16 damage)
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Own Tempo prevents intimidate")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Pastel Veil prevents Poison Sting poison")
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Poison Point inflicts poison on contact")
|
||||
{
|
66
test/battle/ability/primordial_sea.c
Normal file
66
test/battle/ability/primordial_sea.c
Normal 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.");
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "test_battle.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user