diff --git a/.all-contributorsrc b/.all-contributorsrc
index a441c1abc7..b80a18d4c5 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -581,10 +581,10 @@
]
},
{
- "login": "izrofid",
- "name": "Kildemal",
+ "login": "miriamlefae",
+ "name": "Miriam",
"avatar_url": "https://avatars.githubusercontent.com/u/206095739?v=4",
- "profile": "https://github.com/izrofid",
+ "profile": "https://github.com/miriamlefae",
"contributions": [
"code"
]
@@ -715,6 +715,15 @@
"contributions": [
"code"
]
+ },
+ {
+ "login": "Gastly92",
+ "name": "Gastly92",
+ "avatar_url": "https://avatars.githubusercontent.com/u/262681076?v=4",
+ "profile": "https://github.com/Gastly92",
+ "contributions": [
+ "code"
+ ]
}
],
"contributorsPerLine": 7,
diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml
index 42a31171b7..dc13c04856 100644
--- a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml
+++ b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml
@@ -43,9 +43,10 @@ body:
label: Version
description: What version of pokeemerald-expansion are you using?
options:
- - 1.16.0 (Latest release)
+ - 1.16.1 (Latest release)
- master (default, unreleased bugfixes)
- upcoming (Edge)
+ - 1.16.0
- 1.15.3
- 1.15.2
- 1.15.1
diff --git a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml
index 28943effda..48f3793e6d 100644
--- a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml
+++ b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml
@@ -43,9 +43,10 @@ body:
label: Version
description: What version of pokeemerald-expansion are you using?
options:
- - 1.16.0 (Latest release)
+ - 1.16.1 (Latest release)
- master (default, unreleased bugfixes)
- upcoming (Edge)
+ - 1.16.0
- 1.15.3
- 1.15.2
- 1.15.1
diff --git a/.github/ISSUE_TEMPLATE/04_other_errors.yaml b/.github/ISSUE_TEMPLATE/04_other_errors.yaml
index cda4d6dc2f..3c7bd9cf70 100644
--- a/.github/ISSUE_TEMPLATE/04_other_errors.yaml
+++ b/.github/ISSUE_TEMPLATE/04_other_errors.yaml
@@ -43,9 +43,10 @@ body:
label: Version
description: What version of pokeemerald-expansion are you using?
options:
- - 1.16.0 (Latest release)
+ - 1.16.1 (Latest release)
- master (default, unreleased bugfixes)
- upcoming (Edge)
+ - 1.16.0
- 1.15.3
- 1.15.2
- 1.15.1
diff --git a/CREDITS.md b/CREDITS.md
index ac6209db3b..f761d3f086 100644
--- a/CREDITS.md
+++ b/CREDITS.md
@@ -1,6 +1,6 @@
## Credits ✨
-Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
+Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/en/reference/emoji-key/)):
@@ -102,6 +102,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
 blusunrize 🐛 💻 |
 jtebbe 💻 |
 Liam 💻 |
+  Gastly92 💻 |
@@ -119,7 +120,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
-This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
+This project follows the [all-contributors](https://github.com/all-contributors/allcontributors.org) specification. Contributions of any kind welcome!
## Other Credits
### Mega Evolution Overworld Sprite Credits:
diff --git a/Makefile b/Makefile
index d4c75585b4..37249891fa 100644
--- a/Makefile
+++ b/Makefile
@@ -105,8 +105,8 @@ ASSETS_DIR_NAME := $(BUILD_DIR)/assets
ELF_NAME := $(ROM_NAME:.gba=.elf)
MAP_NAME := $(ROM_NAME:.gba=.map)
-TESTELF = $(ROM_NAME:.gba=-test.elf)
-HEADLESSELF = $(ROM_NAME:.gba=-test-headless.elf)
+TESTELF := $(ROM_NAME:.gba=-test.elf)
+HEADLESSELF := $(ROM_NAME:.gba=-test-headless.elf)
# Pick our active variables
ROM := $(ROM_NAME)
diff --git a/README.md b/README.md
index c768a6f5d8..0c4eac3dc1 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@
If you use **`pokeemerald-expansion`**, please credit **RHH (Rom Hacking Hideout)**. Optionally, include the version number for clarity.
```
-Based off RHH's pokeemerald-expansion 1.16.0 https://github.com/rh-hideout/pokeemerald-expansion/
+Based off RHH's pokeemerald-expansion 1.16.1 https://github.com/rh-hideout/pokeemerald-expansion/
```
Please consider [crediting all contributors](CREDITS.md) involved in the project!
diff --git a/charmap.txt b/charmap.txt
index 24fbba0d17..348f00cfb2 100644
--- a/charmap.txt
+++ b/charmap.txt
@@ -432,7 +432,7 @@ B_EFF_TEAM2 = FD 47
NAME_END = FC 00
@ special 0xF7 character
-DYNAMIC = F7
+DYNAMIC = F7
@ more text functions
diff --git a/data/maps/BattleFrontier_BattleTowerMultiPartnerRoom/scripts.inc b/data/maps/BattleFrontier_BattleTowerMultiPartnerRoom/scripts.inc
index 6cd428c8ed..920f912a9e 100644
--- a/data/maps/BattleFrontier_BattleTowerMultiPartnerRoom/scripts.inc
+++ b/data/maps/BattleFrontier_BattleTowerMultiPartnerRoom/scripts.inc
@@ -126,7 +126,7 @@ BattleFrontier_BattleTowerMultiPartnerRoom_EventScript_MoveToElevatorEast:
@ Unused
BattleFrontier_BattleTowerMultiPartnerRoom_EventScript_MoveToElevatorWest:
applymovement LOCALID_TOWER_PARTNER_ROOM_ATTENDANT, BattleFrontier_BattleTowerMultiPartnerRoom_Movement_AttendantEnterElevator
- applymovement LOCALID_PLAYER, BattleFrontier_BattleTowerMultiPartnerRoom_Movement_PlayerEneterElevatorWest
+ applymovement LOCALID_PLAYER, BattleFrontier_BattleTowerMultiPartnerRoom_Movement_PlayerEnterElevatorWest
waitmovement 0
return
@@ -144,7 +144,7 @@ BattleFrontier_BattleTowerMultiPartnerRoom_Movement_PlayerEnterElevatorEast:
step_end
@ Functionally unused
-BattleFrontier_BattleTowerMultiPartnerRoom_Movement_PlayerEneterElevatorWest:
+BattleFrontier_BattleTowerMultiPartnerRoom_Movement_PlayerEnterElevatorWest:
walk_left
walk_up
set_invisible
diff --git a/data/maps/MtChimney/scripts.inc b/data/maps/MtChimney/scripts.inc
index cdff230d77..cf0fde9738 100644
--- a/data/maps/MtChimney/scripts.inc
+++ b/data/maps/MtChimney/scripts.inc
@@ -471,7 +471,7 @@ MtChimney_EventScript_MachineOff::
end
MtChimney_EventScript_MachineOn::
- msgbox MtChimney_Text_MetoriteFittedOnMachine, MSGBOX_DEFAULT
+ msgbox MtChimney_Text_MeteoriteFittedOnMachine, MSGBOX_DEFAULT
releaseall
end
@@ -726,7 +726,7 @@ MtChimney_Text_YouveNotGotTheMoney:
MtChimney_Text_OhFineThen:
.string "Oh, fine then.$"
-MtChimney_Text_MetoriteFittedOnMachine:
+MtChimney_Text_MeteoriteFittedOnMachine:
.string "A METEORITE is fitted on a mysterious\n"
.string "machine…\p"
.string "The machine seems to be storing\n"
diff --git a/data/maps/Route124_DivingTreasureHuntersHouse/scripts.inc b/data/maps/Route124_DivingTreasureHuntersHouse/scripts.inc
index b100438f55..cd5c6c6806 100644
--- a/data/maps/Route124_DivingTreasureHuntersHouse/scripts.inc
+++ b/data/maps/Route124_DivingTreasureHuntersHouse/scripts.inc
@@ -328,11 +328,11 @@ Route124_DivingTreasureHuntersHouse_Text_ComeBackIfYouChangeMind:
.string "Well, if you change your mind, come back.$"
Route124_DivingTreasureHuntersHouse_Text_ShardTradeBoard:
- .string "{CLEAR_TO 0x0a}Wanted item{CLEAR_TO 0x7c}Trade item\n"
- .string "{CLEAR_TO 0x0f}RED SHARD{CLEAR_TO 0x59}{LEFT_ARROW}{RIGHT_ARROW}{CLEAR_TO 0x7b}FIRE STONE{CLEAR_TO 0xc8}\p"
- .string "{CLEAR_TO 0x0a}Wanted item{CLEAR_TO 0x7c}Trade item\n"
- .string "{CLEAR_TO 0x06}YELLOW SHARD{CLEAR_TO 0x59}{LEFT_ARROW}{RIGHT_ARROW}{CLEAR_TO 0x73}THUNDERSTONE{CLEAR_TO 0xc8}\p"
- .string "{CLEAR_TO 0x0a}Wanted item{CLEAR_TO 0x7c}Trade item\n"
- .string "{CLEAR_TO 0x0c}BLUE SHARD{CLEAR_TO 0x59}{LEFT_ARROW}{RIGHT_ARROW}{CLEAR_TO 0x79}WATER STONE{CLEAR_TO 0xc8}\p"
- .string "{CLEAR_TO 0x0a}Wanted item{CLEAR_TO 0x7c}Trade item\n"
- .string "{CLEAR_TO 0x08}GREEN SHARD{CLEAR_TO 0x59}{LEFT_ARROW}{RIGHT_ARROW}{CLEAR_TO 0x7b}LEAF STONE$"
+ .string "{CLEAR_TO 10}Wanted item{CLEAR_TO 124}Trade item\n"
+ .string "{CLEAR_TO 15}RED SHARD{CLEAR_TO 89}{LEFT_ARROW}{RIGHT_ARROW}{CLEAR_TO 123}FIRE STONE{CLEAR_TO 200}\p"
+ .string "{CLEAR_TO 10}Wanted item{CLEAR_TO 124}Trade item\n"
+ .string "{CLEAR_TO 6}YELLOW SHARD{CLEAR_TO 89}{LEFT_ARROW}{RIGHT_ARROW}{CLEAR_TO 115}THUNDERSTONE{CLEAR_TO 200}\p"
+ .string "{CLEAR_TO 10}Wanted item{CLEAR_TO 124}Trade item\n"
+ .string "{CLEAR_TO 12}BLUE SHARD{CLEAR_TO 89}{LEFT_ARROW}{RIGHT_ARROW}{CLEAR_TO 121}WATER STONE{CLEAR_TO 200}\p"
+ .string "{CLEAR_TO 10}Wanted item{CLEAR_TO 124}Trade item\n"
+ .string "{CLEAR_TO 8}GREEN SHARD{CLEAR_TO 89}{LEFT_ARROW}{RIGHT_ARROW}{CLEAR_TO 123}LEAF STONE$"
diff --git a/data/scripts/cable_club_frlg.inc b/data/scripts/cable_club_frlg.inc
index bd2f91a412..bba62dda1d 100644
--- a/data/scripts/cable_club_frlg.inc
+++ b/data/scripts/cable_club_frlg.inc
@@ -298,7 +298,7 @@ CableClub_EventScript_EnterColosseum_Frlg::
release
goto_if_eq VAR_0x8004, USING_MULTI_BATTLE, CableClub_EventScript_WarpTo4PColosseum_Frlg
special SetCableClubWarp
- warp MAP_BATTLE_COLOSSEUM_2P, 6, 8
+ warp MAP_BATTLE_COLOSSEUM_2P_FRLG, 6, 8
special DoCableClubWarp
end
@@ -310,7 +310,7 @@ CableClub_EventScript_PlayerApproachLinkRoomRight_Frlg::
CableClub_EventScript_WarpTo4PColosseum_Frlg::
special SetCableClubWarp
- warp MAP_BATTLE_COLOSSEUM_4P, 5, 8
+ warp MAP_BATTLE_COLOSSEUM_4P_FRLG, 5, 8
special DoCableClubWarp
end
diff --git a/data/scripts/mart_clerk.inc b/data/scripts/mart_clerk.inc
index 2b9f872e85..a947ce1711 100644
--- a/data/scripts/mart_clerk.inc
+++ b/data/scripts/mart_clerk.inc
@@ -6,7 +6,7 @@ gText_PleaseComeAgain::
.string "Please come again!$"
gText_PlayerWhatCanIDoForYou::
- .string "{PLAYER}{STRING 5}, welcome!\p"
+ .string "{PLAYER}{KUN}, welcome!\p"
.string "What can I do for you?$"
Pokemart_DefaultItemList::
diff --git a/data/scripts/std_msgbox.inc b/data/scripts/std_msgbox.inc
index 541ec384d1..cb95b5ebf7 100644
--- a/data/scripts/std_msgbox.inc
+++ b/data/scripts/std_msgbox.inc
@@ -33,7 +33,7 @@ Std_ReceivedItem::
textcolor NPC_TEXT_COLOR_NEUTRAL
call_if_eq VAR_0x8002, MUS_LEVEL_UP, EventScript_ReceivedItemFanfare1
call_if_eq VAR_0x8002, MUS_RG_OBTAIN_KEY_ITEM, EventScript_ReceivedItemFanfare2
- message 0x0
+ message NULL
waitmessage
waitfanfare
call_if_eq VAR_0x8002, MUS_LEVEL_UP, EventScript_ReceivedItemWaitFanfare
diff --git a/data/text/lottery_corner.inc b/data/text/lottery_corner.inc
index 44571ef562..e86cdff59c 100644
--- a/data/text/lottery_corner.inc
+++ b/data/text/lottery_corner.inc
@@ -16,7 +16,7 @@ LilycoveCity_DepartmentStore_1F_Text_PleaseVisitAgain:
LilycoveCity_DepartmentStore_1F_Text_PleasePickTicket:
.string "Please pick a LOTO TICKET.\n"
- .string "…{PAUSE 0x0F}{PAUSE 0x0F}{PAUSE 0x0F}{PAUSE 0x0F}…{PAUSE 0x0F}{PAUSE 0x0F}{PAUSE 0x0F}{PAUSE 0x0F}…{PAUSE 0x0F}{PAUSE 0x0F}{PAUSE 0x0F}{PAUSE 0x0F}$"
+ .string "…{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}…{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}…{PAUSE 15}{PAUSE 15}{PAUSE 15}{PAUSE 15}$"
LilycoveCity_DepartmentStore_1F_Text_TicketNumberIsXPleaseWait:
.string "The LOTO TICKET number is {STR_VAR_1}.\p"
diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md
index 807404bff7..5deb27670e 100644
--- a/docs/SUMMARY.md
+++ b/docs/SUMMARY.md
@@ -58,6 +58,7 @@
- [How to use dynamic trainer battle scripts](tutorials/how_to_dynamic_trainer_script.md)
- [Changelog](./CHANGELOG.md)
- [1.16.x]()
+ - [Version 1.16.1](changelogs/1.16.x/1.16.1.md)
- [Version 1.16.0](changelogs/1.16.x/1.16.0.md)
- [1.15.x]()
- [Version 1.15.3](changelogs/1.15.x/1.15.3.md)
diff --git a/docs/changelogs/1.16.x/1.16.1.md b/docs/changelogs/1.16.x/1.16.1.md
new file mode 100644
index 0000000000..4ab9c54104
--- /dev/null
+++ b/docs/changelogs/1.16.x/1.16.1.md
@@ -0,0 +1,90 @@
+```md
+## How to update
+- If you haven't set up a remote, run the command `git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion`.
+- Once you have your remote set up, run the command `git pull RHH expansion/1.16.1
+`.
+```
+
+
+## 🧬 General 🧬
+### Added
+* Add `if_comptime` by @mrgriffin in [#10130](https://github.com/rh-hideout/pokeemerald-expansion/pull/10130)
+
+### Changed
+* Cleanup 'message 0x0' by @mrgriffin in [#10110](https://github.com/rh-hideout/pokeemerald-expansion/pull/10110)
+* Fix Trainer Party Pool documentation by @RubyRaven6 in [#10122](https://github.com/rh-hideout/pokeemerald-expansion/pull/10122)
+* Remove deprecated ``HQ_RANDOM`` config by @Bassoonian in [#10131](https://github.com/rh-hideout/pokeemerald-expansion/pull/10131)
+
+### Fixed
+* chore(credits): change kildemal to miriam in credits by @miriamlefae in [#10123](https://github.com/rh-hideout/pokeemerald-expansion/pull/10123)
+* Misc Fixes/Cleanups by @mrgriffin in [#9892](https://github.com/rh-hideout/pokeemerald-expansion/pull/9892)
+* Fix HGSS Dex Form Strings by @HashtagMarky in [#10147](https://github.com/rh-hideout/pokeemerald-expansion/pull/10147)
+
+## 🗺️ Overworld 🗺️
+### Changed
+* assertf for NULL goto/call by @mrgriffin in [#10111](https://github.com/rh-hideout/pokeemerald-expansion/pull/10111)
+
+### Fixed
+* Fix colosseum warps frlg by @Viperio19 in [#10100](https://github.com/rh-hideout/pokeemerald-expansion/pull/10100)
+
+## 🐉 Pokémon 🐉
+### Changed
+* Fix missing incgfx for Mega Garchomp Z by @hedara90 in [#10116](https://github.com/rh-hideout/pokeemerald-expansion/pull/10116)
+
+## ⚔️ Battle General ⚔️
+### Changed
+* feat (battle): improve gimmick triggers' graphics by @mudskipper13 in [#10129](https://github.com/rh-hideout/pokeemerald-expansion/pull/10129)
+
+### Fixed
+* Fixes stat change queue having erroneous stats stored by @AlexOn1ine in [#10088](https://github.com/rh-hideout/pokeemerald-expansion/pull/10088)
+* Fixes Acupressure timeout in doubles by @AlexOn1ine in [#10091](https://github.com/rh-hideout/pokeemerald-expansion/pull/10091)
+* Fixes Random Move from disobedience by @AlexOn1ine in [#10093](https://github.com/rh-hideout/pokeemerald-expansion/pull/10093)
+* Fix link singles and doubles using incorrect parties by @Viperio19 in [#10102](https://github.com/rh-hideout/pokeemerald-expansion/pull/10102)
+* Fix player's hp display showing 0 max hp for p2 in link battles after taking damage by @Viperio19 in [#10105](https://github.com/rh-hideout/pokeemerald-expansion/pull/10105)
+* Fix generic ability ineffective battle message misuse by @Cle-bit in [#10149](https://github.com/rh-hideout/pokeemerald-expansion/pull/10149)
+
+## 🧶 Items 🧶
+### Changed
+* Add missing item sort types by @Cle-bit in [#10104](https://github.com/rh-hideout/pokeemerald-expansion/pull/10104)
+* SanitizeBagItemId, TryTakeMonItemResult by @mrgriffin in [#10109](https://github.com/rh-hideout/pokeemerald-expansion/pull/10109)
+
+### Fixed
+* Use values from `enum PokeBall` for Poké Balls by @PCG06 in [#10106](https://github.com/rh-hideout/pokeemerald-expansion/pull/10106)
+
+## 🤖 Battle AI 🤖
+### Fixed
+* Prevent AI illegally targeting itself in doubles by @grintoul1 in [#10139](https://github.com/rh-hideout/pokeemerald-expansion/pull/10139)
+
+## 🧹 Other Cleanup 🧹
+* Add missing item sort types by @Cle-bit in [#10104](https://github.com/rh-hideout/pokeemerald-expansion/pull/10104)
+* Cleanup 'message 0x0' by @mrgriffin in [#10110](https://github.com/rh-hideout/pokeemerald-expansion/pull/10110)
+* SanitizeBagItemId, TryTakeMonItemResult by @mrgriffin in [#10109](https://github.com/rh-hideout/pokeemerald-expansion/pull/10109)
+* feat (battle): improve gimmick triggers' graphics by @mudskipper13 in [#10129](https://github.com/rh-hideout/pokeemerald-expansion/pull/10129)
+* assertf for NULL goto/call by @mrgriffin in [#10111](https://github.com/rh-hideout/pokeemerald-expansion/pull/10111)
+* Remove deprecated ``HQ_RANDOM`` config by @Bassoonian in [#10131](https://github.com/rh-hideout/pokeemerald-expansion/pull/10131)
+* Fix Beat Up typeless damage test effectiveness check by @Cle-bit in [#10103](https://github.com/rh-hideout/pokeemerald-expansion/pull/10103)
+
+## 🧪 Test Runner 🧪
+### Changed
+* Fix Beat Up typeless damage test effectiveness check by @Cle-bit in [#10103](https://github.com/rh-hideout/pokeemerald-expansion/pull/10103)
+
+### Fixed
+* Prevent AI illegally targeting itself in doubles by @grintoul1 in [#10139](https://github.com/rh-hideout/pokeemerald-expansion/pull/10139)
+
+## 📚 Documentation 📚
+* Fix Trainer Party Pool documentation by @RubyRaven6 in [#10122](https://github.com/rh-hideout/pokeemerald-expansion/pull/10122)
+* Fix broken/old links in CREDITS.md by @ThePeeps191 in [#10120](https://github.com/rh-hideout/pokeemerald-expansion/pull/10120)
+
+## 📦 Branch Synchronisation 📦
+### pret
+* 1st of June, 2026 in [#10113](https://github.com/rh-hideout/pokeemerald-expansion/pull/10113)
+ * Implicit waitstate for special/specialvars by @mrgriffin in [pret#2200](https://github.com/pret/pokeemerald/pull/2200)
+
+## New Contributors
+* @Viperio19 made their first contribution in [#10100](https://github.com/rh-hideout/pokeemerald-expansion/pull/10100)
+
+**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.16.0...expansion/1.16.1
+
+
+
+
diff --git a/docs/tutorials/how_to_trainer_party_pool.md b/docs/tutorials/how_to_trainer_party_pool.md
index e111ba957e..b0045249c8 100644
--- a/docs/tutorials/how_to_trainer_party_pool.md
+++ b/docs/tutorials/how_to_trainer_party_pool.md
@@ -3,7 +3,7 @@ Trainer Party Pools (TPP) is a way to introduce a bit of unpredictability to tra
The maximum number of mons that can be in a single trainer's pool is 255.
-## Turning on TPP with `trainer.sparty`
+## Turning on TPP with `trainers.party`
To use TPP with `trainers.party`, all that's needed is to define a `Party Size` that's smaller than than the number of defined mons for the trainer.
## Turning on TPP with `trainers.h`
@@ -69,7 +69,7 @@ Double Battle: Yes
AI: Check Bad Move
Party Size: 4
Pool Rules: Weather Doubles
-Pool Pick Index: Default
+Pool Pick Functions: Default
Zigzagoon
Level: 4
diff --git a/graphics/battle_interface/burst_trigger.png b/graphics/battle_interface/burst_trigger.png
index bbd16ac555..f9b1f13707 100644
Binary files a/graphics/battle_interface/burst_trigger.png and b/graphics/battle_interface/burst_trigger.png differ
diff --git a/graphics/battle_interface/dynamax_trigger.png b/graphics/battle_interface/dynamax_trigger.png
index 18f3a84cff..954de81e7c 100644
Binary files a/graphics/battle_interface/dynamax_trigger.png and b/graphics/battle_interface/dynamax_trigger.png differ
diff --git a/graphics/battle_interface/mega_trigger.pal b/graphics/battle_interface/mega_trigger.pal
deleted file mode 100644
index 2672d1f10a..0000000000
--- a/graphics/battle_interface/mega_trigger.pal
+++ /dev/null
@@ -1,19 +0,0 @@
-JASC-PAL
-0100
-16
-185 207 163
-77 105 97
-199 159 199
-221 177 207
-57 151 117
-139 221 253
-247 161 133
-255 255 255
-153 87 67
-233 233 125
-129 255 223
-149 147 247
-195 207 201
-123 151 135
-0 0 0
-0 0 0
diff --git a/graphics/battle_interface/mega_trigger.png b/graphics/battle_interface/mega_trigger.png
index a269ee738c..bdb3e8e957 100644
Binary files a/graphics/battle_interface/mega_trigger.png and b/graphics/battle_interface/mega_trigger.png differ
diff --git a/graphics/battle_interface/tera_trigger.png b/graphics/battle_interface/tera_trigger.png
index 5498ea8806..660880acf9 100644
Binary files a/graphics/battle_interface/tera_trigger.png and b/graphics/battle_interface/tera_trigger.png differ
diff --git a/graphics/battle_interface/z_move_trigger.png b/graphics/battle_interface/z_move_trigger.png
index 7d5fbaba0f..907a4cf20c 100644
Binary files a/graphics/battle_interface/z_move_trigger.png and b/graphics/battle_interface/z_move_trigger.png differ
diff --git a/graphics/pokemon/bounsweet/anim_front.png b/graphics/pokemon/bounsweet/anim_front.png
new file mode 100644
index 0000000000..d9a30f545d
Binary files /dev/null and b/graphics/pokemon/bounsweet/anim_front.png differ
diff --git a/graphics/pokemon/bounsweet/front.png b/graphics/pokemon/bounsweet/front.png
deleted file mode 100644
index 9e09d6d728..0000000000
Binary files a/graphics/pokemon/bounsweet/front.png and /dev/null differ
diff --git a/graphics/pokemon/bruxish/anim_front.png b/graphics/pokemon/bruxish/anim_front.png
new file mode 100644
index 0000000000..b9485d270b
Binary files /dev/null and b/graphics/pokemon/bruxish/anim_front.png differ
diff --git a/graphics/pokemon/bruxish/front.png b/graphics/pokemon/bruxish/front.png
deleted file mode 100644
index ce29eb8d5f..0000000000
Binary files a/graphics/pokemon/bruxish/front.png and /dev/null differ
diff --git a/graphics/pokemon/comfey/anim_front.png b/graphics/pokemon/comfey/anim_front.png
new file mode 100644
index 0000000000..a76dd3b51e
Binary files /dev/null and b/graphics/pokemon/comfey/anim_front.png differ
diff --git a/graphics/pokemon/comfey/front.png b/graphics/pokemon/comfey/front.png
deleted file mode 100644
index d2e8709651..0000000000
Binary files a/graphics/pokemon/comfey/front.png and /dev/null differ
diff --git a/graphics/pokemon/cosmog/anim_front.png b/graphics/pokemon/cosmog/anim_front.png
new file mode 100644
index 0000000000..a348e884e9
Binary files /dev/null and b/graphics/pokemon/cosmog/anim_front.png differ
diff --git a/graphics/pokemon/cosmog/front.png b/graphics/pokemon/cosmog/front.png
deleted file mode 100644
index c1c2cba84f..0000000000
Binary files a/graphics/pokemon/cosmog/front.png and /dev/null differ
diff --git a/graphics/pokemon/dhelmise/anim_front.png b/graphics/pokemon/dhelmise/anim_front.png
new file mode 100644
index 0000000000..06d1ebed11
Binary files /dev/null and b/graphics/pokemon/dhelmise/anim_front.png differ
diff --git a/graphics/pokemon/dhelmise/front.png b/graphics/pokemon/dhelmise/front.png
deleted file mode 100644
index 1181df89b9..0000000000
Binary files a/graphics/pokemon/dhelmise/front.png and /dev/null differ
diff --git a/graphics/pokemon/fomantis/anim_front.png b/graphics/pokemon/fomantis/anim_front.png
new file mode 100644
index 0000000000..97448d37a6
Binary files /dev/null and b/graphics/pokemon/fomantis/anim_front.png differ
diff --git a/graphics/pokemon/fomantis/front.png b/graphics/pokemon/fomantis/front.png
deleted file mode 100644
index 116850706e..0000000000
Binary files a/graphics/pokemon/fomantis/front.png and /dev/null differ
diff --git a/graphics/pokemon/komala/anim_front.png b/graphics/pokemon/komala/anim_front.png
new file mode 100644
index 0000000000..58fa1eba70
Binary files /dev/null and b/graphics/pokemon/komala/anim_front.png differ
diff --git a/graphics/pokemon/komala/front.png b/graphics/pokemon/komala/front.png
deleted file mode 100644
index 8b8c6cb687..0000000000
Binary files a/graphics/pokemon/komala/front.png and /dev/null differ
diff --git a/graphics/pokemon/morelull/anim_front.png b/graphics/pokemon/morelull/anim_front.png
new file mode 100644
index 0000000000..1f9a8e915d
Binary files /dev/null and b/graphics/pokemon/morelull/anim_front.png differ
diff --git a/graphics/pokemon/morelull/front.png b/graphics/pokemon/morelull/front.png
deleted file mode 100644
index 73c2c96425..0000000000
Binary files a/graphics/pokemon/morelull/front.png and /dev/null differ
diff --git a/graphics/pokemon/palossand/anim_front.png b/graphics/pokemon/palossand/anim_front.png
new file mode 100644
index 0000000000..0cb8750303
Binary files /dev/null and b/graphics/pokemon/palossand/anim_front.png differ
diff --git a/graphics/pokemon/palossand/front.png b/graphics/pokemon/palossand/front.png
deleted file mode 100644
index d22845d345..0000000000
Binary files a/graphics/pokemon/palossand/front.png and /dev/null differ
diff --git a/graphics/pokemon/sandygast/anim_front.png b/graphics/pokemon/sandygast/anim_front.png
new file mode 100644
index 0000000000..bd8e8ed0b6
Binary files /dev/null and b/graphics/pokemon/sandygast/anim_front.png differ
diff --git a/graphics/pokemon/sandygast/front.png b/graphics/pokemon/sandygast/front.png
deleted file mode 100644
index 5e80875bb0..0000000000
Binary files a/graphics/pokemon/sandygast/front.png and /dev/null differ
diff --git a/graphics/pokemon/shiinotic/anim_front.png b/graphics/pokemon/shiinotic/anim_front.png
new file mode 100644
index 0000000000..a9cee08c39
Binary files /dev/null and b/graphics/pokemon/shiinotic/anim_front.png differ
diff --git a/graphics/pokemon/shiinotic/front.png b/graphics/pokemon/shiinotic/front.png
deleted file mode 100644
index 0f63c92c7d..0000000000
Binary files a/graphics/pokemon/shiinotic/front.png and /dev/null differ
diff --git a/graphics/pokemon/steenee/anim_front.png b/graphics/pokemon/steenee/anim_front.png
new file mode 100644
index 0000000000..fdcf044c51
Binary files /dev/null and b/graphics/pokemon/steenee/anim_front.png differ
diff --git a/graphics/pokemon/steenee/front.png b/graphics/pokemon/steenee/front.png
deleted file mode 100644
index 77ae6e0f22..0000000000
Binary files a/graphics/pokemon/steenee/front.png and /dev/null differ
diff --git a/graphics/pokemon/tsareena/anim_front.png b/graphics/pokemon/tsareena/anim_front.png
new file mode 100644
index 0000000000..a3503731e1
Binary files /dev/null and b/graphics/pokemon/tsareena/anim_front.png differ
diff --git a/graphics/pokemon/tsareena/front.png b/graphics/pokemon/tsareena/front.png
deleted file mode 100644
index 9072ce8651..0000000000
Binary files a/graphics/pokemon/tsareena/front.png and /dev/null differ
diff --git a/include/battle_anim.h b/include/battle_anim.h
index b3cfc97d60..ead7730e6e 100644
--- a/include/battle_anim.h
+++ b/include/battle_anim.h
@@ -270,8 +270,8 @@ extern const union AffineAnimCmd *const gAffineAnims_SpinningBone[];
// battle_anim_throw.c
void TryShinyAnimation(enum BattlerId battler, struct Pokemon *mon);
-u8 AnimateBallOpenParticles(u8 x, u8 y, u8 priority, u8 subpriority, u8 ballId);
-u8 LaunchBallFadeMonTask(bool8 unfadeLater, u8 spritePalNum, u32 selectedPalettes, u8 ballId);
+u8 AnimateBallOpenParticles(u8 x, u8 y, u8 priority, u8 subpriority, enum PokeBall ballId);
+u8 LaunchBallFadeMonTask(bool8 unfadeLater, u8 spritePalNum, u32 selectedPalettes, enum PokeBall ballId);
bool32 IsCriticalCapture(void);
// battle_anim_utility_funcs.c
void InitStatsChangeAnimation(u8 taskId);
diff --git a/include/battle_controllers.h b/include/battle_controllers.h
index e5218e8733..fa1b50de76 100644
--- a/include/battle_controllers.h
+++ b/include/battle_controllers.h
@@ -93,46 +93,55 @@ enum BattleController
static inline void MarkBattleControllerActiveOnLocal(enum BattlerId battler)
{
+ assertf(battler < MAX_BATTLERS_COUNT, "illegal battle controller: %d", battler);
gBattleControllerExecFlags |= (1u << battler);
}
static inline void MarkBattleControllerIdleOnLocal(enum BattlerId battler)
{
+ assertf(battler < MAX_BATTLERS_COUNT, "illegal battle controller: %d", battler);
gBattleControllerExecFlags &= ~(1u << battler);
}
static inline bool32 IsBattleControllerActiveOnLocal(enum BattlerId battler)
{
+ assertf(battler < MAX_BATTLERS_COUNT, "illegal battle controller: %d", battler);
return gBattleControllerExecFlags & (1u << battler);
}
static inline void MarkBattleControllerMessageOutboundOverLink(enum BattlerId battler)
{
+ assertf(battler < MAX_BATTLERS_COUNT, "illegal battle controller: %d", battler);
gBattleControllerExecFlags |= ((1u << battler) << (32 - MAX_BATTLERS_COUNT));
}
static inline void MarkBattleControllerMessageSynchronizedOverLink(enum BattlerId battler)
{
+ assertf(battler < MAX_BATTLERS_COUNT, "illegal battle controller: %d", battler);
gBattleControllerExecFlags &= ~((1 << 28) << (battler));
}
static inline bool32 IsBattleControllerMessageSynchronizedOverLink(enum BattlerId battler)
{
+ assertf(battler < MAX_BATTLERS_COUNT, "illegal battle controller: %d", battler);
return gBattleControllerExecFlags & (1u << (battler + 28));
}
static inline void MarkBattleControllerActiveForPlayer(enum BattlerId battler, u32 playerId)
{
+ assertf(battler < MAX_BATTLERS_COUNT, "illegal battle controller: %d", battler);
gBattleControllerExecFlags |= ((1u << battler) << ((playerId) << 2));
}
static inline void MarkBattleControllerIdleForPlayer(enum BattlerId battler, u32 playerId)
{
+ assertf(battler < MAX_BATTLERS_COUNT, "illegal battle controller: %d", battler);
gBattleControllerExecFlags &= ~((1u << battler) << ((playerId) * 4));
}
static inline bool32 IsBattleControllerActiveForPlayer(enum BattlerId battler, u32 playerId)
{
+ assertf(battler < MAX_BATTLERS_COUNT, "illegal battle controller: %d", battler);
return gBattleControllerExecFlags & ((1u << battler) << ((playerId) * 4));
}
@@ -141,6 +150,7 @@ static inline bool32 IsBattleControllerActiveForPlayer(enum BattlerId battler, u
// can only be so specific before it just gets ridiculous.
static inline bool32 IsBattleControllerActiveOrPendingSyncAnywhere(enum BattlerId battler)
{
+ assertf(battler < MAX_BATTLERS_COUNT, "illegal battle controller: %d", battler);
return gBattleControllerExecFlags & (
(1u << battler)
| (0xF << 28)
diff --git a/include/battle_stat_change.h b/include/battle_stat_change.h
index d1f4b93bf7..920cc0321d 100644
--- a/include/battle_stat_change.h
+++ b/include/battle_stat_change.h
@@ -39,6 +39,7 @@ void SetStatChange(enum BattlerId battler, enum Stat stat, s32 stage);
void SetStatChange2(enum BattlerId battler, enum Stat stat, s32 stage);
void ClearStatChangeValues(void);
void ClearOtherStatChangeValues(enum BattlerId battler);
+void ClearBothStatChangeQueues(void);
enum StatChangeResult TrySingleStatChange(struct BattleCalcValues *cv, struct StatChange *st);
u32 GetStatStage(enum Stat stat, const struct AdditionalEffect *additionalEffect);
diff --git a/include/bg.h b/include/bg.h
index 89ffc8d8eb..9715dfb5b4 100644
--- a/include/bg.h
+++ b/include/bg.h
@@ -58,6 +58,7 @@ u8 LoadBgVram(u32 bg, const void *src, u16 size, u16 destOffset, u32 mode);
void SetTextModeAndHideBgs(void);
bool32 IsInvalidBg(u32 bg);
int BgTileAllocOp(int bg, int offset, int count, int mode);
+int BgTileAllocOpUnchecked(int bg, int offset, int count, int mode);
void ResetBgsAndClearDma3BusyFlags(u32 leftoverFireRedLeafGreenVariable);
void InitBgsFromTemplates(u32 bgMode, const struct BgTemplate *templates, u8 numTemplates);
void InitBgFromTemplate(const struct BgTemplate *template);
diff --git a/include/config/general.h b/include/config/general.h
index 729a28ed0b..e156efbbcc 100644
--- a/include/config/general.h
+++ b/include/config/general.h
@@ -75,7 +75,6 @@
// General settings
#define EXPANSION_INTRO TRUE // If TRUE, a custom RHH intro will play after the vanilla copyright screen.
-#define HQ_RANDOM TRUE // If TRUE, replaces the default RNG with an implementation of SFC32 RNG. May break code that relies on RNG.
#define PHONEMES_SHARED FALSE // If TRUE, bard phonemes all reference the same sound (sound/direct_sound_samples/phonemes/shared.bin) to save ROM space.
// Measurement system constants to be used for UNITS
diff --git a/include/constants/expansion.h b/include/constants/expansion.h
index 22f5af54e8..7532cde428 100644
--- a/include/constants/expansion.h
+++ b/include/constants/expansion.h
@@ -1,7 +1,7 @@
#ifndef GUARD_CONSTANTS_EXPANSION_H
#define GUARD_CONSTANTS_EXPANSION_H
-// Last version: 1.16.0
+// Last version: 1.16.1
#define EXPANSION_VERSION_MAJOR 1
#define EXPANSION_VERSION_MINOR 17
#define EXPANSION_VERSION_PATCH 0
diff --git a/include/malloc.h b/include/malloc.h
index 10481dc398..d1bd330270 100644
--- a/include/malloc.h
+++ b/include/malloc.h
@@ -3,10 +3,10 @@
#define FREE_AND_SET_NULL(ptr) \
-{ \
+do { \
Free(ptr); \
ptr = NULL; \
-}
+} while (0)
#define TRY_FREE_AND_SET_NULL(ptr) if (ptr != NULL) FREE_AND_SET_NULL(ptr)
@@ -47,19 +47,27 @@ extern u8 gHeap[HEAP_SIZE];
#if TESTING || !defined(NDEBUG)
#define Alloc(size) Alloc_(size, __FILE__ ":" STR(__LINE__))
+#define AllocUnchecked(size) AllocUnchecked_(size, __FILE__ ":" STR(__LINE__))
+
#define AllocZeroed(size) AllocZeroed_(size, __FILE__ ":" STR(__LINE__))
+#define AllocZeroedUnchecked(size) AllocZeroedUnchecked_(size, __FILE__ ":" STR(__LINE__))
#else
#define Alloc(size) Alloc_(size, NULL)
+#define AllocUnchecked(size) AllocUnchecked_(size, NULL)
#define AllocZeroed(size) AllocZeroed_(size, NULL)
+#define AllocZeroedUnchecked(size) AllocZeroedUnchecked_(size, NULL)
#endif
void *Alloc_(u32 size, const char *location);
+void *AllocUnchecked_(u32 size, const char *location);
void *AllocZeroed_(u32 size, const char *location);
+void *AllocZeroedUnchecked_(u32 size, const char *location);
void Free(void *pointer);
void InitHeap(void *heapStart, u32 heapSize);
+void PrintHeap(void);
const struct MemBlock *HeapHead(void);
const char *MemBlockLocation(const struct MemBlock *block);
diff --git a/include/metaprogram.h b/include/metaprogram.h
index ec0b6ef0bf..d29c42571c 100644
--- a/include/metaprogram.h
+++ b/include/metaprogram.h
@@ -207,4 +207,14 @@ Input must be of the form (upper << lower) where upper can be up to 7, lower up
/* Useful for counting arguments */
#define PLUS_ONE(...) + 1
+/* Expands to 'if (true)' if 'cond' can be evaluated at compile-time and
+ * evaluates to non-zero; expands to 'if (false)' otherwise.
+ *
+ * GCC will not generate code for an 'if (false) { ... }', so this can
+ * be used to write compile-time optimizations without a run-time cost.
+ *
+ * Because 'cond' must be known at compile-time, this is rarely useful
+ * outside macros. */
+#define if_comptime(cond) if (__builtin_constant_p((cond) ? 0 : *(int *)0))
+
#endif
diff --git a/include/pokeball.h b/include/pokeball.h
index 036cff9275..09a3184b25 100644
--- a/include/pokeball.h
+++ b/include/pokeball.h
@@ -30,8 +30,8 @@ void CreatePokeballSpriteToReleaseMon(u8 monSpriteId, u8 monPalNum, u8 x, u8 y,
u8 CreateTradePokeballSprite(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subPriority, u8 delay, u32 fadePalettes);
void StartHealthboxSlideIn(enum BattlerId battler);
void DoHitAnimHealthboxEffect(enum BattlerId battler);
-void LoadBallGfx(u8 ballId);
-void FreeBallGfx(u8 ballId);
+void LoadBallGfx(enum PokeBall ballId);
+void FreeBallGfx(enum PokeBall ballId);
enum PokeBall ItemIdToBallId(u32 ballItem);
#endif // GUARD_POKEBALL_H
diff --git a/include/pokedex.h b/include/pokedex.h
index d19d340095..2b955974f8 100644
--- a/include/pokedex.h
+++ b/include/pokedex.h
@@ -256,11 +256,11 @@ extern const struct SpriteTemplate sNationalDexSeenOwnNumberSpriteTemplate;
extern const struct SpriteTemplate sDexListStartMenuCursorSpriteTemplate;
extern const struct BgTemplate sSearchMenu_BgTemplate[NUM_SEARCH_MENU_BG_TEMPLATES];
-extern const struct WindowTemplate sSearchMenu_WindowTemplate[];
+extern const struct WindowTemplate sSearchMenu_WindowTemplate[2];
extern const u8 sScrollMonIncrements[];
extern const u8 sScrollTimers[];
extern const struct BgTemplate sPokedex_BgTemplate[NUM_POKEDEX_BG_TEMPLATES];
-extern const struct WindowTemplate sPokemonList_WindowTemplate[];
+extern const struct WindowTemplate sPokemonList_WindowTemplate[2];
extern const struct BgTemplate sInfoScreen_BgTemplate[NUM_INFO_SCREEN_BG_TEMPLATES];
extern const struct BgTemplate sNewEntryInfoScreen_BgTemplate[NUM_NEW_ENTRY_INFO_BG_TEMPLATES];
diff --git a/include/random.h b/include/random.h
index d1c0ddd4f1..9783fda016 100644
--- a/include/random.h
+++ b/include/random.h
@@ -275,7 +275,11 @@ enum RandomTag
#define RandomPercentage(tag, t) \
({ \
u32 r; \
- if (t <= 0) \
+ if_comptime (t == 50) \
+ { \
+ r = RandomUniform(tag, FALSE, TRUE); \
+ } \
+ else if (t <= 0) \
{ \
r = FALSE; \
} \
diff --git a/include/test/battle.h b/include/test/battle.h
index e65ba005d1..9879db8618 100644
--- a/include/test/battle.h
+++ b/include/test/battle.h
@@ -461,7 +461,7 @@
* MESSAGE("Wobbuffet used Dream Eater!");
* MESSAGE("It doesn't affect the opposing Wobbuffet…");
*
- * STATUS_ICON(battler, status1 | none: | sleep: | poison: | burn: | freeze: | paralysis:, badPoison:)
+ * STATUS_ICON(battler, status1 | none: | sleep: | poison: | burn: | freeze: | paralysis: | badPoison: | frostbite:)
* Causes the test to fail if the battler's status is not changed to the
* specified status.
* STATUS_ICON(player, badPoison: TRUE);
@@ -767,8 +767,6 @@ struct BattleTrialData
u8 targetTieCount;
};
-extern struct BattleTrialData gBattleTrialData;
-
struct BattleTestData
{
u8 stack[BATTLE_TEST_STACK_SIZE];
diff --git a/include/test/test.h b/include/test/test.h
index 9e95d837fa..df0a97a4f4 100644
--- a/include/test/test.h
+++ b/include/test/test.h
@@ -57,8 +57,8 @@ struct TestRunnerState
const struct Test *test;
u32 processCosts[MAX_PROCESSES];
- u8 result;
- u8 expectedResult;
+ enum TestResult result:8;
+ enum TestResult expectedResult:8;
bool8 expectLeaks:1;
bool8 inBenchmark:1;
bool8 tearDown:1;
diff --git a/include/text.h b/include/text.h
index 7d2ecdb4ce..f0bda0351b 100644
--- a/include/text.h
+++ b/include/text.h
@@ -186,7 +186,7 @@ extern struct TextGlyph gCurGlyph;
void DeactivateAllTextPrinters(void);
void DeactivateSingleTextPrinter(u32 id, enum TextPrinterType type);
u16 AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16));
-u16 AddSpriteTextPrinterParametrerized(u8 spriteId, u8 fontId, const u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16));
+u16 AddSpriteTextPrinterParameterized(u8 spriteId, u8 fontId, const u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16));
void AddSpriteTextPrinterParameterized3(u8 spriteId, u8 fontId, u8 left, u8 top, const u8 *color, s8 speed, const u8 *str);
void AddSpriteTextPrinterParameterized4(u8 spriteId, u8 fontId, u8 left, u8 top, u8 letterSpacing, u8 lineSpacing, const u8 *color, s8 speed, const u8 *str);
void AddSpriteTextPrinterParameterized6(u8 spriteId, u8 fontId, u8 left, u8 top, u8 letterSpacing, u8 lineSpacing, const union TextColor color, s8 speed, const u8 *str);
diff --git a/include/window.h b/include/window.h
index fc35f724d9..5af7979be4 100644
--- a/include/window.h
+++ b/include/window.h
@@ -48,7 +48,10 @@ struct Window
ALIGNED(4) u8 *tileData;
};
-bool32 InitWindows(const struct WindowTemplate *templates);
+bool32 InitWindowsUnchecked(const struct WindowTemplate *templates);
+bool32 InitWindowsChecked(const struct WindowTemplate *templates, s32 staticSize);
+#define InitWindows(templates) InitWindowsChecked(templates, (__builtin_types_compatible_p(typeof(templates), const struct WindowTemplate *)) ? -1 : (s32)sizeof(templates))
+
u32 AddWindow(const struct WindowTemplate *template);
int AddWindowWithoutTileMap(const struct WindowTemplate *template);
void RemoveWindow(u32 windowId);
diff --git a/ld_script_modern.ld b/ld_script_modern.ld
index 6141d84701..005ca633ff 100644
--- a/ld_script_modern.ld
+++ b/ld_script_modern.ld
@@ -70,7 +70,7 @@ SECTIONS {
script_data :
ALIGN(4)
{
- data/*.o(script_data);
+ data/*.o(script_data);
} > ROM =0
.rodata.compound_string :
diff --git a/map_data_rules.mk b/map_data_rules.mk
index 57752c94d3..9935171306 100755
--- a/map_data_rules.mk
+++ b/map_data_rules.mk
@@ -21,9 +21,9 @@ MAP_HEADERS := $(patsubst $(MAPS_DIR)/%/,$(MAPS_DIR)/%/header.inc,$(MAP_DIRS))
MAP_JSONS := $(patsubst $(MAPS_DIR)/%/,$(MAPS_DIR)/%/map.json,$(MAP_DIRS))
$(DATA_ASM_BUILDDIR)/maps.o: $(DATA_ASM_SUBDIR)/maps.s $(LAYOUTS_DIR)/layouts.inc $(LAYOUTS_DIR)/layouts_table.inc $(MAPS_DIR)/headers.inc $(MAPS_DIR)/groups.inc $(MAPS_DIR)/connections.inc $(MAP_CONNECTIONS) $(MAP_HEADERS)
- $(PREPROC) $< charmap.txt | $(CPP) $(CPPFLAGS) -I include - | $(PREPROC) -ie $< charmap.txt | $(AS) $(ASFLAGS) -o $@
+ $(PREPROC) -s $< charmap.txt | $(CPP) $(CPPFLAGS) -I include - | $(PREPROC) -ie $< charmap.txt | $(AS) $(ASFLAGS) -o $@
$(DATA_ASM_BUILDDIR)/map_events.o: $(DATA_ASM_SUBDIR)/map_events.s $(MAPS_DIR)/events.inc $(MAP_EVENTS)
- $(PREPROC) $< charmap.txt | $(CPP) $(CPPFLAGS) -I include - | $(PREPROC) -ie $< charmap.txt | $(AS) $(ASFLAGS) -o $@
+ $(PREPROC) -s $< charmap.txt | $(CPP) $(CPPFLAGS) -I include - | $(PREPROC) -ie $< charmap.txt | $(AS) $(ASFLAGS) -o $@
$(MAPS_OUTDIR)/%/header.inc $(MAPS_OUTDIR)/%/events.inc $(MAPS_OUTDIR)/%/connections.inc: $(MAPS_DIR)/%/map.json $(INCLUDECONSTS_OUTDIR)/map_groups.h
$(MAPJSON) map emerald $< $(LAYOUTS_DIR)/layouts.json $(@D)
diff --git a/src/assertf.c b/src/assertf.c
index f7ecd0fd82..bf2252a377 100644
--- a/src/assertf.c
+++ b/src/assertf.c
@@ -145,9 +145,9 @@ static bool32 Putp(u32 *x, u32 *y, const void *p)
return TRUE;
}
-static bool32 Puts(u32 *x, u32 *y, const char *s)
+static bool32 Puts(u32 *x, u32 *y, s32 n, const char *s)
{
- while (*s != '\0')
+ while (*s != '\0' && n-- > 0)
{
if (!Putc(x, y, *s++))
return FALSE;
@@ -155,9 +155,9 @@ static bool32 Puts(u32 *x, u32 *y, const char *s)
return TRUE;
}
-static bool32 PutS(u32 *x, u32 *y, const u8 *s)
+static bool32 PutS(u32 *x, u32 *y, s32 n, const u8 *s)
{
- while (*s != EOS)
+ while (*s != EOS && n-- > 0)
{
char c;
if (CHAR_a <= *s && *s <= CHAR_z)
@@ -215,6 +215,7 @@ static bool32 Putx(u32 *x, u32 *y, unsigned u)
static void Vprintf(const void *return1, const void *return0, const char *fmt, va_list va)
{
u32 x, y;
+ s32 n;
x = 3;
y = 19;
@@ -226,6 +227,16 @@ static void Vprintf(const void *return1, const void *return0, const char *fmt, v
y = 0;
while (TRUE)
{
+ if (fmt[0] == '.' && fmt[1] == '*')
+ {
+ fmt += 2;
+ n = va_arg(va, int);
+ }
+ else
+ {
+ n = INT_MAX;
+ }
+
char c = *fmt++;
if (c == '\0')
{
@@ -236,6 +247,10 @@ static void Vprintf(const void *return1, const void *return0, const char *fmt, v
char f = *fmt++;
switch (f)
{
+ case '%':
+ if (!Putc(&x, &y, '%'))
+ return;
+ break;
case 'd':
if (!Puti(&x, &y, va_arg(va, int)))
return;
@@ -245,11 +260,11 @@ static void Vprintf(const void *return1, const void *return0, const char *fmt, v
return;
break;
case 's':
- if (!Puts(&x, &y, va_arg(va, const char *)))
+ if (!Puts(&x, &y, n, va_arg(va, const char *)))
return;
break;
case 'S':
- if (!PutS(&x, &y, va_arg(va, const u8 *)))
+ if (!PutS(&x, &y, n, va_arg(va, const u8 *)))
return;
break;
case 'x':
@@ -265,11 +280,11 @@ static void Vprintf(const void *return1, const void *return0, const char *fmt, v
}
}
- if (!Puts(&x, &y, "\n in: "))
+ if (!Puts(&x, &y, INT_MAX, "\n in: "))
return;
if (!Putp(&x, &y, return1))
return;
- if (!Puts(&x, &y, "\n in: "))
+ if (!Puts(&x, &y, INT_MAX, "\n in: "))
return;
if (!Putp(&x, &y, return0))
return;
@@ -305,7 +320,7 @@ void AssertfCrashScreen(const void *return1, const char *fmt, ...)
// Allocate on heap if possible.
if (!backup)
{
- backup = Alloc(sizeof(*backup));
+ backup = AllocUnchecked(sizeof(*backup));
if (backup)
backup->onHeap = TRUE;
}
diff --git a/src/battle_anim.c b/src/battle_anim.c
index 4dcaba3e3c..3bec8939ad 100644
--- a/src/battle_anim.c
+++ b/src/battle_anim.c
@@ -341,16 +341,37 @@ void LaunchBattleAnimation(u32 animType, u32 animId)
if (gTestRunnerEnabled)
{
TestRunner_Battle_RecordAnimation(animType, animId);
- // Play Transform and Ally Switch even in Headless as these move animations also change mon data.
- if (gTestRunnerHeadless
- #if TESTING // Because gBattleTestRunnerState is not seen outside of test env.
- && !gBattleTestRunnerState->forceMoveAnim
- #endif // TESTING
- && !(animType == ANIM_TYPE_MOVE && (animId == MOVE_TRANSFORM || animId == MOVE_ALLY_SWITCH)))
+
+ bool32 forceMoveAnim = FALSE;
+ #if TESTING // Because gBattleTestRunnerState is not seen outside of test env.
+ forceMoveAnim = gBattleTestRunnerState->forceMoveAnim;
+ #endif
+ if (!forceMoveAnim)
{
- gAnimScriptCallback = Nop;
- gAnimScriptActive = FALSE;
- return;
+ enum { DEFAULT, PLAY, SKIP } mode = DEFAULT;
+ if (animType == ANIM_TYPE_MOVE)
+ {
+ switch (animId)
+ {
+ // Play Transform and Ally Switch even in headless
+ // because the animations also change mon data.
+ case MOVE_TRANSFORM:
+ case MOVE_ALLY_SWITCH:
+ mode = PLAY;
+ break;
+ // Skip Celebrate even in non-headless because it's
+ // very noisy.
+ case MOVE_CELEBRATE:
+ mode = SKIP;
+ break;
+ }
+ }
+ if ((mode == DEFAULT && gTestRunnerHeadless) || mode == SKIP)
+ {
+ gAnimScriptCallback = Nop;
+ gAnimScriptActive = FALSE;
+ return;
+ }
}
}
diff --git a/src/battle_anim_throw.c b/src/battle_anim_throw.c
index dd4cc2fbdf..1b065c3eba 100644
--- a/src/battle_anim_throw.c
+++ b/src/battle_anim_throw.c
@@ -71,7 +71,7 @@ static void SpriteCB_Ball_Capture_Step(struct Sprite *);
static void MakeCaptureStars(struct Sprite *);
static void SpriteCB_Ball_FadeOut(struct Sprite *);
static void DestroySpriteAfterOneFrame(struct Sprite *);
-static void LoadBallParticleGfx(u8);
+static void LoadBallParticleGfx(enum PokeBall);
static void SpriteCB_CaptureStar_Flicker(struct Sprite *);
static void SpriteCB_Ball_Release_Wait(struct Sprite *);
static void SpriteCB_Ball_Block_Step(struct Sprite *);
@@ -1600,7 +1600,7 @@ static void SpriteCB_Ball_Block_Step(struct Sprite *sprite)
#undef sFrame
-static void LoadBallParticleGfx(u8 ballId)
+static void LoadBallParticleGfx(enum PokeBall ballId)
{
if (GetSpriteTileStartByTag(sBallParticles[ballId].pic.tag) == 0xFFFF)
{
@@ -1609,7 +1609,7 @@ static void LoadBallParticleGfx(u8 ballId)
}
}
-u8 AnimateBallOpenParticles(u8 x, u8 y, u8 priority, u8 subpriority, u8 ballId)
+u8 AnimateBallOpenParticles(u8 x, u8 y, u8 priority, u8 subpriority, enum PokeBall ballId)
{
u8 taskId;
@@ -1636,7 +1636,7 @@ static void PokeBallOpenParticleAnimation(u8 taskId)
u8 spriteId;
u8 x, y;
u8 priority, subpriority;
- u8 ballId;
+ enum PokeBall ballId;
u8 var0;
ballId = gTasks[taskId].data[15];
@@ -2065,7 +2065,7 @@ static void DestroyBallOpenAnimationParticle(struct Sprite *sprite)
#define tPaletteHi data[11]
#define tBallId data[15]
-u8 LaunchBallFadeMonTask(bool8 unfadeLater, u8 spritePalNum, u32 selectedPalettes, u8 ballId)
+u8 LaunchBallFadeMonTask(bool8 unfadeLater, u8 spritePalNum, u32 selectedPalettes, enum PokeBall ballId)
{
u8 taskId;
@@ -2094,7 +2094,7 @@ u8 LaunchBallFadeMonTask(bool8 unfadeLater, u8 spritePalNum, u32 selectedPalette
static void Task_FadeMon_ToBallColor(u8 taskId)
{
- u8 ballId = gTasks[taskId].tBallId;
+ enum PokeBall ballId = gTasks[taskId].tBallId;
if (gTasks[taskId].tTimer <= 16)
{
@@ -2122,7 +2122,7 @@ static void Task_FadeMon_ToNormal(u8 taskId)
static void Task_FadeMon_ToNormal_Step(u8 taskId)
{
- u8 ballId = gTasks[taskId].tBallId;
+ enum PokeBall ballId = gTasks[taskId].tBallId;
if (gTasks[taskId].tTimer <= 16)
{
diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c
index 5f5c5d7402..645236d349 100644
--- a/src/battle_controller_player.c
+++ b/src/battle_controller_player.c
@@ -195,12 +195,13 @@ static void CompleteOnBattlerSpritePosX_0(enum BattlerId battler)
BtlController_Complete(battler);
}
-static u16 GetPrevBall(u16 ballId)
+static enum Item GetPrevBall(enum Item ballId)
{
s32 i;
- s32 index = ItemIdToBallId(ballId);
- u32 newBall = 0;
- for (i = 0; i < POKEBALL_COUNT; i++)
+ enum PokeBall index = ItemIdToBallId(ballId);
+ enum Item newBall = ITEM_NONE;
+
+ for (i = 0; i < POKEBALL_COUNT; i++)
{
index--;
if (index == -1)
@@ -212,11 +213,12 @@ static u16 GetPrevBall(u16 ballId)
return ballId;
}
-static u32 GetNextBall(u32 ballId)
+static enum Item GetNextBall(enum Item ballId)
{
s32 i;
s32 index = ItemIdToBallId(ballId);
- u32 newBall = 0;
+ enum Item newBall = ITEM_NONE;
+
for (i = 0; i < POKEBALL_COUNT; i++)
{
index++;
@@ -1783,9 +1785,9 @@ static void MoveSelectionDisplayMoveDescription(enum BattlerId battler)
u8 cat_desc[7] = _("CAT: ");
u8 pwr_desc[7] = _("PWR: ");
u8 acc_desc[7] = _("ACC: ");
- u8 cat_start[] = _("{CLEAR_TO 0x03}");
- u8 pwr_start[] = _("{CLEAR_TO 0x38}");
- u8 acc_start[] = _("{CLEAR_TO 0x6C}");
+ u8 cat_start[] = _("{CLEAR_TO 3}");
+ u8 pwr_start[] = _("{CLEAR_TO 56}");
+ u8 acc_start[] = _("{CLEAR_TO 108}");
LoadMessageBoxAndBorderGfx();
DrawStdWindowFrame(B_WIN_MOVE_DESCRIPTION, FALSE);
if (pwr < 2)
diff --git a/src/battle_controllers.c b/src/battle_controllers.c
index 4349200cb4..97dcf98552 100644
--- a/src/battle_controllers.c
+++ b/src/battle_controllers.c
@@ -2166,11 +2166,13 @@ static void Controller_HandleTrainerSlideBack(enum BattlerId battler)
void Controller_WaitForHealthBar(enum BattlerId battler)
{
s16 hpValue = MoveBattleBar(battler, gHealthboxSpriteIds[battler], HEALTH_BAR, 0);
+ struct Pokemon *mon = GetBattlerMon(battler);
+ s32 maxHP = GetMonData(mon, MON_DATA_MAX_HP);
SetHealthboxSpriteVisible(gHealthboxSpriteIds[battler]);
if (hpValue != -1)
{
- UpdateHpTextInHealthbox(gHealthboxSpriteIds[battler], HP_CURRENT, hpValue, gBattleMons[battler].maxHP);
+ UpdateHpTextInHealthbox(gHealthboxSpriteIds[battler], HP_CURRENT, hpValue, maxHP);
}
else
{
@@ -2644,7 +2646,7 @@ void BtlController_HandlePrintString(enum BattlerId battler)
if (gTestRunnerEnabled)
{
TestRunner_Battle_RecordMessage(gDisplayedStringBattle);
- if (gTestRunnerHeadless)
+ if (gTestRunnerHeadless || *stringId == STRINGID_CELEBRATEMESSAGE)
{
BtlController_Complete(battler);
return;
@@ -3297,7 +3299,7 @@ void FreeShinyStars(void)
enum BattleTrainer GetBattlerTrainer(enum BattlerId battler)
{
- if (gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
{
switch (gBattlerBattleController[battler])
{
@@ -3310,7 +3312,9 @@ enum BattleTrainer GetBattlerTrainer(enum BattlerId battler)
case BATTLE_CONTROLLER_LINK_OPPONENT:
case BATTLE_CONTROLLER_RECORDED_OPPONENT:
case BATTLE_CONTROLLER_OPPONENT:
- return (battler & BIT_FLANK) ? B_TRAINER_OPPONENT_B : B_TRAINER_OPPONENT_A;
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ return (battler & BIT_FLANK) ? B_TRAINER_OPPONENT_B : B_TRAINER_OPPONENT_A;
+ return B_TRAINER_OPPONENT_A;
default:
break;
}
diff --git a/src/battle_frontier.c b/src/battle_frontier.c
index b07b7f1e31..e7cea741a4 100644
--- a/src/battle_frontier.c
+++ b/src/battle_frontier.c
@@ -307,7 +307,7 @@ static void FillTrainerParty(u16 trainerId, enum BattleTrainer trainer, u8 monCo
void CreateFacilityMon(const struct TrainerMon *fmon, u16 level, u8 fixedIV, u32 otID, u32 flags, struct Pokemon *dst)
{
- u8 ball = (fmon->ball == 0xFF) ? Random() % POKEBALL_COUNT : fmon->ball;
+ enum PokeBall ball = (fmon->ball == 0xFF) ? Random() % POKEBALL_COUNT : fmon->ball;
enum Move move;
u32 personality = 0, ability, friendship, j;
diff --git a/src/battle_gimmick.c b/src/battle_gimmick.c
index aa209ca510..af96bed651 100644
--- a/src/battle_gimmick.c
+++ b/src/battle_gimmick.c
@@ -109,12 +109,12 @@ void SetGimmickAsActivated(enum BattlerId battler, enum Gimmick gimmick)
#define SINGLES_GIMMICK_TRIGGER_POS_X_OPTIMAL (30)
#define SINGLES_GIMMICK_TRIGGER_POS_X_PRIORITY (31)
#define SINGLES_GIMMICK_TRIGGER_POS_X_SLIDE (15)
-#define SINGLES_GIMMICK_TRIGGER_POS_Y_DIFF (-11)
+#define SINGLES_GIMMICK_TRIGGER_POS_Y_DIFF (-5)
#define DOUBLES_GIMMICK_TRIGGER_POS_X_OPTIMAL (30)
#define DOUBLES_GIMMICK_TRIGGER_POS_X_PRIORITY (31)
#define DOUBLES_GIMMICK_TRIGGER_POS_X_SLIDE (15)
-#define DOUBLES_GIMMICK_TRIGGER_POS_Y_DIFF (-4)
+#define DOUBLES_GIMMICK_TRIGGER_POS_Y_DIFF (-2)
#define tBattler data[0]
#define tHide data[1]
diff --git a/src/battle_interface.c b/src/battle_interface.c
index fd5392bb21..5cccf61194 100644
--- a/src/battle_interface.c
+++ b/src/battle_interface.c
@@ -63,7 +63,7 @@ enum
HEALTHBOX_GFX_20, //exp bar [8 pixels]
HEALTHBOX_GFX_STATUS_PSN_BATTLER0, //status psn "(P"
HEALTHBOX_GFX_22, //status psn "SN"
- HEALTHBOX_GFX_23, //status psn "|)""
+ HEALTHBOX_GFX_23, //status psn "|)"
HEALTHBOX_GFX_STATUS_PRZ_BATTLER0, //status prz
HEALTHBOX_GFX_25,
HEALTHBOX_GFX_26,
diff --git a/src/battle_main.c b/src/battle_main.c
index 0e563e1d9e..b99844aa0a 100644
--- a/src/battle_main.c
+++ b/src/battle_main.c
@@ -1986,7 +1986,7 @@ u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer
if (B_TRAINER_CLASS_POKE_BALLS >= GEN_7 && ball == -1)
{
- ball = gTrainerClasses[trainer->trainerClass].ball ?: ITEM_POKE_BALL;
+ ball = gTrainerClasses[trainer->trainerClass].ball ?: BALL_POKE;
SetMonData(&party[i], MON_DATA_POKEBALL, &ball);
}
}
@@ -5560,8 +5560,7 @@ static void HandleEndTurn_FinishBattle(void)
}
else
{
- if (gBattleControllerExecFlags == 0)
- gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]]();
+ RunBattleScriptCommands();
}
}
@@ -5708,8 +5707,7 @@ void RunBattleScriptCommands_PopCallbacksStack(void)
}
else
{
- if (gBattleControllerExecFlags == 0)
- gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]]();
+ RunBattleScriptCommands();
}
}
diff --git a/src/battle_message.c b/src/battle_message.c
index 76f2d2dfe2..f171bcc21b 100644
--- a/src/battle_message.c
+++ b/src/battle_message.c
@@ -496,7 +496,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] =
[STRINGID_PKMNSITEMNORMALIZEDSTATUS] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_LAST_ITEM} normalized its status!"), // Not in Gen 5+
[STRINGID_TRAINER1USEDITEM] = COMPOUND_STRING("{B_ATK_TRAINER_NAME_WITH_CLASS} used {B_LAST_ITEM}!"),
[STRINGID_BOXISFULL] = COMPOUND_STRING("The Box is full! You can't catch any more!\p"),
- [STRINGID_PKMNSXMADEITINEFFECTIVE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s item cannot be removed!"),
+ [STRINGID_PKMNSXMADEITINEFFECTIVE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} made it ineffective!"),
[STRINGID_PKMNSXPREVENTSFLINCHING] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX}'s {B_EFF_ABILITY} prevents flinching!"), //not in gen 5+, ability popup
[STRINGID_PKMNALREADYHASBURN] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} is already burned!"),
[STRINGID_PKMNSXBLOCKSY] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} blocks {B_CURRENT_MOVE}!"), //not in gen 5+, ability popup
@@ -1354,7 +1354,7 @@ const u16 gItemSwapStringIds[] =
const u16 gFlashFireStringIds[] =
{
[B_MSG_FLASH_FIRE_BOOST] = STRINGID_PKMNRAISEDFIREPOWERWITH,
- [B_MSG_FLASH_FIRE_NO_BOOST] = STRINGID_PKMNSXMADEYINEFFECTIVE
+ [B_MSG_FLASH_FIRE_NO_BOOST] = STRINGID_PKMNSXMADEITINEFFECTIVE
};
const u16 gCaughtMonStringIds[] =
diff --git a/src/battle_move_resolution.c b/src/battle_move_resolution.c
index 15b292ef5b..5c031d392c 100644
--- a/src/battle_move_resolution.c
+++ b/src/battle_move_resolution.c
@@ -231,6 +231,7 @@ static enum CancelerResult CancelerObedience(struct BattleCalcValues *cv)
return CANCELER_RESULT_FAILURE;
case DISOBEYS_RANDOM_MOVE:
gCurrentMove = gCalledMove = gBattleMons[cv->battlerAtk].moves[gCurrMovePos];
+ gBattlescriptCurrInstr = GetMoveBattleScript(gCalledMove);
BattleScriptCall(BattleScript_IgnoresAndUsesRandomMove);
gBattlerTarget = GetBattleMoveTarget(gCalledMove, TARGET_NONE);
return CANCELER_RESULT_RUN_SCRIPT_AND_INCREMENT;
@@ -722,13 +723,11 @@ static bool32 IsTargetingSelfOrAlly(enum BattlerId battlerAtk, enum BattlerId ba
if (battlerDef == battlerAtk)
return skipFailure;
- if (battlerDef != BATTLE_PARTNER(battlerAtk))
- {
- gBattleStruct->moveResultFlags[battlerDef] = MOVE_RESULT_DOESNT_AFFECT_FOE;
- return skipFailure;
- }
+ if (battlerDef == gBattlerTarget)
+ return checkFailure;
- return checkFailure;
+ gBattleStruct->moveResultFlags[battlerDef] = MOVE_RESULT_DOESNT_AFFECT_FOE;
+ return skipFailure;
}
static bool32 IsTargetingFoesAndAlly(enum BattlerId battlerAtk, enum BattlerId battlerDef)
@@ -4495,10 +4494,43 @@ static enum MoveResult StatChangeSubstitute(struct BattleCalcValues *cv)
return MOVE_RESULT_CONTINUE;
}
+static void TryAcupressureStatChange(struct BattleCalcValues *cv)
+{
+ u32 bits = 0;
+
+ if (ShouldSkipStatChangeOnBattler(cv->battlerAtk, cv->battlerDef))
+ return;
+
+ for (enum Stat stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++)
+ {
+ if (CompareStat(cv->battlerDef, stat, MAX_STAT_STAGE, CMP_LESS_THAN, cv->abilities[cv->battlerDef]))
+ bits |= 1u << stat;
+ }
+
+ if (bits)
+ {
+ enum Stat statId;
+ do
+ {
+ statId = (Random() % (NUM_BATTLE_STATS - 1)) + 1;
+ } while (!(bits & (1u << statId)));
+
+ SetStatChange(cv->battlerDef, statId, 2);
+ gBattleStruct->moveResultFlags[cv->battlerDef] = MOVE_RESULT_ATTEMPT_STAT_CHANGE;
+ }
+ else
+ {
+ gBattleStruct->moveResultFlags[cv->battlerDef] = MOVE_RESULT_DOESNT_AFFECT_FOE;
+ }
+}
+
static enum MoveResult StatChangeCanAnyChange(struct BattleCalcValues *cv)
{
if (GetMoveEffect(cv->move) == EFFECT_ACUPRESSURE)
+ {
+ TryAcupressureStatChange(cv);
return MOVE_RESULT_CONTINUE;
+ }
struct StatChange st = {
.onlyChecking = TRUE,
@@ -4586,34 +4618,6 @@ static enum MoveResult StatChangeBeforeChange(struct BattleCalcValues *cv)
return MOVE_RESULT_RUN_SCRIPT_INCREMENT;
}
break;
- case EFFECT_ACUPRESSURE:
- {
- u32 bits = 0;
- for (enum Stat stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++)
- {
- if (CompareStat(cv->battlerDef, stat, MAX_STAT_STAGE, CMP_LESS_THAN, cv->abilities[cv->battlerDef]))
- bits |= 1u << stat;
- }
- if (bits)
- {
- enum Stat statId;
- do
- {
- statId = (Random() % (NUM_BATTLE_STATS - 1)) + 1;
- } while (!(bits & (1u << statId)));
-
- gBattleStruct->moveResultFlags[cv->battlerDef] = MOVE_RESULT_ATTEMPT_STAT_CHANGE;
- SetStatChange(cv->battlerDef, statId, 2);
- BattleScriptCall(BattleScript_PlayMoveAnim);
- return MOVE_RESULT_RUN_SCRIPT_INCREMENT;
- }
- else
- {
- gBattlescriptCurrInstr = BattleScript_StatChangeFailed;
- return MOVE_RESULT_FAILURE;
- }
- break;
- }
case EFFECT_STUFF_CHEEKS:
// Back up current queue for later use
memcpy(
diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c
index 299d998bb3..150169f7f5 100644
--- a/src/battle_script_commands.c
+++ b/src/battle_script_commands.c
@@ -8659,6 +8659,7 @@ static void Cmd_recoverbasedonsunlight(void)
s32 recoverAmount = 0;
u32 weather = GetWeather();
u32 attackerWeather = GetAttackerWeather(GetBattlerHoldEffect(gBattlerAttacker), GetBattlerAbility(gBattlerAttacker), weather);
+ u32 healingWeather = attackerWeather & ~B_WEATHER_STRONG_WINDS;
if (GetMoveEffect(gCurrentMove) == EFFECT_SHORE_UP)
{
if (attackerWeather & B_WEATHER_SANDSTORM)
@@ -8670,7 +8671,7 @@ static void Cmd_recoverbasedonsunlight(void)
{
if (attackerWeather & B_WEATHER_SUN)
recoverAmount = 20 * GetNonDynamaxMaxHP(gBattlerAttacker) / 30;
- else if (!(GetWeather() & B_WEATHER_ANY) || GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_UTILITY_UMBRELLA)
+ else if (!(healingWeather & B_WEATHER_ANY) || GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_UTILITY_UMBRELLA)
recoverAmount = GetNonDynamaxMaxHP(gBattlerAttacker) / 2;
else // not sunny weather
recoverAmount = GetNonDynamaxMaxHP(gBattlerAttacker) / 4;
@@ -8701,7 +8702,7 @@ static void Cmd_recoverbasedonsunlight(void)
}
if (attackerWeather & B_WEATHER_SUN)
recoverAmount = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 2;
- else if (!(attackerWeather & B_WEATHER_ANY) || GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_UTILITY_UMBRELLA)
+ else if (!(healingWeather & B_WEATHER_ANY) || GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_UTILITY_UMBRELLA)
recoverAmount = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 4;
else // not sunny weather
recoverAmount = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 8;
@@ -9691,7 +9692,7 @@ u8 GetCatchingBattler(void)
static void FinalizeCapture(void)
{
- u32 ballId = ItemIdToBallId(gLastThrownBall);
+ enum PokeBall ballId = ItemIdToBallId(gLastThrownBall);
enum NationalDexOrder natDexNo = SpeciesToNationalPokedexNum(gBattleMons[gBattlerTarget].species);
if ((GetConfig(B_CRITICAL_CAPTURE_IF_OWNED) >= GEN_9 && GetSetPokedexFlag(natDexNo, FLAG_GET_CAUGHT))
|| IsCriticalCapture())
@@ -9739,7 +9740,7 @@ struct BallData
static void ComputeBallData(u32 wildMonBattler, u32 playerBattler, struct BallData *ball)
{
u32 i;
- u32 ballId = ItemIdToBallId(gLastUsedItem);
+ enum PokeBall ballId = ItemIdToBallId(gLastUsedItem);
struct BattlePokemon *battleMon = &gBattleMons[wildMonBattler];
ball->multiplier = 100;
@@ -9921,6 +9922,8 @@ static void ComputeBallData(u32 wildMonBattler, u32 playerBattler, struct BallDa
ball->multiplier = 410;
ball->divider = 4096;
break;
+ default:
+ break;
}
}
diff --git a/src/battle_stat_change.c b/src/battle_stat_change.c
index d7da7d93f4..26e98045e4 100644
--- a/src/battle_stat_change.c
+++ b/src/battle_stat_change.c
@@ -925,6 +925,20 @@ void ClearOtherStatChangeValues(enum BattlerId battler)
gBattleStruct->positiveAnimPlayed = 0;
}
+void ClearBothStatChangeQueues(void)
+{
+ for (enum BattlerId battler = 0; battler < gBattlersCount; battler++)
+ {
+ memset(gSpecialStatuses[battler].statStageQueue2, 0, sizeof(gSpecialStatuses[battler].statStageQueue2));
+ gSpecialStatuses[battler].statStageAmount2 = 0;
+ memset(gSpecialStatuses[battler].statStageQueue, 0, sizeof(gSpecialStatuses[battler].statStageQueue));
+ gSpecialStatuses[battler].statStageAmount = 0;
+ }
+ gBattleStruct->negativeAnimPlayed = 0;
+ gBattleStruct->positiveAnimPlayed = 0;
+ gBattleStruct->statChangeBattler = 0;
+}
+
bool32 CompareStat(enum BattlerId battler, enum Stat statId, u32 cmpTo, u32 cmpKind, enum Ability ability)
{
bool32 ret = FALSE;
diff --git a/src/battle_util.c b/src/battle_util.c
index dc3105fc60..58955eb8f4 100644
--- a/src/battle_util.c
+++ b/src/battle_util.c
@@ -66,7 +66,7 @@ static void ResetParadoxTerrainStat(enum BattlerId battler);
static bool32 CanBattlerFormChange(enum BattlerId battler, enum FormChanges method);
static bool32 IsPowderMoveBlocked(struct DamageContext *ctx);
const u8 *AbsorbedByDrainHpAbility(enum BattlerId battlerDef);
-const u8 *AbsorbedByStatIncreaseAbility(enum BattlerId battlerDef, enum Ability abilityDef, enum Stat statId, u32 statAmount);
+const u8 *AbsorbedByStatIncreaseAbility(struct DamageContext *ctx, enum Stat statId, u32 statAmount);
const u8 *AbsorbedByFlashFire(enum BattlerId battlerDef);
static bool32 IsCriticalHit(struct DamageContext *ctx);
@@ -448,6 +448,7 @@ void HandleAction_UseMove(void)
gBattleStruct->eventState.atkCanceler = 0;
ClearDamageCalcResults();
+ ClearBothStatChangeQueues();
gMultiHitCounter = 0;
gBattleCommunication[MISS_TYPE] = 0;
gBattlerTarget = gBattleStruct->moveTarget[gBattlerAttacker];
@@ -1240,13 +1241,19 @@ void UpdateSentPokesToOpponentValue(enum BattlerId battler)
void BattleScriptPush(const u8 *bsPtr)
{
- assertf(gBattleResources->battleScriptsStack->size < UINT8_MAX, "attempted to push a battle script, but battleScriptsStack is full!");
+ assertf(gBattleResources->battleScriptsStack->size < ARRAY_COUNT(gBattleResources->battleScriptsStack->ptr), "attempted to push a battle script, but battleScriptsStack is full!")
+ {
+ return;
+ }
gBattleResources->battleScriptsStack->ptr[gBattleResources->battleScriptsStack->size++] = bsPtr;
}
void BattleScriptPushCursor(void)
{
- assertf(gBattleResources->battleScriptsStack->size < UINT8_MAX, "attempted to push cursor, but battleScriptsStack is full!");
+ assertf(gBattleResources->battleScriptsStack->size < ARRAY_COUNT(gBattleResources->battleScriptsStack->ptr), "attempted to push cursor, but battleScriptsStack is full!")
+ {
+ return;
+ }
gBattleResources->battleScriptsStack->ptr[gBattleResources->battleScriptsStack->size++] = gBattlescriptCurrInstr;
}
@@ -2255,27 +2262,27 @@ bool32 CanAbilityAbsorbMove(struct DamageContext *ctx)
break;
case ABILITY_MOTOR_DRIVE:
if (ctx->moveType == TYPE_ELECTRIC)
- battleScript = AbsorbedByStatIncreaseAbility(ctx->battlerDef, ctx->abilities[ctx->battlerDef], STAT_SPEED, 1);
+ battleScript = AbsorbedByStatIncreaseAbility(ctx, STAT_SPEED, 1);
break;
case ABILITY_LIGHTNING_ROD:
if (GetConfig(B_REDIRECT_ABILITY_IMMUNITY) >= GEN_5 && ctx->moveType == TYPE_ELECTRIC)
- battleScript = AbsorbedByStatIncreaseAbility(ctx->battlerDef, ctx->abilities[ctx->battlerDef], STAT_SPATK, 1);
+ battleScript = AbsorbedByStatIncreaseAbility(ctx, STAT_SPATK, 1);
break;
case ABILITY_STORM_DRAIN:
if (GetConfig(B_REDIRECT_ABILITY_IMMUNITY) >= GEN_5 && ctx->moveType == TYPE_WATER)
- battleScript = AbsorbedByStatIncreaseAbility(ctx->battlerDef, ctx->abilities[ctx->battlerDef], STAT_SPATK, 1);
+ battleScript = AbsorbedByStatIncreaseAbility(ctx, STAT_SPATK, 1);
break;
case ABILITY_SAP_SIPPER:
if (ctx->moveType == TYPE_GRASS)
- battleScript = AbsorbedByStatIncreaseAbility(ctx->battlerDef, ctx->abilities[ctx->battlerDef], STAT_ATK, 1);
+ battleScript = AbsorbedByStatIncreaseAbility(ctx, STAT_ATK, 1);
break;
case ABILITY_WELL_BAKED_BODY:
if (ctx->moveType == TYPE_FIRE)
- battleScript = AbsorbedByStatIncreaseAbility(ctx->battlerDef, ctx->abilities[ctx->battlerDef], STAT_DEF, 2);
+ battleScript = AbsorbedByStatIncreaseAbility(ctx, STAT_DEF, 2);
break;
case ABILITY_WIND_RIDER:
if (IsWindMove(ctx->move))
- battleScript = AbsorbedByStatIncreaseAbility(ctx->battlerDef, ctx->abilities[ctx->battlerDef], STAT_ATK, 1);
+ battleScript = AbsorbedByStatIncreaseAbility(ctx, STAT_ATK, 1);
break;
case ABILITY_FLASH_FIRE:
if (ctx->moveType == TYPE_FIRE && (B_FLASH_FIRE_FROZEN >= GEN_5 || !(gBattleMons[ctx->battlerDef].status1 & STATUS1_FREEZE)))
@@ -2327,15 +2334,16 @@ const u8 *AbsorbedByDrainHpAbility(enum BattlerId battlerDef)
}
}
-const u8 *AbsorbedByStatIncreaseAbility(enum BattlerId battlerDef, enum Ability abilityDef, enum Stat statId, u32 statAmount)
+const u8 *AbsorbedByStatIncreaseAbility(struct DamageContext *ctx, enum Stat statId, u32 statAmount)
{
- if (!CompareStat(battlerDef, statId, MAX_STAT_STAGE, CMP_LESS_THAN, abilityDef))
+ if (!CompareStat(ctx->battlerDef, statId, MAX_STAT_STAGE, CMP_LESS_THAN, ctx->abilities[ctx->battlerDef]))
{
return BattleScript_AbilityProtectedTarget;
}
else
{
- SetStatChange(battlerDef, statId, statAmount);
+ if (ctx->runScript)
+ SetStatChange(ctx->battlerDef, statId, statAmount);
return BattleScript_MoveStatDrain;
}
}
@@ -5487,10 +5495,9 @@ void ClearVariousBattlerFlags(enum BattlerId battler)
gBattleMons[battler].volatiles.grudge = FALSE;
}
-void HandleAction_RunBattleScript(void) // identical to RunBattleScriptCommands
+void HandleAction_RunBattleScript(void)
{
- if (gBattleControllerExecFlags == 0)
- gBattleScriptingCommandsTable[*gBattlescriptCurrInstr]();
+ RunBattleScriptCommands();
}
u32 SetRandomTarget(enum BattlerId battlerAtk)
@@ -6175,7 +6182,7 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx)
basePower *= 2;
break;
case EFFECT_WEATHER_BALL:
- if (GetAttackerWeather(ctx->holdEffects[ctx->battlerAtk], ctx->abilities[ctx->battlerAtk], ctx->weather) & B_WEATHER_ANY)
+ if (GetAttackerWeather(ctx->holdEffects[ctx->battlerAtk], ctx->abilities[ctx->battlerAtk], ctx->weather) & (B_WEATHER_ANY & ~B_WEATHER_STRONG_WINDS))
basePower *= 2;
break;
case EFFECT_PURSUIT:
diff --git a/src/bg.c b/src/bg.c
index 0ffa35f35f..45397984e8 100644
--- a/src/bg.c
+++ b/src/bg.c
@@ -289,8 +289,15 @@ bool32 IsInvalidBg(u32 bg)
return FALSE;
}
-// From FRLG. Dummied out.
int BgTileAllocOp(int bg, int offset, int count, int mode)
+{
+ int result = BgTileAllocOpUnchecked(bg, offset, count, mode);
+ assertf(result > 0);
+ return result;
+}
+
+// From FRLG. Dummied out.
+int BgTileAllocOpUnchecked(int bg, int offset, int count, int mode)
{
#if IS_FRLG
int start, end;
diff --git a/src/config_changes.c b/src/config_changes.c
index 06e5b6ab6a..6b4bcb65be 100644
--- a/src/config_changes.c
+++ b/src/config_changes.c
@@ -118,12 +118,13 @@ void SetConfig(enum ConfigTag _config, u32 _value)
#if TESTING
void TestInitConfigData(void)
{
+ Free(gConfigChangesTestOverride);
gConfigChangesTestOverride = Alloc(sizeof(sConfigChanges));
memcpy(gConfigChangesTestOverride, &sConfigChanges, sizeof(sConfigChanges));
}
void TestFreeConfigData(void)
{
- TRY_FREE_AND_SET_NULL(gConfigChangesTestOverride)
+ FREE_AND_SET_NULL(gConfigChangesTestOverride);
}
#endif
diff --git a/src/credits_frlg.c b/src/credits_frlg.c
index 3f6145bc0c..e15e9b7a32 100644
--- a/src/credits_frlg.c
+++ b/src/credits_frlg.c
@@ -421,9 +421,9 @@ ALIGNED(4) const u8 gCreditsString_Teruki_Murakawa_Souichi_Yamamoto_Kimiko_Nakam
ALIGNED(4) const u8 gCreditsString_NOA_Product_Testing[] = _("NOA Product Testing\n\n\n\n\n\n");
ALIGNED(4) const u8 gCreditsString_Thomas_Hertzog_Kathy_Huguenard_Mika_Kurosawa[] = _("\nThomas Hertzog\nKathy Huguenard\nMika Kurosawa\n\n\n");
ALIGNED(4) const u8 gCreditsString_Braille_Code_Check_2[] = _("Braille Code Check\n\n\n\n\n\n");
-ALIGNED(4) const u8 gCreditsString_National_Federation_of_the_Blind_Patricia_A_Maurer_Japan_Braille_Library_European_Blind_Union[] = _("\nNational Federation\n{CLEAR_TO 0x13}of the Blind\nPatricia A. Maurer\nJapan Braille Library\nEuropean Blind Union\n");
+ALIGNED(4) const u8 gCreditsString_National_Federation_of_the_Blind_Patricia_A_Maurer_Japan_Braille_Library_European_Blind_Union[] = _("\nNational Federation\n{CLEAR_TO 19}of the Blind\nPatricia A. Maurer\nJapan Braille Library\nEuropean Blind Union\n");
ALIGNED(4) const u8 gCreditsString_Braille_Code_Check_3[] = _("\nBraille Code Check\n\n\n\n\n");
-ALIGNED(4) const u8 gCreditsString_National_Information_Library_Service_Margaret_Campion[] = _("\n\nNational Information Library\n{CLEAR_TO 0x2D}Service\nMargaret Campion\n\n");
+ALIGNED(4) const u8 gCreditsString_National_Information_Library_Service_Margaret_Campion[] = _("\n\nNational Information Library\n{CLEAR_TO 45}Service\nMargaret Campion\n\n");
ALIGNED(4) const u8 gCreditsString_Special_Thanks_4[] = _("Special Thanks\n\n\n\n\n\n");
ALIGNED(4) const u8 gCreditsString_Takehiro_Izushi_Motoyasu_Tojima_Hitoshi_Yamagami_Hiroyuki_Uesugi[] = _("\nTakehiro Izushi\nMotoyasu Tojima\nHitoshi Yamagami\nHiroyuki Uesugi\n\n");
ALIGNED(4) const u8 gCreditsString_Special_Thanks_5[] = _("Special Thanks\n\n\n\n\n\n");
diff --git a/src/data/graphics/gimmicks.h b/src/data/graphics/gimmicks.h
index c7ba9a620d..509d95ec14 100644
--- a/src/data/graphics/gimmicks.h
+++ b/src/data/graphics/gimmicks.h
@@ -5,7 +5,7 @@ static const u8 ALIGNED(4) sBurstTriggerGfx[] = INCGFX_U8("graphics/battle_inter
static const u8 ALIGNED(4) sDynamaxTriggerGfx[] = INCGFX_U8("graphics/battle_interface/dynamax_trigger.png", ".4bpp");
static const u8 ALIGNED(4) sTeraTriggerGfx[] = INCGFX_U8("graphics/battle_interface/tera_trigger.png", ".4bpp");
-static const u16 sMegaTriggerPal[] = INCGFX_U16("graphics/battle_interface/mega_trigger.pal", ".gbapal");
+static const u16 sMegaTriggerPal[] = INCGFX_U16("graphics/battle_interface/mega_trigger.png", ".gbapal");
static const u16 sZMoveTriggerPal[] = INCGFX_U16("graphics/battle_interface/z_move_trigger.png", ".gbapal");
static const u16 sBurstTriggerPal[] = INCGFX_U16("graphics/battle_interface/burst_trigger.png", ".gbapal");
static const u16 sDynamaxTriggerPal[] = INCGFX_U16("graphics/battle_interface/dynamax_trigger.png", ".gbapal");
diff --git a/src/data/graphics/pokemon.h b/src/data/graphics/pokemon.h
index 503ca34556..5d354b3ee9 100644
--- a/src/data/graphics/pokemon.h
+++ b/src/data/graphics/pokemon.h
@@ -15314,9 +15314,9 @@ const u32 gObjectEventPic_Substitute[] = INCGFX_COMP("graphics/pokemon/question_
#endif //P_MEGA_EVOLUTIONS
#if P_GEN_9_MEGA_EVOLUTIONS
- const u32 gMonFrontPic_GarchompMegaZ[] = INCBIN_U32("graphics/pokemon/garchomp/mega_z/front.4bpp.smol");
+ const u32 gMonFrontPic_GarchompMegaZ[] = INCGFX_U32("graphics/pokemon/garchomp/mega_z/front.png", ".4bpp.smol");
const u16 gMonPalette_GarchompMegaZ[] = INCGFX_U16("graphics/pokemon/garchomp/mega_z/normal.pal", ".gbapal");
- const u32 gMonBackPic_GarchompMegaZ[] = INCBIN_U32("graphics/pokemon/garchomp/mega_z/back.4bpp.smol");
+ const u32 gMonBackPic_GarchompMegaZ[] = INCGFX_U32("graphics/pokemon/garchomp/mega_z/back.png", ".4bpp.smol");
const u16 gMonShinyPalette_GarchompMegaZ[] = INCGFX_U16("graphics/pokemon/garchomp/mega_z/shiny.pal", ".gbapal");
const u8 gMonIcon_GarchompMegaZ[] = INCGFX_U8("graphics/pokemon/garchomp/mega_z/icon.png", ".4bpp");
#if OW_POKEMON_OBJECT_EVENTS && OW_BATTLE_ONLY_FORMS
@@ -22017,7 +22017,7 @@ const u32 gObjectEventPic_Substitute[] = INCGFX_COMP("graphics/pokemon/question_
#endif //P_FAMILY_DEWPIDER
#if P_FAMILY_FOMANTIS
- const u32 gMonFrontPic_Fomantis[] = INCGFX_U32("graphics/pokemon/fomantis/front.png", ".4bpp.smol");
+ const u32 gMonFrontPic_Fomantis[] = INCGFX_U32("graphics/pokemon/fomantis/anim_front.png", ".4bpp.smol");
const u16 gMonPalette_Fomantis[] = INCGFX_U16("graphics/pokemon/fomantis/normal.pal", ".gbapal");
const u32 gMonBackPic_Fomantis[] = INCGFX_U32("graphics/pokemon/fomantis/back.png", ".4bpp.smol");
const u16 gMonShinyPalette_Fomantis[] = INCGFX_U16("graphics/pokemon/fomantis/shiny.pal", ".gbapal");
@@ -22051,7 +22051,7 @@ const u32 gObjectEventPic_Substitute[] = INCGFX_COMP("graphics/pokemon/question_
#endif //P_FAMILY_FOMANTIS
#if P_FAMILY_MORELULL
- const u32 gMonFrontPic_Morelull[] = INCGFX_U32("graphics/pokemon/morelull/front.png", ".4bpp.smol");
+ const u32 gMonFrontPic_Morelull[] = INCGFX_U32("graphics/pokemon/morelull/anim_front.png", ".4bpp.smol");
const u16 gMonPalette_Morelull[] = INCGFX_U16("graphics/pokemon/morelull/normal.pal", ".gbapal");
const u32 gMonBackPic_Morelull[] = INCGFX_U32("graphics/pokemon/morelull/back.png", ".4bpp.smol");
const u16 gMonShinyPalette_Morelull[] = INCGFX_U16("graphics/pokemon/morelull/shiny.pal", ".gbapal");
@@ -22067,7 +22067,7 @@ const u32 gObjectEventPic_Substitute[] = INCGFX_COMP("graphics/pokemon/question_
#endif //OW_PKMN_OBJECTS_SHARE_PALETTES
#endif //OW_POKEMON_OBJECT_EVENTS
- const u32 gMonFrontPic_Shiinotic[] = INCGFX_U32("graphics/pokemon/shiinotic/front.png", ".4bpp.smol");
+ const u32 gMonFrontPic_Shiinotic[] = INCGFX_U32("graphics/pokemon/shiinotic/anim_front.png", ".4bpp.smol");
const u16 gMonPalette_Shiinotic[] = INCGFX_U16("graphics/pokemon/shiinotic/normal.pal", ".gbapal");
const u32 gMonBackPic_Shiinotic[] = INCGFX_U32("graphics/pokemon/shiinotic/back.png", ".4bpp.smol");
const u16 gMonShinyPalette_Shiinotic[] = INCGFX_U16("graphics/pokemon/shiinotic/shiny.pal", ".gbapal");
@@ -22153,7 +22153,7 @@ const u32 gObjectEventPic_Substitute[] = INCGFX_COMP("graphics/pokemon/question_
#endif //P_FAMILY_STUFFUL
#if P_FAMILY_BOUNSWEET
- const u32 gMonFrontPic_Bounsweet[] = INCGFX_U32("graphics/pokemon/bounsweet/front.png", ".4bpp.smol");
+ const u32 gMonFrontPic_Bounsweet[] = INCGFX_U32("graphics/pokemon/bounsweet/anim_front.png", ".4bpp.smol");
const u16 gMonPalette_Bounsweet[] = INCGFX_U16("graphics/pokemon/bounsweet/normal.pal", ".gbapal");
const u32 gMonBackPic_Bounsweet[] = INCGFX_U32("graphics/pokemon/bounsweet/back.png", ".4bpp.smol");
const u16 gMonShinyPalette_Bounsweet[] = INCGFX_U16("graphics/pokemon/bounsweet/shiny.pal", ".gbapal");
@@ -22169,7 +22169,7 @@ const u32 gObjectEventPic_Substitute[] = INCGFX_COMP("graphics/pokemon/question_
#endif //OW_PKMN_OBJECTS_SHARE_PALETTES
#endif //OW_POKEMON_OBJECT_EVENTS
- const u32 gMonFrontPic_Steenee[] = INCGFX_U32("graphics/pokemon/steenee/front.png", ".4bpp.smol");
+ const u32 gMonFrontPic_Steenee[] = INCGFX_U32("graphics/pokemon/steenee/anim_front.png", ".4bpp.smol");
const u16 gMonPalette_Steenee[] = INCGFX_U16("graphics/pokemon/steenee/normal.pal", ".gbapal");
const u32 gMonBackPic_Steenee[] = INCGFX_U32("graphics/pokemon/steenee/back.png", ".4bpp.smol");
const u16 gMonShinyPalette_Steenee[] = INCGFX_U16("graphics/pokemon/steenee/shiny.pal", ".gbapal");
@@ -22185,7 +22185,7 @@ const u32 gObjectEventPic_Substitute[] = INCGFX_COMP("graphics/pokemon/question_
#endif //OW_PKMN_OBJECTS_SHARE_PALETTES
#endif //OW_POKEMON_OBJECT_EVENTS
- const u32 gMonFrontPic_Tsareena[] = INCGFX_U32("graphics/pokemon/tsareena/front.png", ".4bpp.smol");
+ const u32 gMonFrontPic_Tsareena[] = INCGFX_U32("graphics/pokemon/tsareena/anim_front.png", ".4bpp.smol");
const u16 gMonPalette_Tsareena[] = INCGFX_U16("graphics/pokemon/tsareena/normal.pal", ".gbapal");
const u32 gMonBackPic_Tsareena[] = INCGFX_U32("graphics/pokemon/tsareena/back.png", ".4bpp.smol");
const u16 gMonShinyPalette_Tsareena[] = INCGFX_U16("graphics/pokemon/tsareena/shiny.pal", ".gbapal");
@@ -22203,7 +22203,7 @@ const u32 gObjectEventPic_Substitute[] = INCGFX_COMP("graphics/pokemon/question_
#endif //P_FAMILY_BOUNSWEET
#if P_FAMILY_COMFEY
- const u32 gMonFrontPic_Comfey[] = INCGFX_U32("graphics/pokemon/comfey/front.png", ".4bpp.smol");
+ const u32 gMonFrontPic_Comfey[] = INCGFX_U32("graphics/pokemon/comfey/anim_front.png", ".4bpp.smol");
const u16 gMonPalette_Comfey[] = INCGFX_U16("graphics/pokemon/comfey/normal.pal", ".gbapal");
const u32 gMonBackPic_Comfey[] = INCGFX_U32("graphics/pokemon/comfey/back.png", ".4bpp.smol");
const u16 gMonShinyPalette_Comfey[] = INCGFX_U16("graphics/pokemon/comfey/shiny.pal", ".gbapal");
@@ -22306,7 +22306,7 @@ const u32 gObjectEventPic_Substitute[] = INCGFX_COMP("graphics/pokemon/question_
#endif //P_FAMILY_WIMPOD
#if P_FAMILY_SANDYGAST
- const u32 gMonFrontPic_Sandygast[] = INCGFX_U32("graphics/pokemon/sandygast/front.png", ".4bpp.smol");
+ const u32 gMonFrontPic_Sandygast[] = INCGFX_U32("graphics/pokemon/sandygast/anim_front.png", ".4bpp.smol");
const u16 gMonPalette_Sandygast[] = INCGFX_U16("graphics/pokemon/sandygast/normal.pal", ".gbapal");
const u32 gMonBackPic_Sandygast[] = INCGFX_U32("graphics/pokemon/sandygast/back.png", ".4bpp.smol");
const u16 gMonShinyPalette_Sandygast[] = INCGFX_U16("graphics/pokemon/sandygast/shiny.pal", ".gbapal");
@@ -22322,7 +22322,7 @@ const u32 gObjectEventPic_Substitute[] = INCGFX_COMP("graphics/pokemon/question_
#endif //OW_PKMN_OBJECTS_SHARE_PALETTES
#endif //OW_POKEMON_OBJECT_EVENTS
- const u32 gMonFrontPic_Palossand[] = INCGFX_U32("graphics/pokemon/palossand/front.png", ".4bpp.smol");
+ const u32 gMonFrontPic_Palossand[] = INCGFX_U32("graphics/pokemon/palossand/anim_front.png", ".4bpp.smol");
const u16 gMonPalette_Palossand[] = INCGFX_U16("graphics/pokemon/palossand/normal.pal", ".gbapal");
const u32 gMonBackPic_Palossand[] = INCGFX_U32("graphics/pokemon/palossand/back.png", ".4bpp.smol");
const u16 gMonShinyPalette_Palossand[] = INCGFX_U16("graphics/pokemon/palossand/shiny.pal", ".gbapal");
@@ -22488,7 +22488,7 @@ const u32 gObjectEventPic_Substitute[] = INCGFX_COMP("graphics/pokemon/question_
#endif //P_FAMILY_MINIOR
#if P_FAMILY_KOMALA
- const u32 gMonFrontPic_Komala[] = INCGFX_U32("graphics/pokemon/komala/front.png", ".4bpp.smol");
+ const u32 gMonFrontPic_Komala[] = INCGFX_U32("graphics/pokemon/komala/anim_front.png", ".4bpp.smol");
const u16 gMonPalette_Komala[] = INCGFX_U16("graphics/pokemon/komala/normal.pal", ".gbapal");
const u32 gMonBackPic_Komala[] = INCGFX_U32("graphics/pokemon/komala/back.png", ".4bpp.smol");
const u16 gMonShinyPalette_Komala[] = INCGFX_U16("graphics/pokemon/komala/shiny.pal", ".gbapal");
@@ -22573,7 +22573,7 @@ const u32 gObjectEventPic_Substitute[] = INCGFX_COMP("graphics/pokemon/question_
#endif //P_FAMILY_MIMIKYU
#if P_FAMILY_BRUXISH
- const u32 gMonFrontPic_Bruxish[] = INCGFX_U32("graphics/pokemon/bruxish/front.png", ".4bpp.smol");
+ const u32 gMonFrontPic_Bruxish[] = INCGFX_U32("graphics/pokemon/bruxish/anim_front.png", ".4bpp.smol");
const u16 gMonPalette_Bruxish[] = INCGFX_U16("graphics/pokemon/bruxish/normal.pal", ".gbapal");
const u32 gMonBackPic_Bruxish[] = INCGFX_U32("graphics/pokemon/bruxish/back.png", ".4bpp.smol");
const u16 gMonShinyPalette_Bruxish[] = INCGFX_U16("graphics/pokemon/bruxish/shiny.pal", ".gbapal");
@@ -22624,7 +22624,7 @@ const u32 gObjectEventPic_Substitute[] = INCGFX_COMP("graphics/pokemon/question_
#endif //P_FAMILY_DRAMPA
#if P_FAMILY_DHELMISE
- const u32 gMonFrontPic_Dhelmise[] = INCGFX_U32("graphics/pokemon/dhelmise/front.png", ".4bpp.smol");
+ const u32 gMonFrontPic_Dhelmise[] = INCGFX_U32("graphics/pokemon/dhelmise/anim_front.png", ".4bpp.smol");
const u16 gMonPalette_Dhelmise[] = INCGFX_U16("graphics/pokemon/dhelmise/normal.pal", ".gbapal");
const u32 gMonBackPic_Dhelmise[] = INCGFX_U32("graphics/pokemon/dhelmise/back.png", ".4bpp.smol");
const u16 gMonShinyPalette_Dhelmise[] = INCGFX_U16("graphics/pokemon/dhelmise/shiny.pal", ".gbapal");
@@ -22764,7 +22764,7 @@ const u32 gObjectEventPic_Substitute[] = INCGFX_COMP("graphics/pokemon/question_
#endif //P_FAMILY_TAPU_FINI
#if P_FAMILY_COSMOG
- const u32 gMonFrontPic_Cosmog[] = INCGFX_U32("graphics/pokemon/cosmog/front.png", ".4bpp.smol");
+ const u32 gMonFrontPic_Cosmog[] = INCGFX_U32("graphics/pokemon/cosmog/anim_front.png", ".4bpp.smol");
const u16 gMonPalette_Cosmog[] = INCGFX_U16("graphics/pokemon/cosmog/normal.pal", ".gbapal");
const u32 gMonBackPic_Cosmog[] = INCGFX_U32("graphics/pokemon/cosmog/back.png", ".4bpp.smol");
const u16 gMonShinyPalette_Cosmog[] = INCGFX_U16("graphics/pokemon/cosmog/shiny.pal", ".gbapal");
diff --git a/src/data/items.h b/src/data/items.h
index e0e4de468e..8f3662ec97 100644
--- a/src/data/items.h
+++ b/src/data/items.h
@@ -14669,6 +14669,7 @@ const struct ItemInfo gItemsInfo[] =
"prevented for this\n"
"items's holder."),
.pocket = POCKET_ITEMS,
+ .sortType = ITEM_TYPE_HELD_ITEM,
.type = ITEM_USE_BAG_MENU,
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
.flingPower = 30,
@@ -15779,6 +15780,7 @@ const struct ItemInfo gItemsInfo[] =
.price = 1200,
.description = sQuestionMarksDesc,
.pocket = POCKET_ITEMS,
+ .sortType = ITEM_TYPE_AUX_ITEM,
.type = ITEM_USE_BAG_MENU,
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
//.effect = currently missing
@@ -15792,6 +15794,7 @@ const struct ItemInfo gItemsInfo[] =
.price = 1200,
.description = sQuestionMarksDesc,
.pocket = POCKET_ITEMS,
+ .sortType = ITEM_TYPE_AUX_ITEM,
.type = ITEM_USE_BAG_MENU,
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
//.effect = currently missing
@@ -15806,6 +15809,7 @@ const struct ItemInfo gItemsInfo[] =
.price = 1600,
.description = sQuestionMarksDesc,
.pocket = POCKET_ITEMS,
+ .sortType = ITEM_TYPE_AUX_ITEM,
.type = ITEM_USE_BAG_MENU,
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
//.effect = currently missing
diff --git a/src/data/pokemon/species_info/gen_7_families.h b/src/data/pokemon/species_info/gen_7_families.h
index 1558e80f80..5ff7bdb6ac 100644
--- a/src/data/pokemon/species_info/gen_7_families.h
+++ b/src/data/pokemon/species_info/gen_7_families.h
@@ -3029,8 +3029,15 @@ const struct SpeciesInfo gSpeciesInfoGen7[] =
.frontPic = gMonFrontPic_Fomantis,
.frontPicSize = MON_COORDS_SIZE(40, 48),
.frontPicYOffset = 11,
- .frontAnimFrames = sAnims_SingleFramePlaceHolder,
- .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE_SLOW,
+ .frontAnimFrames = ANIM_FRAMES(
+ ANIMCMD_FRAME(1, 15),
+ ANIMCMD_FRAME(0, 15),
+ ANIMCMD_FRAME(1, 15),
+ ANIMCMD_FRAME(0, 25),
+ ANIMCMD_FRAME(1, 15),
+ ANIMCMD_FRAME(0, 1),
+ ),
+ .frontAnimId = ANIM_TIP_MOVE_FORWARD,
.backPic = gMonBackPic_Fomantis,
.backPicSize = MON_COORDS_SIZE(40, 56),
.backPicYOffset = 5,
@@ -3227,8 +3234,11 @@ const struct SpeciesInfo gSpeciesInfoGen7[] =
.frontPic = gMonFrontPic_Morelull,
.frontPicSize = MON_COORDS_SIZE(24, 48),
.frontPicYOffset = 10,
- .frontAnimFrames = sAnims_SingleFramePlaceHolder,
- .frontAnimId = ANIM_SHAKE_FLASH_YELLOW,
+ .frontAnimFrames = ANIM_FRAMES(
+ ANIMCMD_FRAME(1, 55),
+ ANIMCMD_FRAME(0, 1),
+ ),
+ .frontAnimId = ANIM_GLOW_YELLOW,
.backPic = gMonBackPic_Morelull,
.backPicSize = MON_COORDS_SIZE(40, 48),
.backPicYOffset = 9,
@@ -3294,7 +3304,11 @@ const struct SpeciesInfo gSpeciesInfoGen7[] =
.frontPic = gMonFrontPic_Shiinotic,
.frontPicSize = MON_COORDS_SIZE(56, 56),
.frontPicYOffset = 4,
- .frontAnimFrames = sAnims_SingleFramePlaceHolder,
+ .frontAnimFrames = ANIM_FRAMES(
+ ANIMCMD_FRAME(1, 55),
+ ANIMCMD_FRAME(1, 55),
+ ANIMCMD_FRAME(0, 1),
+ ),
.frontAnimId = ANIM_SHAKE_GLOW_WHITE_SLOW,
.backPic = gMonBackPic_Shiinotic,
.backPicSize = MON_COORDS_SIZE(64, 48),
@@ -3695,7 +3709,10 @@ const struct SpeciesInfo gSpeciesInfoGen7[] =
.frontPic = gMonFrontPic_Bounsweet,
.frontPicSize = MON_COORDS_SIZE(32, 40),
.frontPicYOffset = 16,
- .frontAnimFrames = sAnims_SingleFramePlaceHolder,
+ .frontAnimFrames = ANIM_FRAMES(
+ ANIMCMD_FRAME(1, 30),
+ ANIMCMD_FRAME(0, 1),
+ ),
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_Bounsweet,
.backPicSize = MON_COORDS_SIZE(48, 40),
@@ -3762,8 +3779,13 @@ const struct SpeciesInfo gSpeciesInfoGen7[] =
.frontPic = gMonFrontPic_Steenee,
.frontPicSize = MON_COORDS_SIZE(48, 56),
.frontPicYOffset = 7,
- .frontAnimFrames = sAnims_SingleFramePlaceHolder,
- .frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
+ .frontAnimFrames = ANIM_FRAMES(
+ ANIMCMD_FRAME(1, 15),
+ ANIMCMD_FRAME(0, 15),
+ ANIMCMD_FRAME(1, 15),
+ ANIMCMD_FRAME(0, 1),
+ ),
+ .frontAnimId = ANIM_V_JUMPS_BIG,
.backPic = gMonBackPic_Steenee,
.backPicSize = MON_COORDS_SIZE(56, 56),
.backPicYOffset = 8,
@@ -3828,8 +3850,13 @@ const struct SpeciesInfo gSpeciesInfoGen7[] =
.frontPic = gMonFrontPic_Tsareena,
.frontPicSize = MON_COORDS_SIZE(56, 64),
.frontPicYOffset = 1,
- .frontAnimFrames = sAnims_SingleFramePlaceHolder,
- .frontAnimId = ANIM_SHRINK_GROW,
+ .frontAnimFrames = ANIM_FRAMES(
+ ANIMCMD_FRAME(1, 30),
+ ANIMCMD_FRAME(0, 40),
+ ANIMCMD_FRAME(1, 15),
+ ANIMCMD_FRAME(0, 1),
+ ),
+ .frontAnimId = ANIM_V_STRETCH,
.backPic = gMonBackPic_Tsareena,
.backPicSize = MON_COORDS_SIZE(56, 56),
.backPicYOffset = 6,
@@ -3895,8 +3922,11 @@ const struct SpeciesInfo gSpeciesInfoGen7[] =
.frontPic = gMonFrontPic_Comfey,
.frontPicSize = MON_COORDS_SIZE(48, 48),
.frontPicYOffset = 9,
- .frontAnimFrames = sAnims_SingleFramePlaceHolder,
- .frontAnimId = ANIM_H_SLIDE_WOBBLE,
+ .frontAnimFrames = ANIM_FRAMES(
+ ANIMCMD_FRAME(1, 30),
+ ANIMCMD_FRAME(0, 1),
+ ),
+ .frontAnimId = ANIM_CIRCULAR_STRETCH_TWICE,
.enemyMonElevation = 8,
.backPic = gMonBackPic_Comfey,
.backPicSize = MON_COORDS_SIZE(64, 56),
@@ -4300,8 +4330,11 @@ const struct SpeciesInfo gSpeciesInfoGen7[] =
.frontPic = gMonFrontPic_Sandygast,
.frontPicSize = MON_COORDS_SIZE(48, 48),
.frontPicYOffset = 11,
- .frontAnimFrames = sAnims_SingleFramePlaceHolder,
- .frontAnimId = ANIM_CIRCULAR_STRETCH_TWICE,
+ .frontAnimFrames = ANIM_FRAMES(
+ ANIMCMD_FRAME(1, 50),
+ ANIMCMD_FRAME(0, 1),
+ ),
+ .frontAnimId = ANIM_H_SHAKE,
.backPic = gMonBackPic_Sandygast,
.backPicSize = MON_COORDS_SIZE(40, 48),
.backPicYOffset = 11,
@@ -4367,8 +4400,11 @@ const struct SpeciesInfo gSpeciesInfoGen7[] =
.frontPic = gMonFrontPic_Palossand,
.frontPicSize = MON_COORDS_SIZE(64, 64),
.frontPicYOffset = 0,
- .frontAnimFrames = sAnims_SingleFramePlaceHolder,
- .frontAnimId = ANIM_H_VIBRATE,
+ .frontAnimFrames = ANIM_FRAMES(
+ ANIMCMD_FRAME(1, 50),
+ ANIMCMD_FRAME(0, 1),
+ ),
+ .frontAnimId = ANIM_GROW_VIBRATE,
.backPic = gMonBackPic_Palossand,
.backPicSize = MON_COORDS_SIZE(64, 64),
.backPicYOffset = 2,
@@ -4780,7 +4816,10 @@ const struct SpeciesInfo gSpeciesInfoGen7[] =
.frontPic = gMonFrontPic_Komala,
.frontPicSize = MON_COORDS_SIZE(48, 40),
.frontPicYOffset = 12,
- .frontAnimFrames = sAnims_SingleFramePlaceHolder,
+ .frontAnimFrames = ANIM_FRAMES(
+ ANIMCMD_FRAME(1, 60),
+ ANIMCMD_FRAME(0, 1),
+ ),
.frontAnimId = ANIM_H_DIP,
.backPic = gMonBackPic_Komala,
.backPicSize = MON_COORDS_SIZE(64, 48),
@@ -5286,8 +5325,13 @@ const struct SpeciesInfo gSpeciesInfoGen7[] =
.frontPic = gMonFrontPic_Bruxish,
.frontPicSize = MON_COORDS_SIZE(56, 40),
.frontPicYOffset = 15,
- .frontAnimFrames = sAnims_SingleFramePlaceHolder,
- .frontAnimId = ANIM_RISING_WOBBLE,
+ .frontAnimFrames = ANIM_FRAMES(
+ ANIMCMD_FRAME(1, 30),
+ ANIMCMD_FRAME(0, 20),
+ ANIMCMD_FRAME(1, 10),
+ ANIMCMD_FRAME(0, 1),
+ ),
+ .frontAnimId = ANIM_H_SPRING,
.backPic = gMonBackPic_Bruxish,
.backPicSize = MON_COORDS_SIZE(64, 48),
.backPicYOffset = 14,
@@ -5486,7 +5530,16 @@ const struct SpeciesInfo gSpeciesInfoGen7[] =
.frontPic = gMonFrontPic_Dhelmise,
.frontPicSize = MON_COORDS_SIZE(48, 64),
.frontPicYOffset = 1,
- .frontAnimFrames = sAnims_SingleFramePlaceHolder,
+ .frontAnimFrames = ANIM_FRAMES(
+ ANIMCMD_FRAME(1, 10),
+ ANIMCMD_FRAME(0, 10),
+ ANIMCMD_FRAME(1, 10),
+ ANIMCMD_FRAME(0, 10),
+ ANIMCMD_FRAME(1, 10),
+ ANIMCMD_FRAME(0, 10),
+ ANIMCMD_FRAME(1, 10),
+ ANIMCMD_FRAME(0, 1),
+ ),
.frontAnimId = ANIM_SWING_CONVEX,
.enemyMonElevation = 2,
.backPic = gMonBackPic_Dhelmise,
@@ -6117,7 +6170,10 @@ const struct SpeciesInfo gSpeciesInfoGen7[] =
.frontPic = gMonFrontPic_Cosmog,
.frontPicSize = MON_COORDS_SIZE(56, 48),
.frontPicYOffset = 10,
- .frontAnimFrames = sAnims_SingleFramePlaceHolder,
+ .frontAnimFrames = ANIM_FRAMES(
+ ANIMCMD_FRAME(1, 30),
+ ANIMCMD_FRAME(0, 1),
+ ),
.frontAnimId = ANIM_H_JUMPS_V_STRETCH,
.enemyMonElevation = 7,
.backPic = gMonBackPic_Cosmog,
diff --git a/src/data/script_menu.h b/src/data/script_menu.h
index 843a6a10cf..a4260e72c5 100644
--- a/src/data/script_menu.h
+++ b/src/data/script_menu.h
@@ -216,9 +216,9 @@ static const struct MenuAction MultichoiceList_Mechadoll5_Q3[] =
static const struct MenuAction MultichoiceList_VendingMachine[] =
{
- {COMPOUND_STRING("FRESH WATER{CLEAR_TO 0x48}¥200")},
- {COMPOUND_STRING("SODA POP{CLEAR_TO 0x48}¥300")},
- {COMPOUND_STRING("LEMONADE{CLEAR_TO 0x48}¥350")},
+ {COMPOUND_STRING("FRESH WATER{CLEAR_TO 72}¥200")},
+ {COMPOUND_STRING("SODA POP{CLEAR_TO 72}¥300")},
+ {COMPOUND_STRING("LEMONADE{CLEAR_TO 72}¥350")},
{gText_Exit},
};
@@ -273,11 +273,11 @@ static const struct MenuAction MultichoiceList_GameCornerDolls[] =
static const struct MenuAction MultichoiceList_GameCornerTMs[] =
{
- {COMPOUND_STRING("TM32{CLEAR_TO 0x48}1,500 COINS")},
- {COMPOUND_STRING("TM29{CLEAR_TO 0x48}3,500 COINS")},
- {COMPOUND_STRING("TM35{CLEAR_TO 0x48}4,000 COINS")},
- {COMPOUND_STRING("TM24{CLEAR_TO 0x48}4,000 COINS")},
- {COMPOUND_STRING("TM13{CLEAR_TO 0x48}4,000 COINS")},
+ {COMPOUND_STRING("TM32{CLEAR_TO 72}1,500 COINS")},
+ {COMPOUND_STRING("TM29{CLEAR_TO 72}3,500 COINS")},
+ {COMPOUND_STRING("TM35{CLEAR_TO 72}4,000 COINS")},
+ {COMPOUND_STRING("TM24{CLEAR_TO 72}4,000 COINS")},
+ {COMPOUND_STRING("TM13{CLEAR_TO 72}4,000 COINS")},
{gText_Exit},
};
@@ -817,7 +817,7 @@ static const struct MenuAction MultichoiceList_BerryPlot[] =
};
static const struct MenuAction sMultichoiceList_BikeShop[] = {
- {COMPOUND_STRING("BICYCLE{CLEAR_TO 0x49}{FONT_SMALL}¥1,000,000")},
+ {COMPOUND_STRING("BICYCLE{CLEAR_TO 73}{FONT_SMALL}¥1,000,000")},
{COMPOUND_STRING("NO THANKS")}
};
@@ -909,36 +909,36 @@ const u8 sText_NoThanks[] = _("NO THANKS");
static const struct MenuAction sMultichoiceList_GameCornerPokemonPrizes[] = {
#if defined(FIRERED)
- {COMPOUND_STRING("ABRA{CLEAR_TO 0x55}{FONT_SMALL} 180 COINS")},
- {COMPOUND_STRING("CLEFAIRY{CLEAR_TO 0x55}{FONT_SMALL} 500 COINS")},
- {COMPOUND_STRING("DRATINI{CLEAR_TO 0x4B}{FONT_SMALL} 2,800 COINS")},
- {COMPOUND_STRING("SCYTHER{CLEAR_TO 0x4B}{FONT_SMALL} 5,500 COINS")},
- {COMPOUND_STRING("PORYGON{CLEAR_TO 0x4B}{FONT_SMALL} 9,999 COINS")},
+ {COMPOUND_STRING("ABRA{CLEAR_TO 85}{FONT_SMALL} 180 COINS")},
+ {COMPOUND_STRING("CLEFAIRY{CLEAR_TO 85}{FONT_SMALL} 500 COINS")},
+ {COMPOUND_STRING("DRATINI{CLEAR_TO 75}{FONT_SMALL} 2,800 COINS")},
+ {COMPOUND_STRING("SCYTHER{CLEAR_TO 75}{FONT_SMALL} 5,500 COINS")},
+ {COMPOUND_STRING("PORYGON{CLEAR_TO 75}{FONT_SMALL} 9,999 COINS")},
#else
- {COMPOUND_STRING("ABRA{CLEAR_TO 0x55}{FONT_SMALL} 120 COINS")},
- {COMPOUND_STRING("CLEFAIRY{CLEAR_TO 0x55}{FONT_SMALL} 750 COINS")},
- {COMPOUND_STRING("PINSIR{CLEAR_TO 0x4B}{FONT_SMALL} 2,500 COINS")},
- {COMPOUND_STRING("DRATINI{CLEAR_TO 0x4B}{FONT_SMALL} 4,600 COINS")},
- {COMPOUND_STRING("PORYGON{CLEAR_TO 0x4B}{FONT_SMALL} 6,500 COINS")},
+ {COMPOUND_STRING("ABRA{CLEAR_TO 85}{FONT_SMALL} 120 COINS")},
+ {COMPOUND_STRING("CLEFAIRY{CLEAR_TO 85}{FONT_SMALL} 750 COINS")},
+ {COMPOUND_STRING("PINSIR{CLEAR_TO 75}{FONT_SMALL} 2,500 COINS")},
+ {COMPOUND_STRING("DRATINI{CLEAR_TO 75}{FONT_SMALL} 4,600 COINS")},
+ {COMPOUND_STRING("PORYGON{CLEAR_TO 75}{FONT_SMALL} 6,500 COINS")},
#endif
{sText_NoThanks}
};
static const struct MenuAction sMultichoiceList_GameCornerTMPrizes[] = {
- {COMPOUND_STRING("TM13{CLEAR_TO 0x48}{FONT_SMALL}4,000 COINS")},
- {COMPOUND_STRING("TM23{CLEAR_TO 0x48}{FONT_SMALL}3,500 COINS")},
- {COMPOUND_STRING("TM24{CLEAR_TO 0x48}{FONT_SMALL}4,000 COINS")},
- {COMPOUND_STRING("TM30{CLEAR_TO 0x48}{FONT_SMALL}4,500 COINS")},
- {COMPOUND_STRING("TM35{CLEAR_TO 0x48}{FONT_SMALL}4,000 COINS")},
+ {COMPOUND_STRING("TM13{CLEAR_TO 72}{FONT_SMALL}4,000 COINS")},
+ {COMPOUND_STRING("TM23{CLEAR_TO 72}{FONT_SMALL}3,500 COINS")},
+ {COMPOUND_STRING("TM24{CLEAR_TO 72}{FONT_SMALL}4,000 COINS")},
+ {COMPOUND_STRING("TM30{CLEAR_TO 72}{FONT_SMALL}4,500 COINS")},
+ {COMPOUND_STRING("TM35{CLEAR_TO 72}{FONT_SMALL}4,000 COINS")},
{sText_NoThanks}
};
static const struct MenuAction sMultichoiceList_GameCornerBattleItemPrizes[] = {
- {COMPOUND_STRING("SMOKE BALL{CLEAR_TO 0x5A}{FONT_SMALL}800 COINS")},
- {COMPOUND_STRING("MIRACLE SEED{CLEAR_TO 0x50}{FONT_SMALL}1,000 COINS")},
- {COMPOUND_STRING("CHARCOAL{CLEAR_TO 0x50}{FONT_SMALL}1,000 COINS")},
- {COMPOUND_STRING("MYSTIC WATER{CLEAR_TO 0x50}{FONT_SMALL}1,000 COINS")},
- {COMPOUND_STRING("YELLOW FLUTE{CLEAR_TO 0x50}{FONT_SMALL}1,600 COINS")},
+ {COMPOUND_STRING("SMOKE BALL{CLEAR_TO 90}{FONT_SMALL}800 COINS")},
+ {COMPOUND_STRING("MIRACLE SEED{CLEAR_TO 80}{FONT_SMALL}1,000 COINS")},
+ {COMPOUND_STRING("CHARCOAL{CLEAR_TO 80}{FONT_SMALL}1,000 COINS")},
+ {COMPOUND_STRING("MYSTIC WATER{CLEAR_TO 80}{FONT_SMALL}1,000 COINS")},
+ {COMPOUND_STRING("YELLOW FLUTE{CLEAR_TO 80}{FONT_SMALL}1,600 COINS")},
{sText_NoThanks}
};
@@ -952,8 +952,8 @@ static const struct MenuAction sMultichoiceList_DeptStoreElevator[] = {
};
static const struct MenuAction sMultichoiceList_GameCornerCoinPurchaseCounter[] = {
- {COMPOUND_STRING("{FONT_SMALL} 50 COINS{CLEAR_TO 0x45}¥1,000")},
- {COMPOUND_STRING("{FONT_SMALL}500 COINS{CLEAR_TO 0x40}¥10,000")},
+ {COMPOUND_STRING("{FONT_SMALL} 50 COINS{CLEAR_TO 69}¥1,000")},
+ {COMPOUND_STRING("{FONT_SMALL}500 COINS{CLEAR_TO 64}¥10,000")},
{gText_Exit}
};
@@ -965,9 +965,9 @@ static const struct MenuAction sMultichoiceList_LinkedDirectUnion[] = {
};
static const struct MenuAction sMultichoiceList_CeladonVendingMachine[] = {
- {COMPOUND_STRING("FRESH WATER{CLEAR_TO 0x57}{FONT_SMALL}¥200")},
- {COMPOUND_STRING("SODA POP{CLEAR_TO 0x57}{FONT_SMALL}¥300")},
- {COMPOUND_STRING("LEMONADE{CLEAR_TO 0x57}{FONT_SMALL}¥350")},
+ {COMPOUND_STRING("FRESH WATER{CLEAR_TO 87}{FONT_SMALL}¥200")},
+ {COMPOUND_STRING("SODA POP{CLEAR_TO 87}{FONT_SMALL}¥300")},
+ {COMPOUND_STRING("LEMONADE{CLEAR_TO 87}{FONT_SMALL}¥350")},
{gText_Exit}
};
diff --git a/src/field_specials.c b/src/field_specials.c
index 9cf4137653..e2cbe8b7f9 100644
--- a/src/field_specials.c
+++ b/src/field_specials.c
@@ -2543,48 +2543,48 @@ static const u8 *const sScrollableMultichoiceOptions[][MAX_SCROLL_MULTI_LENGTH]
},
[SCROLL_MULTI_BF_EXCHANGE_CORNER_DECOR_VENDOR_1] =
{
- COMPOUND_STRING("KISS POSTER{CLEAR_TO 0x5E}16BP"),
- COMPOUND_STRING("KISS CUSHION{CLEAR_TO 0x5E}32BP"),
- COMPOUND_STRING("SMOOCHUM DOLL{CLEAR_TO 0x5E}32BP"),
- COMPOUND_STRING("TOGEPI DOLL{CLEAR_TO 0x5E}48BP"),
- COMPOUND_STRING("MEOWTH DOLL{CLEAR_TO 0x5E}48BP"),
- COMPOUND_STRING("CLEFAIRY DOLL{CLEAR_TO 0x5E}48BP"),
- COMPOUND_STRING("DITTO DOLL{CLEAR_TO 0x5E}48BP"),
- COMPOUND_STRING("CYNDAQUIL DOLL{CLEAR_TO 0x5E}80BP"),
- COMPOUND_STRING("CHIKORITA DOLL{CLEAR_TO 0x5E}80BP"),
- COMPOUND_STRING("TOTODILE DOLL{CLEAR_TO 0x5E}80BP"),
+ COMPOUND_STRING("KISS POSTER{CLEAR_TO 94}16BP"),
+ COMPOUND_STRING("KISS CUSHION{CLEAR_TO 94}32BP"),
+ COMPOUND_STRING("SMOOCHUM DOLL{CLEAR_TO 94}32BP"),
+ COMPOUND_STRING("TOGEPI DOLL{CLEAR_TO 94}48BP"),
+ COMPOUND_STRING("MEOWTH DOLL{CLEAR_TO 94}48BP"),
+ COMPOUND_STRING("CLEFAIRY DOLL{CLEAR_TO 94}48BP"),
+ COMPOUND_STRING("DITTO DOLL{CLEAR_TO 94}48BP"),
+ COMPOUND_STRING("CYNDAQUIL DOLL{CLEAR_TO 94}80BP"),
+ COMPOUND_STRING("CHIKORITA DOLL{CLEAR_TO 94}80BP"),
+ COMPOUND_STRING("TOTODILE DOLL{CLEAR_TO 94}80BP"),
gText_Exit
},
[SCROLL_MULTI_BF_EXCHANGE_CORNER_DECOR_VENDOR_2] =
{
- COMPOUND_STRING("LAPRAS DOLL{CLEAR_TO 0x58}128BP"),
- COMPOUND_STRING("SNORLAX DOLL{CLEAR_TO 0x58}128BP"),
- COMPOUND_STRING("VENUSAUR DOLL{CLEAR_TO 0x58}256BP"),
- COMPOUND_STRING("CHARIZARD DOLL{CLEAR_TO 0x58}256BP"),
- COMPOUND_STRING("BLASTOISE DOLL{CLEAR_TO 0x58}256BP"),
+ COMPOUND_STRING("LAPRAS DOLL{CLEAR_TO 88}128BP"),
+ COMPOUND_STRING("SNORLAX DOLL{CLEAR_TO 88}128BP"),
+ COMPOUND_STRING("VENUSAUR DOLL{CLEAR_TO 88}256BP"),
+ COMPOUND_STRING("CHARIZARD DOLL{CLEAR_TO 88}256BP"),
+ COMPOUND_STRING("BLASTOISE DOLL{CLEAR_TO 88}256BP"),
gText_Exit
},
[SCROLL_MULTI_BF_EXCHANGE_CORNER_VITAMIN_VENDOR] =
{
- COMPOUND_STRING("PROTEIN{CLEAR_TO 0x64}1BP"),
- COMPOUND_STRING("CALCIUM{CLEAR_TO 0x64}1BP"),
- COMPOUND_STRING("IRON{CLEAR_TO 0x64}1BP"),
- COMPOUND_STRING("ZINC{CLEAR_TO 0x64}1BP"),
- COMPOUND_STRING("CARBOS{CLEAR_TO 0x64}1BP"),
- COMPOUND_STRING("HP UP{CLEAR_TO 0x64}1BP"),
+ COMPOUND_STRING("PROTEIN{CLEAR_TO 100}1BP"),
+ COMPOUND_STRING("CALCIUM{CLEAR_TO 100}1BP"),
+ COMPOUND_STRING("IRON{CLEAR_TO 100}1BP"),
+ COMPOUND_STRING("ZINC{CLEAR_TO 100}1BP"),
+ COMPOUND_STRING("CARBOS{CLEAR_TO 100}1BP"),
+ COMPOUND_STRING("HP UP{CLEAR_TO 100}1BP"),
gText_Exit
},
[SCROLL_MULTI_BF_EXCHANGE_CORNER_HOLD_ITEM_VENDOR] =
{
- COMPOUND_STRING("LEFTOVERS{CLEAR_TO 0x5E}48BP"),
- COMPOUND_STRING("WHITE HERB{CLEAR_TO 0x5E}48BP"),
- COMPOUND_STRING("QUICK CLAW{CLEAR_TO 0x5E}48BP"),
- COMPOUND_STRING("MENTAL HERB{CLEAR_TO 0x5E}48BP"),
- COMPOUND_STRING("BRIGHTPOWDER{CLEAR_TO 0x5E}64BP"),
- COMPOUND_STRING("CHOICE BAND{CLEAR_TO 0x5E}64BP"),
- COMPOUND_STRING("KING'S ROCK{CLEAR_TO 0x5E}64BP"),
- COMPOUND_STRING("FOCUS BAND{CLEAR_TO 0x5E}64BP"),
- COMPOUND_STRING("SCOPE LENS{CLEAR_TO 0x5E}64BP"),
+ COMPOUND_STRING("LEFTOVERS{CLEAR_TO 94}48BP"),
+ COMPOUND_STRING("WHITE HERB{CLEAR_TO 94}48BP"),
+ COMPOUND_STRING("QUICK CLAW{CLEAR_TO 94}48BP"),
+ COMPOUND_STRING("MENTAL HERB{CLEAR_TO 94}48BP"),
+ COMPOUND_STRING("BRIGHTPOWDER{CLEAR_TO 94}64BP"),
+ COMPOUND_STRING("CHOICE BAND{CLEAR_TO 94}64BP"),
+ COMPOUND_STRING("KING'S ROCK{CLEAR_TO 94}64BP"),
+ COMPOUND_STRING("FOCUS BAND{CLEAR_TO 94}64BP"),
+ COMPOUND_STRING("SCOPE LENS{CLEAR_TO 94}64BP"),
gText_Exit
},
[SCROLL_MULTI_BERRY_POWDER_VENDOR] =
@@ -2617,30 +2617,30 @@ static const u8 *const sScrollableMultichoiceOptions[][MAX_SCROLL_MULTI_LENGTH]
},
[SCROLL_MULTI_BF_MOVE_TUTOR_1] =
{
- COMPOUND_STRING("SOFTBOILED{CLEAR_TO 0x4E}16BP"),
- COMPOUND_STRING("SEISMIC TOSS{CLEAR_TO 0x4E}24BP"),
- COMPOUND_STRING("DREAM EATER{CLEAR_TO 0x4E}24BP"),
- COMPOUND_STRING("MEGA PUNCH{CLEAR_TO 0x4E}24BP"),
- COMPOUND_STRING("MEGA KICK{CLEAR_TO 0x4E}48BP"),
- COMPOUND_STRING("BODY SLAM{CLEAR_TO 0x4E}48BP"),
- COMPOUND_STRING("ROCK SLIDE{CLEAR_TO 0x4E}48BP"),
- COMPOUND_STRING("COUNTER{CLEAR_TO 0x4E}48BP"),
- COMPOUND_STRING("THUNDER WAVE{CLEAR_TO 0x4E}48BP"),
- COMPOUND_STRING("SWORDS DANCE{CLEAR_TO 0x4E}48BP"),
+ COMPOUND_STRING("SOFTBOILED{CLEAR_TO 78}16BP"),
+ COMPOUND_STRING("SEISMIC TOSS{CLEAR_TO 78}24BP"),
+ COMPOUND_STRING("DREAM EATER{CLEAR_TO 78}24BP"),
+ COMPOUND_STRING("MEGA PUNCH{CLEAR_TO 78}24BP"),
+ COMPOUND_STRING("MEGA KICK{CLEAR_TO 78}48BP"),
+ COMPOUND_STRING("BODY SLAM{CLEAR_TO 78}48BP"),
+ COMPOUND_STRING("ROCK SLIDE{CLEAR_TO 78}48BP"),
+ COMPOUND_STRING("COUNTER{CLEAR_TO 78}48BP"),
+ COMPOUND_STRING("THUNDER WAVE{CLEAR_TO 78}48BP"),
+ COMPOUND_STRING("SWORDS DANCE{CLEAR_TO 78}48BP"),
gText_Exit
},
[SCROLL_MULTI_BF_MOVE_TUTOR_2] =
{
- COMPOUND_STRING("DEFENSE CURL{CLEAR_TO 0x4E}16BP"),
- COMPOUND_STRING("SNORE{CLEAR_TO 0x4E}24BP"),
- COMPOUND_STRING("MUD-SLAP{CLEAR_TO 0x4E}24BP"),
- COMPOUND_STRING("SWIFT{CLEAR_TO 0x4E}24BP"),
- COMPOUND_STRING("ICY WIND{CLEAR_TO 0x4E}24BP"),
- COMPOUND_STRING("ENDURE{CLEAR_TO 0x4E}48BP"),
- COMPOUND_STRING("PSYCH UP{CLEAR_TO 0x4E}48BP"),
- COMPOUND_STRING("ICE PUNCH{CLEAR_TO 0x4E}48BP"),
- COMPOUND_STRING("THUNDERPUNCH{CLEAR_TO 0x4E}48BP"),
- COMPOUND_STRING("FIRE PUNCH{CLEAR_TO 0x4E}48BP"),
+ COMPOUND_STRING("DEFENSE CURL{CLEAR_TO 78}16BP"),
+ COMPOUND_STRING("SNORE{CLEAR_TO 78}24BP"),
+ COMPOUND_STRING("MUD-SLAP{CLEAR_TO 78}24BP"),
+ COMPOUND_STRING("SWIFT{CLEAR_TO 78}24BP"),
+ COMPOUND_STRING("ICY WIND{CLEAR_TO 78}24BP"),
+ COMPOUND_STRING("ENDURE{CLEAR_TO 78}48BP"),
+ COMPOUND_STRING("PSYCH UP{CLEAR_TO 78}48BP"),
+ COMPOUND_STRING("ICE PUNCH{CLEAR_TO 78}48BP"),
+ COMPOUND_STRING("THUNDERPUNCH{CLEAR_TO 78}48BP"),
+ COMPOUND_STRING("FIRE PUNCH{CLEAR_TO 78}48BP"),
gText_Exit
},
[SCROLL_MULTI_SS_TIDAL_DESTINATION] =
diff --git a/src/item.c b/src/item.c
index cec77d7dfb..e060343c30 100644
--- a/src/item.c
+++ b/src/item.c
@@ -34,6 +34,8 @@ static bool32 CheckPyramidBagHasSpace(enum Item itemId, u16 count);
static const u8 *GetItemPluralName(enum Item);
static bool32 DoesItemHavePluralName(enum Item);
static void NONNULL BagPocket_CompactItems(struct BagPocket *pocket);
+static u16 SanitizeItemId(enum Item itemId);
+static u16 SanitizeBagItemId(enum Item itemId);
EWRAM_DATA struct BagPocket gBagPockets[POCKETS_COUNT] = {0};
@@ -347,7 +349,8 @@ static bool32 NONNULL BagPocket_AddItem(struct BagPocket *pocket, enum Item item
bool32 AddBagItem(enum Item itemId, u16 count)
{
- if (GetItemPocket(itemId) >= POCKETS_COUNT)
+ itemId = SanitizeBagItemId(itemId);
+ if (itemId == ITEM_NONE)
return FALSE;
// check Battle Pyramid Bag
@@ -403,7 +406,8 @@ static bool32 NONNULL BagPocket_RemoveItem(struct BagPocket *pocket, enum Item i
bool32 RemoveBagItem(enum Item itemId, u16 count)
{
- if (GetItemPocket(itemId) >= POCKETS_COUNT || itemId == ITEM_NONE)
+ itemId = SanitizeBagItemId(itemId);
+ if (itemId == ITEM_NONE)
return FALSE;
// check Battle Pyramid Bag
@@ -789,6 +793,23 @@ static u16 SanitizeItemId(enum Item itemId)
return itemId;
}
+static u16 SanitizeBagItemId(enum Item itemId)
+{
+ itemId = SanitizeItemId(itemId);
+
+ assertf(itemId != ITEM_NONE, "invalid bag item: ITEM_NONE")
+ {
+ return ITEM_NONE;
+ }
+
+ assertf(GetItemPocket(itemId) < POCKETS_COUNT, "invalid bag item pocket: %S", gItemsInfo[itemId].name)
+ {
+ return ITEM_NONE;
+ }
+
+ return itemId;
+}
+
const u8 *GetItemName(enum Item itemId)
{
const u8 *name = gItemsInfo[SanitizeItemId(itemId)].name;
diff --git a/src/malloc.c b/src/malloc.c
index f31c4e024e..2f457bfddd 100644
--- a/src/malloc.c
+++ b/src/malloc.c
@@ -27,7 +27,7 @@ void PutFirstMemBlockHeader(void *block, u32 size)
PutMemBlockHeader(block, (struct MemBlock *)block, (struct MemBlock *)block, size - sizeof(struct MemBlock));
}
-void *AllocInternal(void *heapStart, u32 size, const char *location)
+static void *AllocInternal(void *heapStart, u32 size, const char *location)
{
struct MemBlock *pos = (struct MemBlock *)heapStart;
struct MemBlock *head = pos;
@@ -81,36 +81,14 @@ void *AllocInternal(void *heapStart, u32 size, const char *location)
}
}
-#if TESTING
if (pos->next == head)
- {
- const struct MemBlock *head = HeapHead();
- const struct MemBlock *block = head;
- do
- {
- if (block->allocated)
- {
- const char *location = MemBlockLocation(block);
- if (location)
- Test_MgbaPrintf("%s: %d bytes allocated", location, block->size);
- else
- Test_MgbaPrintf(": %d bytes allocated", block->size);
- }
- block = block->next;
- }
- while (block != head);
- }
-#endif
- assertf(pos->next != head, "%s: out of memory trying to allocate %d bytes", location, size)
- {
return NULL;
- }
pos = pos->next;
}
}
-void FreeInternal(void *heapStart, void *pointer)
+static void FreeInternal(void *heapStart, void *pointer)
{
if (pointer)
{
@@ -154,7 +132,7 @@ void FreeInternal(void *heapStart, void *pointer)
}
}
-void *AllocZeroedInternal(void *heapStart, u32 size, const char *location)
+static void *AllocZeroedInternal(void *heapStart, u32 size, const char *location)
{
void *mem = AllocInternal(heapStart, size, location);
@@ -169,7 +147,7 @@ void *AllocZeroedInternal(void *heapStart, u32 size, const char *location)
return mem;
}
-bool32 CheckMemBlockInternal(void *heapStart, void *pointer)
+static bool32 CheckMemBlockInternal(void *heapStart, void *pointer)
{
struct MemBlock *head = (struct MemBlock *)heapStart;
struct MemBlock *block = (struct MemBlock *)((u8 *)pointer - sizeof(struct MemBlock));
@@ -202,12 +180,55 @@ void InitHeap(void *heapStart, u32 heapSize)
PutFirstMemBlockHeader(heapStart, heapSize);
}
+void PrintHeap(void)
+{
+ const struct MemBlock *head = HeapHead();
+ const struct MemBlock *block = head;
+ do
+ {
+ if (block->allocated)
+ {
+ const char *location = MemBlockLocation(block);
+ if (location)
+ DebugPrintf("%s: %d bytes allocated", location, block->size);
+ else
+ DebugPrintf(": %d bytes allocated", block->size);
+ }
+ block = block->next;
+ }
+ while (block != head);
+}
+
void *Alloc_(u32 size, const char *location)
+{
+ void *p = AllocInternal(sHeapStart, size, location);
+ if (!p)
+ {
+ if (TESTING)
+ PrintHeap();
+ errorf("%s: out of memory trying to allocate %d bytes", location, size);
+ }
+ return p;
+}
+
+void *AllocUnchecked_(u32 size, const char *location)
{
return AllocInternal(sHeapStart, size, location);
}
void *AllocZeroed_(u32 size, const char *location)
+{
+ void *p = AllocZeroedInternal(sHeapStart, size, location);
+ if (!p)
+ {
+ if (TESTING)
+ PrintHeap();
+ errorf("%s: out of memory trying to allocate %d bytes", location, size);
+ }
+ return p;
+}
+
+void *AllocZeroedUnchecked_(u32 size, const char *location)
{
return AllocZeroedInternal(sHeapStart, size, location);
}
diff --git a/src/mini_printf.c b/src/mini_printf.c
index 31d72dcd17..74ceb5bad5 100644
--- a/src/mini_printf.c
+++ b/src/mini_printf.c
@@ -47,7 +47,7 @@ struct mini_buff
u32 buffer_len;
};
-static inline char mini_pchar_decode(char encoded)
+char mini_pchar_decode(char encoded)
{
char ret = '?';
if (encoded >= CHAR_a && encoded <= CHAR_z)
diff --git a/src/party_menu.c b/src/party_menu.c
index e72ce71737..aa70440700 100644
--- a/src/party_menu.c
+++ b/src/party_menu.c
@@ -2119,19 +2119,27 @@ static void GiveItemToMon(struct Pokemon *mon, enum Item item)
TryItemHoldFormChange(&gParties[B_TRAINER_PLAYER][gPartyMenu.slotId], gPartyMenu.slotId, B_TRAINER_PLAYER);
}
-static u8 TryTakeMonItem(struct Pokemon *mon)
+enum TryTakeMonItemResult
+{
+ TAKE_NO_ITEM,
+ TAKE_NO_BAG_SPACE,
+ TAKE_OK,
+};
+
+static enum TryTakeMonItemResult TryTakeMonItem(struct Pokemon *mon)
{
enum Item item = GetMonData(mon, MON_DATA_HELD_ITEM);
if (item == ITEM_NONE)
- return 0;
- if (AddBagItem(item, 1) == FALSE)
- return 1;
+ return TAKE_NO_ITEM;
+
+ if (!AddBagItem(item, 1))
+ return TAKE_NO_BAG_SPACE;
item = ITEM_NONE;
SetMonData(mon, MON_DATA_HELD_ITEM, &item);
TryItemHoldFormChange(&gParties[B_TRAINER_PLAYER][gPartyMenu.slotId], gPartyMenu.slotId, B_TRAINER_PLAYER);
- return 2;
+ return TAKE_OK;
}
static void BufferBagFullCantTakeItemMessage(u16 itemUnused)
@@ -3652,16 +3660,16 @@ static void CursorCb_TakeItem(u8 taskId)
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
switch (TryTakeMonItem(mon))
{
- case 0: // Not holding item
+ case TAKE_NO_ITEM:
GetMonNickname(mon, gStringVar1);
StringExpandPlaceholders(gStringVar4, gText_PkmnNotHolding);
DisplayPartyMenuMessage(gStringVar4, TRUE);
break;
- case 1: // No room to take item
+ case TAKE_NO_BAG_SPACE:
BufferBagFullCantTakeItemMessage(item);
DisplayPartyMenuMessage(gStringVar4, TRUE);
break;
- default: // Took item
+ case TAKE_OK:
DisplayTookHeldItemMessage(mon, item, TRUE);
break;
}
diff --git a/src/pokeball.c b/src/pokeball.c
index c8d9f5e4a7..1bca450a35 100644
--- a/src/pokeball.c
+++ b/src/pokeball.c
@@ -45,7 +45,7 @@ static void SpriteCB_TradePokeballEnd(struct Sprite *sprite);
static void SpriteCB_HealthboxSlideInDelayed(struct Sprite *sprite);
static void SpriteCB_HealthboxSlideIn(struct Sprite *sprite);
static void SpriteCB_HitAnimHealthoxEffect(struct Sprite *sprite);
-static u16 GetBattlerPokeballItemId(enum BattlerId battler);
+static enum PokeBall GetBattlerPokeballItemId(enum BattlerId battler);
// rom const data
@@ -400,7 +400,8 @@ u8 DoPokeballSendOutAnimation(enum BattlerId battler, s16 pan, u8 kindOfThrow)
static void Task_DoPokeballSendOutAnim(u8 taskId)
{
- u32 throwCaseId, ballId, ballSpriteId;
+ u32 throwCaseId, ballSpriteId;
+ enum PokeBall ballId;
enum BattlerId battler;
bool32 notSendOut = FALSE;
u32 throwXoffset = (B_ENEMY_THROW_BALLS >= GEN_6 && !gTestRunnerHeadless) ? 24 : 0;
@@ -491,7 +492,7 @@ static void SpriteCB_BallThrow(struct Sprite *sprite)
{
if (TranslateAnimHorizontalArc(sprite))
{
- u16 ballId;
+ enum PokeBall ballId;
u8 taskId = sprite->oam.affineParam;
u8 opponentBattler = gTasks[taskId].tOpponentBattler;
u8 noOfShakes = gTasks[taskId].tThrowId;
@@ -816,7 +817,7 @@ static void Task_PlayCryWhenReleasedFromBall(u8 taskId)
static void SpriteCB_ReleaseMonFromBall(struct Sprite *sprite)
{
enum BattlerId battler = sprite->sBattler;
- u32 ballId;
+ enum PokeBall ballId;
StartSpriteAnim(sprite, 1);
ballId = GetBattlerPokeballItemId(battler);
@@ -1395,7 +1396,7 @@ static void SpriteCB_HitAnimHealthoxEffect(struct Sprite *sprite)
}
}
-void LoadBallGfx(u8 ballId)
+void LoadBallGfx(enum PokeBall ballId)
{
u16 var;
@@ -1414,16 +1415,18 @@ void LoadBallGfx(u8 ballId)
var = GetSpriteTileStartByTag(gPokeBalls[ballId].pic.tag);
DecompressDataWithHeaderVram(gOpenPokeballGfx, (void *)(OBJ_VRAM0 + 0x100 + var * 32));
break;
+ default:
+ break;
}
}
-void FreeBallGfx(u8 ballId)
+void FreeBallGfx(enum PokeBall ballId)
{
FreeSpriteTilesByTag(gPokeBalls[ballId].pic.tag);
FreeSpritePaletteByTag(gPokeBalls[ballId].palette.tag);
}
-static u16 GetBattlerPokeballItemId(enum BattlerId battler)
+static enum PokeBall GetBattlerPokeballItemId(enum BattlerId battler)
{
struct Pokemon *illusionMon;
struct Pokemon *mon = GetBattlerMon(battler);
diff --git a/src/pokedex_plus_hgss.c b/src/pokedex_plus_hgss.c
index 108bb569d1..f469694de3 100644
--- a/src/pokedex_plus_hgss.c
+++ b/src/pokedex_plus_hgss.c
@@ -149,9 +149,9 @@ static const u8 sText_EVO_DEFEAT_THREE_WITH_ITEM[] = _("{LV}{UP_ARROW} defeating
static const u8 sText_EVO_NONE[] = _("{STR_VAR_1} has no evolution.");
static const u8 sText_FORMS_Buttons_PE[] = _("{A_BUTTON}FORM MODE {START_BUTTON}EVOs");
-static const u8 sText_FORMS_Buttons_Decapped_PE[] = _("{START_BUTTON}Evos");
+static const u8 sText_FORMS_Buttons_Decapped_PE[] = _("{A_BUTTON}Form Mode {START_BUTTON}Evos");
static const u8 sText_FORMS_Buttons_Submenu_PE[] = _("{DPAD_NONE}FORMs {A_BUTTON}CHECK {START_BUTTON}EVOs");
-static const u8 sText_FORMS_Buttons_Submenu_Decapped_PE[] = _("{START_BUTTON}Evos");
+static const u8 sText_FORMS_Buttons_Submenu_Decapped_PE[] = _("{DPAD_NONE}Forms {A_BUTTON}Check {START_BUTTON}Evos");
static const u8 sText_FORMS_NONE[] = _("{STR_VAR_1} has no alternate forms.");
static const u8 sText_PlusSymbol[] = _("+");
diff --git a/src/pokemon.c b/src/pokemon.c
index f8f66967a7..36a6a97716 100644
--- a/src/pokemon.c
+++ b/src/pokemon.c
@@ -1006,7 +1006,7 @@ void CreateBoxMon(struct BoxPokemon *boxMon, enum Species species, u8 level, u32
SetBoxMonData(boxMon, MON_DATA_MET_LOCATION, &value);
SetBoxMonData(boxMon, MON_DATA_MET_LEVEL, &level);
SetBoxMonData(boxMon, MON_DATA_MET_GAME, &gGameVersion);
- value = ITEM_POKE_BALL;
+ value = BALL_POKE;
SetBoxMonData(boxMon, MON_DATA_POKEBALL, &value);
SetBoxMonData(boxMon, MON_DATA_OT_GENDER, &gSaveBlock2Ptr->playerGender);
@@ -5050,7 +5050,7 @@ s32 CalculateFriendshipBonuses(struct Pokemon *mon, s32 modifier, enum HoldEffec
if (modifier == 0)
return bonus;
- if (GetMonData(mon, MON_DATA_POKEBALL) == ITEM_LUXURY_BALL)
+ if (GetMonData(mon, MON_DATA_POKEBALL) == BALL_LUXURY)
bonus += ITEM_FRIENDSHIP_LUXURY_BONUS;
if (GetMonData(mon, MON_DATA_MET_LOCATION) == GetCurrentRegionMapSectionId())
@@ -6524,7 +6524,12 @@ bool32 TryBoxMonFormChange(struct BoxPokemon *boxMon, enum FormChanges method)
enum Species SanitizeSpeciesId(enum Species species)
{
- assertf(species <= NUM_SPECIES && (species == SPECIES_NONE || IsSpeciesEnabled(species)), "invalid species: %d", species)
+ assertf(species <= NUM_SPECIES, "invalid species: %d", species)
+ {
+ return SPECIES_NONE;
+ }
+
+ assertf(species == SPECIES_NONE || IsSpeciesEnabled(species), "disabled species: %d", species)
{
return SPECIES_NONE;
}
diff --git a/src/pokenav_ribbons_summary.c b/src/pokenav_ribbons_summary.c
index 4e862a6534..7bc67d1eb3 100644
--- a/src/pokenav_ribbons_summary.c
+++ b/src/pokenav_ribbons_summary.c
@@ -871,9 +871,9 @@ static void AddRibbonSummaryMonNameWindow(struct Pokenav_RibbonsSummaryMenu *men
PrintRibbbonsSummaryMonInfo(menu);
}
-static const u8 sMaleIconString[] = _("{TEXT_COLORS LIGHT_RED GREEN WHITE}{BACKGROUND WHITE}♂{TEXT_COLORS DARK_GRAY LIGHT_GRAY WHITE}{BACKGROUND WHITE}");
-static const u8 sFemaleIconString[] = _("{TEXT_COLORS LIGHT_GREEN BLUE WHITE}{BACKGROUND WHITE}♀{TEXT_COLORS DARK_GRAY LIGHT_GRAY WHITE}{BACKGROUND WHITE}");
-static const u8 sGenderlessIconString[] = _("{UNK_SPACER}");
+static const u8 sText_MaleSymbol[] = _("{TEXT_COLORS LIGHT_RED GREEN WHITE}{BACKGROUND WHITE}♂{TEXT_COLORS DARK_GRAY LIGHT_GRAY WHITE}{BACKGROUND WHITE}");
+static const u8 sText_FemaleSymbol[] = _("{TEXT_COLORS LIGHT_GREEN BLUE WHITE}{BACKGROUND WHITE}♀{TEXT_COLORS DARK_GRAY LIGHT_GRAY WHITE}{BACKGROUND WHITE}");
+static const u8 sText_NoGenderSymbol[] = _("{UNK_SPACER}");
static void PrintRibbbonsSummaryMonInfo(struct Pokenav_RibbonsSummaryMenu *menu)
{
@@ -887,13 +887,13 @@ static void PrintRibbbonsSummaryMonInfo(struct Pokenav_RibbonsSummaryMenu *menu)
switch (gender)
{
case MON_MALE:
- genderTxt = sMaleIconString;
+ genderTxt = sText_MaleSymbol;
break;
case MON_FEMALE:
- genderTxt = sFemaleIconString;
+ genderTxt = sText_FemaleSymbol;
break;
default:
- genderTxt = sGenderlessIconString;
+ genderTxt = sText_NoGenderSymbol;
break;
}
AddTextPrinterParameterized(windowId, GetFontIdToFit(gStringVar3, FONT_NORMAL, 0, 60), gStringVar3, 0, 1, TEXT_SKIP_DRAW, NULL);
diff --git a/src/save_failed_screen.c b/src/save_failed_screen.c
index c2d16b0dc6..2075ae96ef 100644
--- a/src/save_failed_screen.c
+++ b/src/save_failed_screen.c
@@ -424,7 +424,8 @@ void CB2_FlashNotDetectedScreen(void)
.height = 16,
.paletteNum = 15,
.baseBlock = 1,
- }
+ },
+ DUMMY_WIN_TEMPLATE
};
if (gMain.state)
diff --git a/src/scrcmd.c b/src/scrcmd.c
index 3d16267598..ad8479f2c2 100644
--- a/src/scrcmd.c
+++ b/src/scrcmd.c
@@ -88,10 +88,6 @@ extern const u8 *gStdScripts_End[];
static void CloseBrailleWindow(void);
static void DynamicMultichoiceSortList(struct ListMenuItem *items, u32 count);
-// This is defined in here so the optimizer can't see its value when compiling
-// script.c.
-void *const gNullScriptPtr = NULL;
-
static const u8 sScriptConditionTable[6][3] =
{
// < = >
diff --git a/src/script.c b/src/script.c
index 3f40103954..ff1e43375a 100644
--- a/src/script.c
+++ b/src/script.c
@@ -40,7 +40,6 @@ EWRAM_DATA u8 gMsgBoxIsCancelable = FALSE;
extern ScrCmdFunc gScriptCmdTable[];
extern ScrCmdFunc gScriptCmdTableEnd[];
-extern void *const gNullScriptPtr;
void InitScriptStack(struct ScriptStack *stk)
{
@@ -90,9 +89,6 @@ void StopScript(struct ScriptContext *ctx)
bool8 RunScriptCommand(struct ScriptContext *ctx)
{
- if (ctx->mode == SCRIPT_MODE_STOPPED)
- return FALSE;
-
switch (ctx->mode)
{
case SCRIPT_MODE_STOPPED:
@@ -114,18 +110,12 @@ bool8 RunScriptCommand(struct ScriptContext *ctx)
u8 cmdCode;
ScrCmdFunc *func;
- if (!ctx->scriptPtr)
+ if (ctx->scriptPtr == NULL)
{
ctx->mode = SCRIPT_MODE_STOPPED;
return FALSE;
}
- if (ctx->scriptPtr == gNullScriptPtr)
- {
- while (1)
- asm("svc 2"); // HALT
- }
-
cmdCode = *(ctx->scriptPtr);
ctx->scriptPtr++;
func = &ctx->cmdTable[cmdCode];
@@ -192,16 +182,26 @@ const u8 *ScriptPop(struct ScriptContext *ctx)
void ScriptJump(struct ScriptContext *ctx, const u8 *ptr)
{
+ assertf(ptr != NULL, "goto to NULL");
ctx->scriptPtr = ptr;
}
void ScriptCall(struct ScriptContext *ctx, const u8 *ptr)
{
- assertf(!ScriptPush(ctx, ctx->scriptPtr),
- "Failed to push %p to %p", ptr, ctx)
+ assertf(ptr != NULL, "call to NULL")
+ {
+ // HINT: Returning without having pushed the current location is
+ // equivalent to branching to a script that just contains
+ // 'return'.
+ return;
+ }
+
+ bool32 failed = ScriptPush(ctx, ctx->scriptPtr);
+ assertf(!failed, "could not push %p to %p", ptr, ctx)
{
return;
}
+
ctx->scriptPtr = ptr;
}
diff --git a/src/sprite.c b/src/sprite.c
index 80051f576f..c4e1851589 100644
--- a/src/sprite.c
+++ b/src/sprite.c
@@ -15,8 +15,8 @@
#define SET_SPRITE_TILE_RANGE(index, start, count) \
{ \
- sSpriteTileRanges[index * 2] = start; \
- (sSpriteTileRanges + 1)[index * 2] = count; \
+ sSpriteTileRanges[index][0] = start; \
+ sSpriteTileRanges[index][1] = count; \
}
#define ALLOC_SPRITE_TILE(n) \
@@ -250,7 +250,7 @@ const struct OamDimensions gOamDimensions[3][4] =
// iwram bss
static u16 sSpriteTileRangeTags[MAX_SPRITES];
-static u16 sSpriteTileRanges[MAX_SPRITES * 2];
+static u16 sSpriteTileRanges[MAX_SPRITES][2];
static struct AffineAnimState sAffineAnimStates[OAM_MATRIX_COUNT];
static u16 sSpritePaletteTags[16];
@@ -1563,14 +1563,10 @@ void FreeSpriteTilesByTag(u16 tag)
gSpriteAllocs--;
#endif
u16 i;
- u16 *rangeStarts;
- u16 *rangeCounts;
u16 start;
u16 count;
- rangeStarts = sSpriteTileRanges;
- start = rangeStarts[index * 2];
- rangeCounts = sSpriteTileRanges + 1;
- count = rangeCounts[index * 2];
+ start = sSpriteTileRanges[index][0];
+ count = sSpriteTileRanges[index][1];
for (i = start; i < start + count; i++)
FREE_SPRITE_TILE(i);
@@ -1595,7 +1591,7 @@ u16 GetSpriteTileStartByTag(u16 tag)
u8 index = IndexOfSpriteTileTag(tag);
if (index == 0xFF)
return 0xFFFF;
- return sSpriteTileRanges[index * 2];
+ return sSpriteTileRanges[index][0];
}
u8 IndexOfSpriteTileTag(u16 tag)
@@ -1615,7 +1611,7 @@ u16 GetSpriteTileTagByTileStart(u16 start)
for (i = 0; i < MAX_SPRITES; i++)
{
- if (sSpriteTileRangeTags[i] != TAG_NONE && sSpriteTileRanges[i * 2] == start)
+ if (sSpriteTileRangeTags[i] != TAG_NONE && sSpriteTileRanges[i][0] == start)
return sSpriteTileRangeTags[i];
}
diff --git a/src/strings.c b/src/strings.c
index 3c94e0917e..863fb14280 100644
--- a/src/strings.c
+++ b/src/strings.c
@@ -45,12 +45,12 @@ const u8 gText_Boy[] = _("BOY");
const u8 gText_Girl[] = _("GIRL");
const u8 gText_ThisIsAPokemon[] = _("This is what we call a “POKéMON.”{PAUSE 96}\p");
const u8 gText_5MarksPokemon[] = _("????? POKéMON");
-const u8 gText_UnkHeight[] = _("{CLEAR_TO 0x0C}??'??”");
+const u8 gText_UnkHeight[] = _("{CLEAR_TO 12}??'??”");
const u8 gText_UnkHeightMetric[] = _("???.? m");
const u8 gText_UnkWeight[] = _("????.? lbs.");
const u8 gText_UnkWeightMetric[] = _("???.? kg.");
const u8 gText_EmptyPkmnCategory[] = _(" POKéMON"); // Unused
-const u8 gText_EmptyHeight[] = _("{CLEAR_TO 0x0C} ' ”"); // Unused
+const u8 gText_EmptyHeight[] = _("{CLEAR_TO 12} ' ”"); // Unused
const u8 gText_EmptyWeight[] = _(" . lbs."); // Unused
const u8 gText_EmptyPokedexInfo1[] = _(""); // Unused
const u8 gText_CryOf[] = _("CRY OF");
@@ -143,7 +143,7 @@ const u8 gText_ThreeDashes[] = _("---");
const u8 gText_MaleSymbol[] = _("♂");
const u8 gText_FemaleSymbol[] = _("♀");
const u8 gText_LevelSymbol[] = _("{LV}");
-const u8 gText_NumberClear01[] = _("{NO}{CLEAR 0x01}");
+const u8 gText_NumberClear01[] = _("{NO}{CLEAR 1}");
const u8 gText_RightArrow[] = _("{RIGHT_ARROW}"); // Unused
const u8 gText_IDNumber2[] = _("{ID}{NO}");
const u8 gText_Space[] = _(" ");
@@ -210,8 +210,8 @@ const u8 *const gPocketNamesStringsTable[] =
[POCKET_KEY_ITEMS] = COMPOUND_STRING("KEY ITEMS")
};
-const u8 gText_NumberItem_TMBerry[] = _("{NO}{STR_VAR_1}{CLEAR 0x03}{STR_VAR_2}");
-const u8 gText_NumberItem_HM[] = _("{CLEAR_TO 0x11}{STR_VAR_1}{CLEAR 0x05}{STR_VAR_2}");
+const u8 gText_NumberItem_TMBerry[] = _("{NO}{STR_VAR_1}{CLEAR 3}{STR_VAR_2}");
+const u8 gText_NumberItem_HM[] = _("{CLEAR_TO 17}{STR_VAR_1}{CLEAR 5}{STR_VAR_2}");
const u8 gText_ShopBuy[] = _("BUY");
const u8 gText_ShopSell[] = _("SELL");
@@ -820,7 +820,7 @@ const u8 gText_BerriesPicked[] = _("BERRIES picked:");
const u8 gText_BestScore[] = _("Best score:");
const u8 gText_BerriesInRowFivePlayers[] = _("BERRIES picked in a row with\nfive players:");
const u8 gText_BerryPickingResults[] = _("Announcing BERRY-PICKING results!");
-const u8 gText_10P30P50P50P[] = _("{CLEAR_TO 0x03}10P{CLEAR_TO 0x2B}30P{CLEAR_TO 0x53}50P{CLEAR_TO 0x77}{EMOJI_MINUS}50P");
+const u8 gText_10P30P50P50P[] = _("{CLEAR_TO 3}10P{CLEAR_TO 43}30P{CLEAR_TO 83}50P{CLEAR_TO 119}{EMOJI_MINUS}50P");
const u8 gText_AnnouncingRankings[] = _("Announcing rankings!");
const u8 gText_AnnouncingPrizes[] = _("Announcing prizes!");
const u8 gText_1Colon[] = _("1:");
@@ -895,7 +895,7 @@ const u8 gText_Total[] = _("Total");
const u8 gText_ClearStreak[] = _("Clear streak: {STR_VAR_1}");
const u8 gText_Championships[] = _("Championships: {STR_VAR_1}");
const u8 gText_RoomsCleared[] = _("Rooms cleared: {STR_VAR_1}");
-const u8 gText_TimesCleared[] = _("Times cleared:{CLEAR 0x05}{STR_VAR_1}");
+const u8 gText_TimesCleared[] = _("Times cleared:{CLEAR 5}{STR_VAR_1}");
const u8 gText_KOsInARow[] = _("KOs in a row: {STR_VAR_1}");
const u8 gText_TimesVar1[] = _("Times: {STR_VAR_1}");
const u8 gText_FloorsCleared[] = _("Floors cleared: {STR_VAR_1}");
@@ -965,7 +965,7 @@ const u8 gJPText_Player[] = _("プレイヤー"); // Unused
const u8 gJPText_Sama[] = _("さま"); // Unused
const u8 gText_DexHoenn[] = _("HOENN");
const u8 gText_DexNational[] = _("NATIONAL");
-const u8 gText_PokedexDiploma[] = _("PLAYER: {CLEAR 0x10}{COLOR RED}{SHADOW LIGHT_RED}{PLAYER}{COLOR DARK_GRAY}{SHADOW LIGHT_GRAY}\n\nThis document certifies\nthat you have successfully\ncompleted your\n{STR_VAR_1} POKéDEX.\n\n{CLEAR_TO 0x42}{COLOR RED}{SHADOW LIGHT_RED}GAME FREAK");
+const u8 gText_PokedexDiploma[] = _("PLAYER: {CLEAR 16}{COLOR RED}{SHADOW LIGHT_RED}{PLAYER}{COLOR DARK_GRAY}{SHADOW LIGHT_GRAY}\n\nThis document certifies\nthat you have successfully\ncompleted your\n{STR_VAR_1} POKéDEX.\n\n{CLEAR_TO 66}{COLOR RED}{SHADOW LIGHT_RED}GAME FREAK");
const u8 gJPText_GameFreak[] = _("{COLOR RED}{SHADOW LIGHT_RED}ゲ-ムフリ-ク"); // Unused
const u8 gText_DiplomaEmpty[] = _("{COLOR RED}{SHADOW LIGHT_RED}"); // Unused
const u8 gText_Hoenn[] = _("HOENN");
@@ -1098,7 +1098,7 @@ ALIGNED(4) const u8 gText_PickOKExit[] = _("{DPAD_UPDOWN}PICK {A_BUTTON}OK {B_BU
ALIGNED(4) const u8 gText_PickOKCancel[] = _("{DPAD_UPDOWN}PICK {A_BUTTON}OK {B_BUTTON}CANCEL");
const u8 gText_PlayersBattleResults[] = _("{PLAYER}'s BATTLE RESULTS");
const u8 gText_TotalRecordWLD[] = _("TOTAL RECORD W:{STR_VAR_1} L:{STR_VAR_2} D:{STR_VAR_3}");
-const u8 gText_WinLoseDraw[] = _("{CLEAR_TO 0x53}WIN{CLEAR_TO 0x80}LOSE{CLEAR_TO 0xB0}DRAW");
+const u8 gText_WinLoseDraw[] = _("{CLEAR_TO 83}WIN{CLEAR_TO 128}LOSE{CLEAR_TO 176}DRAW");
const u8 gText_CommunicationStandby5[] = _("Communication standby…");
const u8 gDaycareText_GetAlongVeryWell[] = _("The two seem to get along\nvery well.");
const u8 gDaycareText_GetAlong[] = _("The two seem to get along.");
diff --git a/src/text.c b/src/text.c
index 2fd9c9f84d..132490f415 100644
--- a/src/text.c
+++ b/src/text.c
@@ -385,7 +385,7 @@ u16 AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 *str, u8 x, u8
return AddTextPrinter(&printerTemplate, speed, callback);
}
-u16 AddSpriteTextPrinterParametrerized(u8 spriteId, u8 fontId, const u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16))
+u16 AddSpriteTextPrinterParameterized(u8 spriteId, u8 fontId, const u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16))
{
struct TextPrinterTemplate printerTemplate;
diff --git a/src/window.c b/src/window.c
index 51b473e89c..885e802ec0 100644
--- a/src/window.c
+++ b/src/window.c
@@ -20,7 +20,42 @@ static void DummyWindowBgTilemap(void)
}
-bool32 InitWindows(const struct WindowTemplate *templates)
+bool32 InitWindowsChecked(const struct WindowTemplate *templates, s32 staticSize)
+{
+ bool32 terminated;
+
+ if (staticSize >= 0)
+ {
+ terminated = templates[(staticSize / sizeof(*templates)) - 1].bg == 0xFF;
+ }
+ else
+ {
+ terminated = FALSE;
+ for (u32 i = 0; i < WINDOWS_MAX; i++)
+ {
+ if (templates[i].bg == 0xFF)
+ {
+ terminated = TRUE;
+ break;
+ }
+ else if (0x04 <= templates[i].bg && templates[i].bg < 0xFF)
+ {
+ break;
+ }
+ }
+ }
+
+ assertf(terminated, "%p is missing DUMMY_WIN_TEMPLATE terminator", templates)
+ {
+ return FALSE;
+ }
+
+ bool32 initialized = InitWindowsUnchecked(templates);
+ assertf(initialized, "Could not initialize windows");
+ return initialized;
+}
+
+bool32 InitWindowsUnchecked(const struct WindowTemplate *templates)
{
int i;
void *bgTilemapBuffer;
@@ -49,7 +84,7 @@ bool32 InitWindows(const struct WindowTemplate *templates)
{
if (gWindowTileAutoAllocEnabled == TRUE)
{
- allocatedBaseBlock = BgTileAllocOp(bgLayer, 0, templates[i].width * templates[i].height, 0);
+ allocatedBaseBlock = BgTileAllocOpUnchecked(bgLayer, 0, templates[i].width * templates[i].height, 0);
if (allocatedBaseBlock == -1)
return FALSE;
}
@@ -60,7 +95,7 @@ bool32 InitWindows(const struct WindowTemplate *templates)
if (attrib != 0xFFFF)
{
- allocatedTilemapBuffer = AllocZeroed(attrib);
+ allocatedTilemapBuffer = AllocZeroedUnchecked(attrib);
if (allocatedTilemapBuffer == NULL)
{
@@ -76,7 +111,7 @@ bool32 InitWindows(const struct WindowTemplate *templates)
}
}
- allocatedTilemapBuffer = AllocZeroed((u16)(32 * (templates[i].width * templates[i].height)));
+ allocatedTilemapBuffer = AllocZeroedUnchecked((u16)(32 * (templates[i].width * templates[i].height)));
if (allocatedTilemapBuffer == NULL)
{
@@ -125,7 +160,7 @@ u32 AddWindow(const struct WindowTemplate *template)
if (gWindowTileAutoAllocEnabled == TRUE)
{
- allocatedBaseBlock = BgTileAllocOp(bgLayer, 0, template->width * template->height, 0);
+ allocatedBaseBlock = BgTileAllocOpUnchecked(bgLayer, 0, template->width * template->height, 0);
if (allocatedBaseBlock == -1)
return WINDOW_NONE;
diff --git a/test/battle/ability/delta_stream.c b/test/battle/ability/delta_stream.c
index 0ea7429ff4..816317459a 100644
--- a/test/battle/ability/delta_stream.c
+++ b/test/battle/ability/delta_stream.c
@@ -8,18 +8,18 @@
DOUBLE_BATTLE_TEST("Delta Stream doesn't activate if there's already strong winds")
{
GIVEN {
+ PLAYER(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE); }
PLAYER(SPECIES_WOBBUFFET);
- PLAYER(SPECIES_WOBBUFFET);
- PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
- OPPONENT(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
+ OPPONENT(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
- TURN { SWITCH(playerLeft, 2); }
+ TURN {
+ MOVE(opponentLeft, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA);
+ MOVE(playerLeft, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA);
+ }
} SCENE {
ABILITY_POPUP(opponentLeft, ABILITY_DELTA_STREAM);
MESSAGE("Mysterious strong winds are protecting Flying-type Pokémon!");
- SWITCH_OUT_MESSAGE("Wobbuffet");
- SEND_IN_MESSAGE("Rayquaza");
NONE_OF {
ABILITY_POPUP(playerLeft, ABILITY_DELTA_STREAM);
MESSAGE("Mysterious strong winds are protecting Flying-type Pokémon!");
@@ -30,18 +30,21 @@ DOUBLE_BATTLE_TEST("Delta Stream doesn't activate if there's already strong wind
DOUBLE_BATTLE_TEST("Strong winds continue as long as there's a Pokémon with Delta Stream on the field")
{
GIVEN {
- PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); HP(1); }
- PLAYER(SPECIES_WOBBUFFET);
- PLAYER(SPECIES_WOBBUFFET);
- OPPONENT(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
- OPPONENT(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_RAYQUAZA) { HP(1); Speed(5); Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE); }
+ PLAYER(SPECIES_WOBBUFFET) { Speed(4); }
+ PLAYER(SPECIES_WOBBUFFET) { Speed(3); }
+ OPPONENT(SPECIES_RAYQUAZA) { Speed(2); Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE, MOVE_SCRATCH); }
+ OPPONENT(SPECIES_WOBBUFFET) { Speed(1); }
} WHEN {
+ TURN {
+ MOVE(playerLeft, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA);
+ MOVE(opponentLeft, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA);
+ }
TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerLeft); SEND_OUT(playerLeft, 2); }
} SCENE {
+ ABILITY_POPUP(playerLeft, ABILITY_DELTA_STREAM);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft);
- HP_BAR(playerLeft, hp: 0);
- MESSAGE("Rayquaza fainted!");
- SEND_IN_MESSAGE("Wobbuffet");
+ HP_BAR(playerLeft);
NOT MESSAGE("The mysterious strong winds have dissipated!");
} THEN {
EXPECT(gBattleWeather & B_WEATHER_STRONG_WINDS);
diff --git a/test/battle/ability/desolate_land.c b/test/battle/ability/desolate_land.c
index e45197aea4..6a35847b1a 100644
--- a/test/battle/ability/desolate_land.c
+++ b/test/battle/ability/desolate_land.c
@@ -128,7 +128,8 @@ SINGLE_BATTLE_TEST("Desolate Land blocks weather-setting moves")
SINGLE_BATTLE_TEST("Desolate Land prevents other weather abilities")
{
- enum Ability ability; u16 species;
+ enum Ability ability;
+ enum Species species;
PARAMETRIZE { ability = ABILITY_DROUGHT; species = SPECIES_NINETALES; }
PARAMETRIZE { ability = ABILITY_DRIZZLE; species = SPECIES_POLITOED; }
PARAMETRIZE { ability = ABILITY_SAND_STREAM; species = SPECIES_HIPPOWDON; }
@@ -151,10 +152,9 @@ SINGLE_BATTLE_TEST("Desolate Land can be replaced by Delta Stream")
{
GIVEN {
PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); }
- OPPONENT(SPECIES_WOBBUFFET);
- OPPONENT(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
+ OPPONENT(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE); }
} WHEN {
- TURN { SWITCH(opponent, 1); }
+ TURN { MOVE(opponent, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_DELTA_STREAM);
MESSAGE("Mysterious strong winds are protecting Flying-type Pokémon!");
diff --git a/test/battle/ability/flash_fire.c b/test/battle/ability/flash_fire.c
index 4cdcec9973..3b7d7bbb0b 100644
--- a/test/battle/ability/flash_fire.c
+++ b/test/battle/ability/flash_fire.c
@@ -16,9 +16,11 @@ SINGLE_BATTLE_TEST("Flash Fire boosts fire type moves by 50% but no subsequent i
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
HP_BAR(opponent, captureDamage: &damage[0]);
ABILITY_POPUP(player, ABILITY_FLASH_FIRE);
+ MESSAGE("The power of Heatran's Fire-type moves rose!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
HP_BAR(opponent, captureDamage: &damage[1]);
ABILITY_POPUP(player, ABILITY_FLASH_FIRE);
+ MESSAGE("Heatran made it ineffective!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
HP_BAR(opponent, captureDamage: &damage[2]);
} THEN {
diff --git a/test/battle/ability/insomnia.c b/test/battle/ability/insomnia.c
index c95b294907..f012c90ec1 100644
--- a/test/battle/ability/insomnia.c
+++ b/test/battle/ability/insomnia.c
@@ -12,6 +12,7 @@ SINGLE_BATTLE_TEST("Insomnia prevents sleep")
TURN { MOVE(opponent, MOVE_SPORE); }
} SCENE {
ABILITY_POPUP(player, ABILITY_INSOMNIA);
+ MESSAGE("Drowzee made it ineffective!");
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponent);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player);
diff --git a/test/battle/ability/primordial_sea.c b/test/battle/ability/primordial_sea.c
index b6000718cc..9cd37096dc 100644
--- a/test/battle/ability/primordial_sea.c
+++ b/test/battle/ability/primordial_sea.c
@@ -94,7 +94,8 @@ SINGLE_BATTLE_TEST("Primordial Sea blocks weather-setting moves")
SINGLE_BATTLE_TEST("Primordial Sea prevents other weather abilities")
{
- enum Ability ability; u16 species;
+ enum Ability ability;
+ enum Species species;
PARAMETRIZE { ability = ABILITY_DROUGHT; species = SPECIES_NINETALES; }
PARAMETRIZE { ability = ABILITY_DRIZZLE; species = SPECIES_POLITOED; }
PARAMETRIZE { ability = ABILITY_SAND_STREAM; species = SPECIES_HIPPOWDON; }
@@ -117,10 +118,9 @@ SINGLE_BATTLE_TEST("Primordial Sea can be replaced by Delta Stream")
{
GIVEN {
PLAYER(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); }
- OPPONENT(SPECIES_WOBBUFFET);
- OPPONENT(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
+ OPPONENT(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE); }
} WHEN {
- TURN { SWITCH(opponent, 1); }
+ TURN { MOVE(opponent, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_DELTA_STREAM);
MESSAGE("Mysterious strong winds are protecting Flying-type Pokémon!");
diff --git a/test/battle/ability/shadow_tag.c b/test/battle/ability/shadow_tag.c
index f00696d8b7..93b930ecb3 100644
--- a/test/battle/ability/shadow_tag.c
+++ b/test/battle/ability/shadow_tag.c
@@ -2,3 +2,18 @@
#include "test/battle.h"
TO_DO_BATTLE_TEST("TODO: Write Shadow Tag (Ability) test titles")
+
+WILD_BATTLE_TEST("Shadow Tag prevents wild Pokemon from fleeing with Teleport")
+{
+ GIVEN {
+ ASSUME(GetMoveEffect(MOVE_TELEPORT) == EFFECT_TELEPORT);
+ PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_SHADOW_TAG); }
+ OPPONENT(SPECIES_ABRA);
+ } WHEN {
+ TURN { MOVE(opponent, MOVE_TELEPORT); }
+ } SCENE {
+ NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TELEPORT, opponent);
+ ABILITY_POPUP(player, ABILITY_SHADOW_TAG);
+ MESSAGE("Wobbuffet made it ineffective!");
+ }
+}
diff --git a/test/battle/ability/vital_spirit.c b/test/battle/ability/vital_spirit.c
index 2539df2334..85fcbff613 100644
--- a/test/battle/ability/vital_spirit.c
+++ b/test/battle/ability/vital_spirit.c
@@ -2,3 +2,23 @@
#include "test/battle.h"
TO_DO_BATTLE_TEST("TODO: Write Vital Spirit (Ability) test titles")
+
+SINGLE_BATTLE_TEST("Vital Spirit prevents sleep")
+{
+ GIVEN {
+ ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_NON_VOLATILE_STATUS);
+ ASSUME(GetMoveNonVolatileStatus(MOVE_SPORE) == MOVE_EFFECT_SLEEP);
+ PLAYER(SPECIES_MANKEY) { Ability(ABILITY_VITAL_SPIRIT); }
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { MOVE(opponent, MOVE_SPORE); }
+ } SCENE {
+ ABILITY_POPUP(player, ABILITY_VITAL_SPIRIT);
+ MESSAGE("Mankey made it ineffective!");
+ NONE_OF {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponent);
+ ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player);
+ STATUS_ICON(player, sleep: TRUE);
+ }
+ }
+}
diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c
index c9437b99b9..8b783b2985 100644
--- a/test/battle/ai/ai.c
+++ b/test/battle/ai/ai.c
@@ -1355,3 +1355,93 @@ AI_DOUBLE_BATTLE_TEST("Bolt Beak damage will be correctly seen by AI (doubles)")
}
}
}
+
+AI_MULTI_BATTLE_TEST("AI does not target itself with selected moves in doubles (TARGET_SELECTED)")
+{
+ PASSES_RANDOMLY(100, 100, RNG_AI_SCORE_TIE_DOUBLES_TARGET);
+
+ GIVEN {
+ ASSUME(GetMoveTarget(MOVE_FLAMETHROWER) == TARGET_SELECTED);
+ AI_FLAGS(0);
+ TIE_BREAK_TARGET(TARGET_TIE_CHOSEN, i % 3);
+ PLAYER(SPECIES_TURTONATOR) { Speed(4); }
+ PARTNER(SPECIES_TURTONATOR) { Speed(2); Moves(MOVE_FLAMETHROWER); }
+ OPPONENT_A(SPECIES_TURTONATOR) { Speed(3); Moves(MOVE_FLAMETHROWER); }
+ OPPONENT_B(SPECIES_TURTONATOR) { Speed(1); Moves(MOVE_FLAMETHROWER); }
+ } WHEN {
+ TURN {
+ EXPECT_MOVE(opponentLeft, MOVE_FLAMETHROWER);
+ EXPECT_MOVE(playerRight, MOVE_FLAMETHROWER);
+ EXPECT_MOVE(opponentRight, MOVE_FLAMETHROWER);
+ }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_FLAMETHROWER, opponentLeft);
+ NOT HP_BAR(opponentLeft);
+
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_FLAMETHROWER, playerRight);
+ NOT HP_BAR(playerRight);
+
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_FLAMETHROWER, opponentRight);
+ NOT HP_BAR(opponentRight);
+ }
+}
+
+AI_MULTI_BATTLE_TEST("AI does not target itself with selected moves in doubles (TARGET_FOES_AND_ALLY)")
+{
+ PASSES_RANDOMLY(100, 100, RNG_AI_SCORE_TIE_DOUBLES_TARGET);
+
+ GIVEN {
+ ASSUME(GetMoveTarget(MOVE_LAVA_PLUME) == TARGET_FOES_AND_ALLY);
+ AI_FLAGS(0);
+ TIE_BREAK_TARGET(TARGET_TIE_CHOSEN, i % 3);
+ PLAYER(SPECIES_TURTONATOR) { Speed(4); }
+ PARTNER(SPECIES_TURTONATOR) { Speed(2); Moves(MOVE_LAVA_PLUME); }
+ OPPONENT_A(SPECIES_TURTONATOR) { Speed(3); Moves(MOVE_LAVA_PLUME); }
+ OPPONENT_B(SPECIES_TURTONATOR) { Speed(1); Moves(MOVE_LAVA_PLUME); }
+ } WHEN {
+ TURN {
+ EXPECT_MOVE(opponentLeft, MOVE_LAVA_PLUME);
+ EXPECT_MOVE(playerRight, MOVE_LAVA_PLUME);
+ EXPECT_MOVE(opponentRight, MOVE_LAVA_PLUME);
+ }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_LAVA_PLUME, opponentLeft);
+ NOT HP_BAR(opponentLeft);
+
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_LAVA_PLUME, playerRight);
+ NOT HP_BAR(playerRight);
+
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_LAVA_PLUME, opponentRight);
+ NOT HP_BAR(opponentRight);
+ }
+}
+
+AI_MULTI_BATTLE_TEST("AI does not target itself with selected moves in doubles (TARGET_BOTH)")
+{
+ PASSES_RANDOMLY(100, 100, RNG_AI_SCORE_TIE_DOUBLES_TARGET);
+
+ GIVEN {
+ ASSUME(GetMoveTarget(MOVE_HEAT_WAVE) == TARGET_BOTH);
+ AI_FLAGS(0);
+ TIE_BREAK_TARGET(TARGET_TIE_CHOSEN, i % 3);
+ PLAYER(SPECIES_TURTONATOR) { Speed(4); }
+ PARTNER(SPECIES_TURTONATOR) { Speed(2); Moves(MOVE_HEAT_WAVE); }
+ OPPONENT_A(SPECIES_TURTONATOR) { Speed(3); Moves(MOVE_HEAT_WAVE); }
+ OPPONENT_B(SPECIES_TURTONATOR) { Speed(1); Moves(MOVE_HEAT_WAVE); }
+ } WHEN {
+ TURN {
+ EXPECT_MOVE(opponentLeft, MOVE_HEAT_WAVE);
+ EXPECT_MOVE(playerRight, MOVE_HEAT_WAVE);
+ EXPECT_MOVE(opponentRight, MOVE_HEAT_WAVE);
+ }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_HEAT_WAVE, opponentLeft);
+ NOT HP_BAR(opponentLeft);
+
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_HEAT_WAVE, playerRight);
+ NOT HP_BAR(playerRight);
+
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_HEAT_WAVE, opponentRight);
+ NOT HP_BAR(opponentRight);
+ }
+}
diff --git a/test/battle/move_effect/acupressure.c b/test/battle/move_effect/acupressure.c
index 6eaade94ae..b0d7b61e19 100644
--- a/test/battle/move_effect/acupressure.c
+++ b/test/battle/move_effect/acupressure.c
@@ -1,13 +1,6 @@
#include "global.h"
#include "test/battle.h"
-TO_DO_BATTLE_TEST("Acupressure increases one of its stats by 2 stages at random");
-TO_DO_BATTLE_TEST("Acupressure doesn't try to increase a stat that has been maximized");
-TO_DO_BATTLE_TEST("Acupressure fails on the user if all of its stats are maximized");
-TO_DO_BATTLE_TEST("Acupressure fails on the ally if all of its stats are maximized");
-TO_DO_BATTLE_TEST("Acupressure works on the user if it's behind a Substitute (Gen5+)");
-TO_DO_BATTLE_TEST("Acupressure fails on its ally if it's behind a Substitute");
-
DOUBLE_BATTLE_TEST("Acupressure fails on the user if it targeted its ally but switched positions via Ally Switch")
{
GIVEN {
@@ -50,8 +43,112 @@ DOUBLE_BATTLE_TEST("Acupressure works on the ally if it targeted itself but swit
}
}
-TO_DO_BATTLE_TEST("Acupressure works on the user if its side is protected by Crafty Shield");
-TO_DO_BATTLE_TEST("Acupressure fails on the ally if its side is protected by Crafty Shield");
+DOUBLE_BATTLE_TEST("Acupressure will not try to raise partners stat if it already increased its own")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WYNAUT);
+ } WHEN {
+ TURN { MOVE(opponentRight, MOVE_ACUPRESSURE, target: opponentRight); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_ACUPRESSURE, opponentRight);
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
+ NONE_OF {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_ACUPRESSURE, opponentLeft);
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
+ }
+ }
+}
+
+DOUBLE_BATTLE_TEST("Acupressure works on the user if its side is protected by Crafty Shield")
+{
+ GIVEN {
+ ASSUME(GetMoveEffect(MOVE_PROTECT) == EFFECT_PROTECT);
+ ASSUME(GetMoveEffect(MOVE_CRAFTY_SHIELD) == EFFECT_PROTECT);
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WYNAUT);
+ } WHEN {
+ TURN {
+ MOVE(opponentLeft, MOVE_CRAFTY_SHIELD);
+ MOVE(opponentRight, MOVE_ACUPRESSURE, target: opponentRight);
+ }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_CRAFTY_SHIELD, opponentLeft);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_ACUPRESSURE, opponentRight);
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
+ }
+}
+
+DOUBLE_BATTLE_TEST("Acupressure works on the ally if its side is protected by Crafty Shield")
+{
+ GIVEN {
+ ASSUME(GetMoveEffect(MOVE_PROTECT) == EFFECT_PROTECT);
+ ASSUME(GetMoveEffect(MOVE_CRAFTY_SHIELD) == EFFECT_PROTECT);
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WYNAUT);
+ } WHEN {
+ TURN {
+ MOVE(opponentLeft, MOVE_CRAFTY_SHIELD);
+ MOVE(opponentRight, MOVE_ACUPRESSURE, target: opponentLeft);
+ }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_CRAFTY_SHIELD, opponentLeft);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_ACUPRESSURE, opponentRight);
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
+ }
+}
+
+DOUBLE_BATTLE_TEST("Acupressure works on the user if it's behind a Substitute (Gen5+)")
+{
+ GIVEN {
+ ASSUME(GetMoveEffect(MOVE_SUBSTITUTE) == EFFECT_SUBSTITUTE);
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WYNAUT);
+ } WHEN {
+ TURN { MOVE(opponentRight, MOVE_SUBSTITUTE); }
+ TURN { MOVE(opponentRight, MOVE_ACUPRESSURE, target: opponentRight); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, opponentRight);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_ACUPRESSURE, opponentRight);
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
+ }
+}
+
+DOUBLE_BATTLE_TEST("Acupressure fails on its ally if it's behind a Substitute")
+{
+ GIVEN {
+ ASSUME(GetMoveEffect(MOVE_SUBSTITUTE) == EFFECT_SUBSTITUTE);
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WYNAUT);
+ } WHEN {
+ TURN {
+ MOVE(opponentLeft, MOVE_SUBSTITUTE);
+ MOVE(opponentRight, MOVE_ACUPRESSURE, target: opponentLeft);
+ }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, opponentLeft);
+ NONE_OF {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_ACUPRESSURE, opponentRight);
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
+ }
+ }
+}
+
+
+TO_DO_BATTLE_TEST("Acupressure fails on the user if all of its stats are maximized");
+TO_DO_BATTLE_TEST("Acupressure fails on the ally if all of its stats are maximized");
+TO_DO_BATTLE_TEST("Acupressure doesn't try to increase a stat that has been maximized");
+TO_DO_BATTLE_TEST("Acupressure increases one of its stats by 2 stages at random");
// Triple Battles required to test
//TO_DO_BATTLE_TEST("Acupressure works on the ally if the user targeted itself but switched positions via Triple Battle shift before execution");
diff --git a/test/battle/move_effect/beat_up.c b/test/battle/move_effect/beat_up.c
index 8f8c716fe5..1f8f15b7a2 100644
--- a/test/battle/move_effect/beat_up.c
+++ b/test/battle/move_effect/beat_up.c
@@ -200,7 +200,7 @@ SINGLE_BATTLE_TEST("Beat Up lists each party member's name")
}
}
-SINGLE_BATTLE_TEST("Beat Up's damage is typeless", s16 damage)
+SINGLE_BATTLE_TEST("Beat Up's damage is typeless (up to Gen4)", s16 damage)
{
u16 defender = SPECIES_WOBBUFFET;
u16 type1, type2;
@@ -225,7 +225,7 @@ SINGLE_BATTLE_TEST("Beat Up's damage is typeless", s16 damage)
PARAMETRIZE { defender = SPECIES_SYLVEON; } // Fairy
GIVEN {
- WITH_CONFIG(B_BEAT_UP, GEN_3);
+ WITH_CONFIG(B_BEAT_UP, GEN_4);
type1 = GetSpeciesType(defender, 0);
type2 = GetSpeciesType(defender, 1);
ASSUME(type2 == type1 || type2 == TYPE_MYSTERY); // Ensure monotype targets
@@ -235,12 +235,8 @@ SINGLE_BATTLE_TEST("Beat Up's damage is typeless", s16 damage)
TURN { MOVE(player, MOVE_BEAT_UP); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player);
+ EFFECTIVENESS_SE(opponent, SE_EFFECTIVE);
HP_BAR(opponent, captureDamage: &results[i].damage);
- NONE_OF {
- MESSAGE("It's super effective!");
- MESSAGE("It's not very effective...");
- MESSAGE("It doesn't affect");
- }
} THEN {
EXPECT_GT(results[i].damage, 0);
}
diff --git a/test/battle/move_effect/roost.c b/test/battle/move_effect/roost.c
index f42ebad3ca..a1e674ac50 100644
--- a/test/battle/move_effect/roost.c
+++ b/test/battle/move_effect/roost.c
@@ -255,12 +255,14 @@ DOUBLE_BATTLE_TEST("Roost suppresses the user's not-yet-aquired Flying-type this
SINGLE_BATTLE_TEST("Roost prevents a Flying-type user from being protected by Delta Stream")
{
GIVEN {
- ASSUME(GetSpeciesType(SPECIES_RAYQUAZA, 1) == TYPE_FLYING);
- PLAYER(SPECIES_RAYQUAZA) { HP(1); Ability(ABILITY_DELTA_STREAM); }
+ ASSUME(GetSpeciesType(SPECIES_RAYQUAZA_MEGA, 1) == TYPE_FLYING);
+ PLAYER(SPECIES_RAYQUAZA) { HP(1); Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE, MOVE_ROOST); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
+ TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
TURN { MOVE(player, MOVE_ROOST); MOVE(opponent, MOVE_ICE_BEAM); }
} SCENE {
+ ABILITY_POPUP(player, ABILITY_DELTA_STREAM);
MESSAGE("Rayquaza used Roost!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROOST, player);
MESSAGE("Rayquaza's HP was restored.");
diff --git a/test/battle/move_effect/weather_ball.c b/test/battle/move_effect/weather_ball.c
index 912a4515e8..70cd269f4f 100644
--- a/test/battle/move_effect/weather_ball.c
+++ b/test/battle/move_effect/weather_ball.c
@@ -97,6 +97,45 @@ SINGLE_BATTLE_TEST("Weather Ball doubles its power and turns to an Ice-type move
}
}
+DOUBLE_BATTLE_TEST("Weather Ball doesn't double its power and stays a Normal-type move in strong winds", s16 damage)
+{
+ bool32 strongWinds;
+ enum Species species;
+ PARAMETRIZE { strongWinds = FALSE; species = SPECIES_WOBBUFFET; }
+ PARAMETRIZE { strongWinds = TRUE; species = SPECIES_WOBBUFFET; }
+ PARAMETRIZE { strongWinds = TRUE; species = SPECIES_GASTLY; }
+
+ GIVEN {
+ ASSUME(GetMoveType(MOVE_WEATHER_BALL) == TYPE_NORMAL);
+ ASSUME(GetSpeciesType(SPECIES_GASTLY, 0) == TYPE_GHOST);
+ if (strongWinds)
+ PLAYER(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE); }
+ else
+ PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_AIR_LOCK); }
+ PLAYER(SPECIES_WOBBUFFET);
+ OPPONENT(species);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ if (strongWinds)
+ TURN { MOVE(playerLeft, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
+ TURN { MOVE(playerRight, MOVE_WEATHER_BALL, target: opponentLeft); }
+ } SCENE {
+ if (strongWinds)
+ ABILITY_POPUP(playerLeft, ABILITY_DELTA_STREAM);
+ if (species == SPECIES_GASTLY) {
+ NONE_OF {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_WEATHER_BALL, playerRight);
+ HP_BAR(opponentLeft);
+ }
+ } else {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_WEATHER_BALL, playerRight);
+ HP_BAR(opponentLeft, captureDamage: &results[i].damage);
+ }
+ } FINALLY {
+ EXPECT_EQ(results[0].damage, results[1].damage);
+ }
+}
+
SINGLE_BATTLE_TEST("Weather Ball doesn't double its power in Sunlight or Rain if Cloud Nine/Air Lock is on the field", s16 damage)
{
enum Move setupMove;
diff --git a/test/battle/stat_change_leaks.c b/test/battle/stat_change_leaks.c
new file mode 100644
index 0000000000..51ff94ba08
--- /dev/null
+++ b/test/battle/stat_change_leaks.c
@@ -0,0 +1,55 @@
+#include "global.h"
+#include "test/battle.h"
+
+AI_SINGLE_BATTLE_TEST("Type-absorbing ability checks don't queue stat increases")
+{
+ enum Ability ability;
+ enum Move absorbedMove;
+ enum Species species;
+ enum Stat boostedStat;
+
+ PARAMETRIZE { species = SPECIES_TATSUGIRI; ability = ABILITY_STORM_DRAIN; absorbedMove = MOVE_WATER_GUN; boostedStat = STAT_SPATK; }
+ PARAMETRIZE { species = SPECIES_RAICHU; ability = ABILITY_LIGHTNING_ROD; absorbedMove = MOVE_THUNDERBOLT; boostedStat = STAT_SPATK; }
+ PARAMETRIZE { species = SPECIES_MARILL; ability = ABILITY_SAP_SIPPER; absorbedMove = MOVE_VINE_WHIP; boostedStat = STAT_ATK; }
+
+ GIVEN {
+ ASSUME(GetMoveType(MOVE_WATER_GUN) == TYPE_WATER);
+ ASSUME(GetMoveType(MOVE_THUNDERBOLT) == TYPE_ELECTRIC);
+ ASSUME(GetMoveType(MOVE_VINE_WHIP) == TYPE_GRASS);
+ ASSUME_STAT_CHANGE(MOVE_GROWL, attack: -1);
+ AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT);
+ PLAYER(species) { Ability(ability); Speed(1); }
+ OPPONENT(SPECIES_WOBBUFFET) { Moves(absorbedMove, MOVE_GROWL); Speed(2); }
+ } WHEN {
+ TURN { EXPECT_MOVE(opponent, MOVE_GROWL); }
+ } THEN {
+ EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1);
+ if (boostedStat != STAT_ATK)
+ EXPECT_EQ(player->statStages[boostedStat], DEFAULT_STAT_STAGE);
+ }
+}
+
+AI_SINGLE_BATTLE_TEST("Type-absorbing abilities only increase a stat once after AI checks")
+{
+ enum Ability ability;
+ enum Move absorbedMove;
+ enum Species species;
+ enum Stat boostedStat;
+
+ PARAMETRIZE { species = SPECIES_TATSUGIRI; ability = ABILITY_STORM_DRAIN; absorbedMove = MOVE_WATER_GUN; boostedStat = STAT_SPATK; }
+ PARAMETRIZE { species = SPECIES_RAICHU; ability = ABILITY_LIGHTNING_ROD; absorbedMove = MOVE_THUNDERBOLT; boostedStat = STAT_SPATK; }
+ PARAMETRIZE { species = SPECIES_MARILL; ability = ABILITY_SAP_SIPPER; absorbedMove = MOVE_VINE_WHIP; boostedStat = STAT_ATK; }
+
+ GIVEN {
+ ASSUME(GetMoveType(MOVE_WATER_GUN) == TYPE_WATER);
+ ASSUME(GetMoveType(MOVE_THUNDERBOLT) == TYPE_ELECTRIC);
+ ASSUME(GetMoveType(MOVE_VINE_WHIP) == TYPE_GRASS);
+ AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT);
+ PLAYER(species) { Ability(ability); Speed(1); }
+ OPPONENT(SPECIES_WOBBUFFET) { Moves(absorbedMove); Speed(2); }
+ } WHEN {
+ TURN { EXPECT_MOVE(opponent, absorbedMove); }
+ } THEN {
+ EXPECT_EQ(player->statStages[boostedStat], DEFAULT_STAT_STAGE + 1);
+ }
+}
diff --git a/test/battle/trainer_slides.c b/test/battle/trainer_slides.c
index 12e374ad40..fd78339a4c 100644
--- a/test/battle/trainer_slides.c
+++ b/test/battle/trainer_slides.c
@@ -1483,9 +1483,10 @@ AI_MULTI_BATTLE_TEST("Trainer Slide: Multi: Attacker Z Move")
OPPONENT_B(SPECIES_WOBBUFFET) { Speed(1); Item(ITEM_NORMALIUM_Z); }
} WHEN {
TURN {
- EXPECT_MOVE(opponentLeft, MOVE_QUICK_ATTACK, gimmick: GIMMICK_Z_MOVE);
- MOVE(playerRight, MOVE_QUICK_ATTACK, gimmick: GIMMICK_Z_MOVE, target: opponentLeft);
- EXPECT_MOVE(opponentRight, MOVE_QUICK_ATTACK, gimmick: GIMMICK_Z_MOVE); }
+ EXPECT_MOVE(opponentLeft, MOVE_QUICK_ATTACK, gimmick: GIMMICK_Z_MOVE);
+ MOVE(playerRight, MOVE_QUICK_ATTACK, gimmick: GIMMICK_Z_MOVE, target: opponentLeft);
+ EXPECT_MOVE(opponentRight, MOVE_QUICK_ATTACK, gimmick: GIMMICK_Z_MOVE);
+ }
} SCENE {
MESSAGE("Trainer A: This message plays before the attacker activates the Z-Move gimmick.{PAUSE_UNTIL_PRESS}");
MESSAGE("The opposing Wobbuffet surrounded itself with its Z-Power!");
diff --git a/test/battle/weather/strong_winds.c b/test/battle/weather/strong_winds.c
index 3098ebd43a..d583bfc915 100644
--- a/test/battle/weather/strong_winds.c
+++ b/test/battle/weather/strong_winds.c
@@ -1,97 +1,77 @@
#include "global.h"
#include "test/battle.h"
-DOUBLE_BATTLE_TEST("Strong winds remove Flying-type weaknesses of all battlers") // Electric, Ice, Rock
+ASSUMPTIONS
+{
+ ASSUME(GetMoveType(MOVE_THUNDER_SHOCK) == TYPE_ELECTRIC);
+ ASSUME(GetMoveType(MOVE_ICE_BEAM) == TYPE_ICE);
+ ASSUME(GetMoveType(MOVE_ROCK_THROW) == TYPE_ROCK);
+ ASSUME(GetSpeciesType(SPECIES_PIDGEY, 0) == TYPE_FLYING || GetSpeciesType(SPECIES_PIDGEY, 1) == TYPE_FLYING);
+}
+
+DOUBLE_BATTLE_TEST("Strong winds remove Flying-type weaknesses of all battlers")
{
enum Move move;
- bool32 targetPlayer;
-
- PARAMETRIZE { move = MOVE_THUNDER_SHOCK; targetPlayer = TRUE; }
- PARAMETRIZE { move = MOVE_ICE_BEAM; targetPlayer = TRUE; }
- PARAMETRIZE { move = MOVE_ROCK_THROW; targetPlayer = TRUE; }
- PARAMETRIZE { move = MOVE_THUNDER_SHOCK; targetPlayer = FALSE; }
- PARAMETRIZE { move = MOVE_ICE_BEAM; targetPlayer = FALSE; }
- PARAMETRIZE { move = MOVE_ROCK_THROW; targetPlayer = FALSE; }
+ PARAMETRIZE { move = MOVE_THUNDER_SHOCK; }
+ PARAMETRIZE { move = MOVE_ICE_BEAM; }
+ PARAMETRIZE { move = MOVE_ROCK_THROW; }
GIVEN {
- ASSUME(GetMoveType(MOVE_THUNDER_SHOCK) == TYPE_ELECTRIC);
- ASSUME(GetMoveType(MOVE_ICE_BEAM) == TYPE_ICE);
- ASSUME(GetMoveType(MOVE_ROCK_THROW) == TYPE_ROCK);
- ASSUME(GetSpeciesType(SPECIES_PIDGEY, 0) == TYPE_NORMAL);
- ASSUME(GetSpeciesType(SPECIES_PIDGEY, 1) == TYPE_FLYING);
- PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
+ PLAYER(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE, move); }
PLAYER(SPECIES_PIDGEY);
OPPONENT(SPECIES_PIDGEY);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
- if (targetPlayer)
- TURN { MOVE(opponentLeft, move, target: playerRight); }
- else
- TURN { MOVE(playerRight, move, target: opponentLeft); }
- } SCENE {
- if (targetPlayer) {
- if (move == MOVE_THUNDER_SHOCK)
- MESSAGE("The opposing Pidgey used Thunder Shock!");
- else if (move == MOVE_ICE_BEAM)
- MESSAGE("The opposing Pidgey used Ice Beam!");
- else
- MESSAGE("The opposing Pidgey used Rock Throw!");
- MESSAGE("The mysterious strong winds weakened the attack!");
- ANIMATION(ANIM_TYPE_MOVE, move, opponentLeft);
- } else {
- if (move == MOVE_THUNDER_SHOCK)
- MESSAGE("Pidgey used Thunder Shock!");
- else if (move == MOVE_ICE_BEAM)
- MESSAGE("Pidgey used Ice Beam!");
- else
- MESSAGE("Pidgey used Rock Throw!");
- MESSAGE("The mysterious strong winds weakened the attack!");
- ANIMATION(ANIM_TYPE_MOVE, move, playerRight);
+ TURN { MOVE(playerLeft, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
+ TURN {
+ MOVE(playerLeft, move, target: opponentLeft);
+ MOVE(opponentRight, move, target: playerRight);
}
+ } SCENE {
+ ABILITY_POPUP(playerLeft, ABILITY_DELTA_STREAM);
+ ANIMATION(ANIM_TYPE_MOVE, move, playerLeft);
+ EFFECTIVENESS_SE(opponentLeft, SE_EFFECTIVE);
+ HP_BAR(opponentLeft);
+ ANIMATION(ANIM_TYPE_MOVE, move, opponentRight);
+ EFFECTIVENESS_SE(playerRight, SE_EFFECTIVE);
+ HP_BAR(playerRight);
}
}
-DOUBLE_BATTLE_TEST("Strong winds remove Flying-type weaknesses of all battlers - Inverse Battle", s16 damagePlayer, s16 damageOpponent) // Bug, Fighting, Grass
+DOUBLE_BATTLE_TEST("Strong winds remove Flying-type weaknesses of all battlers - Inverse Battle")
{
enum Move move;
- bool32 strongWinds;
-
- PARAMETRIZE { move = MOVE_BUG_BITE; strongWinds = FALSE; }
- PARAMETRIZE { move = MOVE_BUG_BITE; strongWinds = TRUE; }
- PARAMETRIZE { move = MOVE_KARATE_CHOP; strongWinds = FALSE; }
- PARAMETRIZE { move = MOVE_KARATE_CHOP; strongWinds = TRUE; }
- PARAMETRIZE { move = MOVE_VINE_WHIP; strongWinds = FALSE; }
- PARAMETRIZE { move = MOVE_VINE_WHIP; strongWinds = TRUE; }
+ PARAMETRIZE { move = MOVE_BUG_BITE; }
+ PARAMETRIZE { move = MOVE_KARATE_CHOP; }
+ PARAMETRIZE { move = MOVE_VINE_WHIP; }
+ PARAMETRIZE { move = MOVE_MUD_SLAP; }
GIVEN {
FLAG_SET(B_FLAG_INVERSE_BATTLE);
ASSUME(GetMoveType(MOVE_BUG_BITE) == TYPE_BUG);
ASSUME(GetMoveType(MOVE_KARATE_CHOP) == TYPE_FIGHTING);
ASSUME(GetMoveType(MOVE_VINE_WHIP) == TYPE_GRASS);
+ ASSUME(GetMoveType(MOVE_MUD_SLAP) == TYPE_GROUND);
ASSUME(GetSpeciesType(SPECIES_TORNADUS, 0) == TYPE_FLYING);
ASSUME(GetSpeciesType(SPECIES_TORNADUS, 1) == TYPE_FLYING);
- if (strongWinds)
- PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
- else
- PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE, move); }
PLAYER(SPECIES_TORNADUS);
OPPONENT(SPECIES_TORNADUS);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
+ TURN { MOVE(playerLeft, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
TURN {
- MOVE(opponentLeft, move, target: playerRight);
- MOVE(playerRight, move, target: opponentLeft);
+ MOVE(playerLeft, move, target: opponentLeft);
+ MOVE(opponentRight, move, target: playerRight);
}
} SCENE {
- HP_BAR(playerRight, captureDamage: &results[i].damagePlayer);
- HP_BAR(opponentLeft, captureDamage: &results[i].damageOpponent);
- } FINALLY {
- EXPECT_GT(results[0].damagePlayer, results[1].damagePlayer);
- EXPECT_GT(results[0].damageOpponent, results[1].damageOpponent);
- EXPECT_GT(results[2].damagePlayer, results[3].damagePlayer);
- EXPECT_GT(results[2].damageOpponent, results[3].damageOpponent);
- EXPECT_GT(results[4].damagePlayer, results[5].damagePlayer);
- EXPECT_GT(results[4].damageOpponent, results[5].damageOpponent);
+ ABILITY_POPUP(playerLeft, ABILITY_DELTA_STREAM);
+ ANIMATION(ANIM_TYPE_MOVE, move, playerLeft);
+ EFFECTIVENESS_SE(opponentLeft, SE_EFFECTIVE);
+ HP_BAR(opponentLeft);
+ ANIMATION(ANIM_TYPE_MOVE, move, opponentRight);
+ EFFECTIVENESS_SE(playerRight, SE_EFFECTIVE);
+ HP_BAR(playerRight);
}
}
@@ -99,16 +79,13 @@ SINGLE_BATTLE_TEST("Strong winds prevent Weakness Policy from activating on Flyi
{
GIVEN {
ASSUME(GetItemHoldEffect(ITEM_WEAKNESS_POLICY) == HOLD_EFFECT_WEAKNESS_POLICY);
- ASSUME(GetMoveType(MOVE_THUNDER_SHOCK) == TYPE_ELECTRIC);
- ASSUME(GetSpeciesType(SPECIES_PIDGEY, 0) == TYPE_NORMAL);
- ASSUME(GetSpeciesType(SPECIES_PIDGEY, 1) == TYPE_FLYING);
- PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); Moves(MOVE_THUNDER_SHOCK); }
+ PLAYER(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE, MOVE_THUNDER_SHOCK); }
OPPONENT(SPECIES_PIDGEY) { Item(ITEM_WEAKNESS_POLICY); }
} WHEN {
+ TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
TURN { MOVE(player, MOVE_THUNDER_SHOCK); }
} SCENE {
- MESSAGE("Rayquaza used Thunder Shock!");
- MESSAGE("The mysterious strong winds weakened the attack!");
+ ABILITY_POPUP(player, ABILITY_DELTA_STREAM);
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_SHOCK, player);
HP_BAR(opponent);
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
@@ -118,35 +95,36 @@ SINGLE_BATTLE_TEST("Strong winds prevent Weakness Policy from activating on Flyi
SINGLE_BATTLE_TEST("Anticipation still triggers with Strong Winds active")
{
GIVEN {
- ASSUME(GetMoveType(MOVE_THUNDER_SHOCK) == TYPE_ELECTRIC);
- ASSUME(GetSpeciesType(SPECIES_PIDGEY, 0) == TYPE_NORMAL);
- ASSUME(GetSpeciesType(SPECIES_PIDGEY, 1) == TYPE_FLYING);
- PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); Moves(MOVE_THUNDER_SHOCK, MOVE_CELEBRATE); }
- OPPONENT(SPECIES_PIDGEY) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_CELEBRATE); }
+ ASSUME(GetSpeciesType(SPECIES_RAYQUAZA_MEGA, 0) == TYPE_DRAGON);
+ ASSUME(GetSpeciesType(SPECIES_RAYQUAZA_MEGA, 1) == TYPE_FLYING);
+ ASSUME(GetMoveEffect(MOVE_SKILL_SWAP) == EFFECT_SKILL_SWAP);
+ PLAYER(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE); }
+ OPPONENT(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_ROCK_THROW, MOVE_SKILL_SWAP); }
} WHEN {
- TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
+ TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); MOVE(opponent, MOVE_SKILL_SWAP); }
} SCENE {
- ABILITY_POPUP(opponent, ABILITY_ANTICIPATION);
- MESSAGE("Rayquaza used Celebrate!");
- MESSAGE("The opposing Pidgey used Celebrate!");
+ ABILITY_POPUP(player, ABILITY_DELTA_STREAM);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent);
+ ABILITY_POPUP(player, ABILITY_ANTICIPATION);
}
}
-SINGLE_BATTLE_TEST("Anticipation still triggers with Strong Winds active in Inverse Battle")
+SINGLE_BATTLE_TEST("Anticipation still triggers with Strong Winds active - Inverse Battle")
{
GIVEN {
FLAG_SET(B_FLAG_INVERSE_BATTLE);
- ASSUME(GetMoveType(MOVE_VINE_WHIP) == TYPE_GRASS);
- ASSUME(GetSpeciesType(SPECIES_TORNADUS, 0) == TYPE_FLYING);
- ASSUME(GetSpeciesType(SPECIES_TORNADUS, 1) == TYPE_FLYING);
- PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); Moves(MOVE_VINE_WHIP, MOVE_CELEBRATE); }
- OPPONENT(SPECIES_TORNADUS) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_CELEBRATE); }
+ ASSUME(GetMoveType(MOVE_BUG_BITE) == TYPE_BUG);
+ ASSUME(GetSpeciesType(SPECIES_RAYQUAZA_MEGA, 0) == TYPE_DRAGON);
+ ASSUME(GetSpeciesType(SPECIES_RAYQUAZA_MEGA, 1) == TYPE_FLYING);
+ ASSUME(GetMoveEffect(MOVE_SKILL_SWAP) == EFFECT_SKILL_SWAP);
+ PLAYER(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE); }
+ OPPONENT(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_BUG_BITE, MOVE_SKILL_SWAP); }
} WHEN {
- TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
+ TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); MOVE(opponent, MOVE_SKILL_SWAP); }
} SCENE {
- ABILITY_POPUP(opponent, ABILITY_ANTICIPATION);
- MESSAGE("Rayquaza used Celebrate!");
- MESSAGE("The opposing Tornadus used Celebrate!");
+ ABILITY_POPUP(player, ABILITY_DELTA_STREAM);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent);
+ ABILITY_POPUP(player, ABILITY_ANTICIPATION);
}
}
@@ -154,18 +132,17 @@ SINGLE_BATTLE_TEST("Strong winds don't affect Stealth Rock's damage")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_STEALTH_ROCK) == EFFECT_STEALTH_ROCK);
- ASSUME(GetSpeciesType(SPECIES_PIDGEY, 0) == TYPE_NORMAL);
- ASSUME(GetSpeciesType(SPECIES_PIDGEY, 1) == TYPE_FLYING);
PLAYER(SPECIES_WOBBUFFET);
- PLAYER(SPECIES_PIDGEY);
- OPPONENT(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
+ PLAYER(SPECIES_PIDGEY){ HP(200); MaxHP(200); }
+ OPPONENT(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE, MOVE_STEALTH_ROCK); }
} WHEN {
+ TURN { MOVE(opponent, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
TURN { MOVE(opponent, MOVE_STEALTH_ROCK); }
TURN { SWITCH(player, 1); }
} SCENE {
- s32 maxHP = GetMonData(&PLAYER_PARTY[1], MON_DATA_MAX_HP);
+ ABILITY_POPUP(opponent, ABILITY_DELTA_STREAM);
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponent);
- HP_BAR(player, damage: maxHP / 4);
+ HP_BAR(player, damage: 50);
}
}
@@ -185,11 +162,13 @@ SINGLE_BATTLE_TEST("Strong winds block weather-setting moves")
ASSUME(GetMoveWeatherType(MOVE_SANDSTORM) == BATTLE_WEATHER_SANDSTORM);
ASSUME(GetMoveWeatherType(MOVE_HAIL) == BATTLE_WEATHER_HAIL);
ASSUME(GetMoveWeatherType(MOVE_SNOWSCAPE) == BATTLE_WEATHER_SNOW);
- PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
+ PLAYER(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
+ TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
TURN { MOVE(opponent, move); }
} SCENE {
+ ABILITY_POPUP(player, ABILITY_DELTA_STREAM);
NOT ANIMATION(ANIM_TYPE_MOVE, move, opponent);
} THEN {
EXPECT(gBattleWeather & B_WEATHER_STRONG_WINDS);
@@ -206,10 +185,11 @@ SINGLE_BATTLE_TEST("Strong winds prevent other weather abilities")
PARAMETRIZE { ability = ABILITY_SNOW_WARNING; species = SPECIES_ABOMASNOW; }
GIVEN {
- PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
+ PLAYER(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(species) { Ability(ability); }
} WHEN {
+ TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
TURN { SWITCH(opponent, 1); }
} SCENE {
ABILITY_POPUP(opponent, ability);
@@ -221,10 +201,11 @@ SINGLE_BATTLE_TEST("Strong winds prevent other weather abilities")
SINGLE_BATTLE_TEST("Strong winds can be replaced by Desolate Land")
{
GIVEN {
- PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
+ PLAYER(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_GROUDON) { Item(ITEM_RED_ORB); }
} WHEN {
+ TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
TURN { SWITCH(opponent, 1); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_DESOLATE_LAND);
@@ -237,10 +218,11 @@ SINGLE_BATTLE_TEST("Strong winds can be replaced by Desolate Land")
SINGLE_BATTLE_TEST("Strong winds can be replaced by Primordial Sea")
{
GIVEN {
- PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
+ PLAYER(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); }
} WHEN {
+ TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
TURN { SWITCH(opponent, 1); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_PRIMORDIAL_SEA);
@@ -249,3 +231,24 @@ SINGLE_BATTLE_TEST("Strong winds can be replaced by Primordial Sea")
EXPECT(gBattleWeather & B_WEATHER_RAIN_PRIMAL);
}
}
+
+SINGLE_BATTLE_TEST("Strong winds don't reduce Synthesis, Morning Sun or Moonlight recovery")
+{
+ enum Move move;
+ enum BattleMoveEffects effect;
+ PARAMETRIZE { move = MOVE_SYNTHESIS; effect = EFFECT_SYNTHESIS; }
+ PARAMETRIZE { move = MOVE_MORNING_SUN; effect = EFFECT_MORNING_SUN; }
+ PARAMETRIZE { move = MOVE_MOONLIGHT; effect = EFFECT_MOONLIGHT; }
+
+ GIVEN {
+ ASSUME(GetMoveEffect(move) == effect);
+ PLAYER(SPECIES_RAYQUAZA) { HP(1); MaxHP(200); Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE, move); }
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
+ TURN { MOVE(player, move); }
+ } SCENE {
+ ABILITY_POPUP(player, ABILITY_DELTA_STREAM);
+ HP_BAR(player, damage: -100);
+ }
+}
diff --git a/test/test_runner.c b/test/test_runner.c
index 007ee6b21d..45684247f3 100644
--- a/test/test_runner.c
+++ b/test/test_runner.c
@@ -1,6 +1,6 @@
#include
-#include "fake_rtc.h"
#include "global.h"
+#include "fake_rtc.h"
#include "gpu_regs.h"
#include "load_save.h"
#include "main.h"
@@ -135,6 +135,8 @@ void TestRunner_CheckMemory(void)
if (gTestRunnerState.result == TEST_RESULT_PASS
&& !gTestRunnerState.expectLeaks)
{
+ TestFreeConfigData();
+
int i;
const struct MemBlock *head = HeapHead();
const struct MemBlock *block = head;
@@ -154,16 +156,11 @@ void TestRunner_CheckMemory(void)
const char *location = MemBlockLocation(block);
if (location)
{
- const char cmpString[] = "src/config_changes.c";
- if (strncmp(cmpString, location, sizeof(cmpString) - 1) != 0)
- {
- Test_MgbaPrintf("%s: %d bytes not freed", location, block->size);
- gTestRunnerState.result = TEST_RESULT_FAIL;
-
- if (gTestRunnerState.expectedFailState == EXPECT_FAIL_OPEN)
- gTestRunnerState.expectedFailState = EXPECT_FAIL_SUCCESS;
- break;
- }
+ Test_MgbaPrintf("%s: %d bytes not freed", location, block->size);
+ gTestRunnerState.result = TEST_RESULT_FAIL;
+
+ if (gTestRunnerState.expectedFailState == EXPECT_FAIL_OPEN)
+ gTestRunnerState.expectedFailState = EXPECT_FAIL_SUCCESS;
}
else
{
@@ -182,7 +179,7 @@ void TestRunner_CheckMemory(void)
{
if (gTasks[i].isActive)
{
- Test_MgbaPrintf(":L%s:%d - %p: task not freed", gTestRunnerState.test->filename, SourceLine(0), gTasks[i].func);
+ Test_MgbaPrintf(":L%s:%d: %p: task not freed", gTestRunnerState.test->filename, SourceLine(0), gTasks[i].func);
gTestRunnerState.result = TEST_RESULT_FAIL;
if (gTestRunnerState.expectedFailState == EXPECT_FAIL_OPEN)
@@ -254,7 +251,7 @@ top:
if (gPersistentTestRunnerState.expectCrash)
gTestRunnerState.expectedResult = TEST_RESULT_CRASH;
-
+
gTestRunnerState.expectedFailLine = 0;
gTestRunnerState.expectedFailState = NO_EXPECT_FAIL;
}
@@ -277,11 +274,21 @@ top:
gTestRunnerState.state = STATE_EXIT;
return;
}
- if (gTestRunnerState.test->runner != &gAssumptionsRunner)
+ if (gTestRunnerState.filterMode == TEST_FILTER_MODE_FILENAME_EXACT
+ && !ExactMatch(gTestRunnerArgv, gTestRunnerState.test->filename))
+ {
+ ++gTestRunnerState.test;
+ continue;
+ }
+ // Run all assumption blocks when filtering on test name
+ // because it's possible that a test in this file could
+ // match.
+ // TODO: Delay running the assumptions block until we find a
+ // test name that matches.
+ else if (gTestRunnerState.test->runner != &gAssumptionsRunner)
{
if ((gTestRunnerState.filterMode == TEST_FILTER_MODE_TEST_NAME_PREFIX && !PrefixMatch(gTestRunnerArgv, gTestRunnerState.test->name))
- || (gTestRunnerState.filterMode == TEST_FILTER_MODE_TEST_NAME_INFIX && !InfixMatch(gTestRunnerArgv, gTestRunnerState.test->name))
- || (gTestRunnerState.filterMode == TEST_FILTER_MODE_FILENAME_EXACT && !ExactMatch(gTestRunnerArgv, gTestRunnerState.test->filename)))
+ || (gTestRunnerState.filterMode == TEST_FILTER_MODE_TEST_NAME_INFIX && !InfixMatch(gTestRunnerArgv, gTestRunnerState.test->name)))
{
++gTestRunnerState.test;
continue;
@@ -326,10 +333,8 @@ top:
SeedRng(0);
SeedRng2(0);
if (gTestRunnerState.test->runner->setUp)
- {
gTestRunnerState.test->runner->setUp(gTestRunnerState.test->data);
- gTestRunnerState.tearDown = TRUE;
- }
+ gTestRunnerState.tearDown = TRUE;
// NOTE: Assumes that the compiler interns __FILE__.
if (gTestRunnerState.skipFilename == gTestRunnerState.test->filename) // Assumption fails for tests in this file.
{
@@ -349,10 +354,8 @@ top:
gTestRunnerState.state = STATE_NEXT_TEST;
if (gTestRunnerState.tearDown && gTestRunnerState.test->runner->tearDown)
- {
gTestRunnerState.test->runner->tearDown(gTestRunnerState.test->data);
- gTestRunnerState.tearDown = FALSE;
- }
+ gTestRunnerState.tearDown = FALSE;
TestRunner_CheckMemory();
@@ -724,7 +727,7 @@ static void Intr_Timer2(void)
if (gTestRunnerState.state == STATE_RUN_TEST)
gTestRunnerState.state = STATE_REPORT_RESULT;
gTestRunnerState.result = TEST_RESULT_TIMEOUT;
- Test_MgbaPrintf(":L%s:%d - TIMEOUT", gTestRunnerState.test->filename, SourceLine(0));
+ Test_MgbaPrintf(":L%s:%d: TIMEOUT", gTestRunnerState.test->filename, SourceLine(0));
ReinitCallbacks();
IRQ_LR = ((uintptr_t)JumpToAgbMainLoop & ~1) + 4;
}
@@ -760,7 +763,7 @@ void Test_ExitWithResult_(enum TestResult result, u32 stopLine, const void *retu
gTestRunnerState.test->filename, stopLine,
gTestRunnerState.expectedFailLine, stopLine);
}
-
+
ReinitCallbacks();
if (gTestRunnerState.state == STATE_REPORT_RESULT
&& gTestRunnerState.result != gTestRunnerState.expectedResult)
@@ -817,12 +820,17 @@ static s32 MgbaPutchar_(s32 i, s32 c)
return i;
}
-extern const u8 gWireless_RSEtoASCIITable[];
-
-// Bare-bones, only supports plain %s, %S, and %d.
+// Bare-bones, supports:
+// - %s, %.*s: print an ASCII string.
+// - %S, %.*S: print a GF-encoded string.
+// - %d: print a signed integer.
+// - %q: print a Q20.12 fixed-point number.
+// - %p: print a pointer (which mgba-rom-test-hydra will convert into a
+// symbol, if possible).
static s32 MgbaVPrintf_(const char *fmt, va_list va)
{
s32 i = 0;
+ s32 n;
s32 c, d;
u32 p;
const char *s;
@@ -832,6 +840,16 @@ static s32 MgbaVPrintf_(const char *fmt, va_list va)
switch ((c = *fmt++))
{
case '%':
+ if (fmt[0] == '.' && fmt[1] == '*')
+ {
+ fmt += 2;
+ n = va_arg(va, int);
+ }
+ else
+ {
+ n = INT_MAX;
+ }
+
switch (*fmt++)
{
case '%':
@@ -913,7 +931,9 @@ static s32 MgbaVPrintf_(const char *fmt, va_list va)
if (++n == 2)
{
u *= 10;
- i = MgbaPutchar_(i, '0' + ((u + UQ_4_12_ROUND) >> 12));
+ // TODO: 'min' is a hack, we should have
+ // rounded up the previous number.
+ i = MgbaPutchar_(i, min('0' + ((u + UQ_4_12_ROUND) >> 12), '9'));
break;
}
}
@@ -921,7 +941,7 @@ static s32 MgbaVPrintf_(const char *fmt, va_list va)
break;
case 's':
s = va_arg(va, const char *);
- while ((c = *s++) != '\0')
+ while ((c = *s++) != '\0' && n-- > 0)
i = MgbaPutchar_(i, c);
break;
case 'S':
@@ -935,13 +955,9 @@ static s32 MgbaVPrintf_(const char *fmt, va_list va)
}
else
{
- while ((c = *pokeS++) != EOS)
- {
- if ((c = gWireless_RSEtoASCIITable[c]) != '\0')
- i = MgbaPutchar_(i, c);
- else
- i = MgbaPutchar_(i, '?');
- }
+ extern char mini_pchar_decode(u8);
+ while ((c = *pokeS++) != EOS && n-- > 0)
+ i = MgbaPutchar_(i, mini_pchar_decode(c));
}
break;
}
diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c
index 34e9da72b9..ca24c7a4e9 100644
--- a/test/test_runner_battle.c
+++ b/test/test_runner_battle.c
@@ -290,7 +290,6 @@ static void BattleTest_SetUp(void *data)
{
const struct BattleTest *test = data;
memset(STATE, 0, sizeof(*STATE));
- TestInitConfigData();
InvokeTestFunction(test);
STATE->parameters = STATE->parametersCount;
if (STATE->parametersCount == 0 && test->resultsSize > 0)
@@ -382,6 +381,7 @@ static void BattleTest_Run(void *data)
const struct BattleTest *test = data;
memset(&DATA, 0, sizeof(DATA));
+ TestInitConfigData();
DATA.recordedBattle.rngSeed = defaultSeed;
DATA.recordedBattle.textSpeed = OPTIONS_TEXT_SPEED_FAST;