diff --git a/INSTALL.md b/INSTALL.md
index fc1aeb5ba8..25e6adb428 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -1,564 +1,82 @@
# Instructions
+Install instructions for each supported operating system can be found in their respective directories under `docs/install/`.
+Lines to those can be found under each heading.
+This file only contains a short introduction to each supported system.
+If you run into trouble, ask for help on Discord (see [README.md](README.md)).
-These instructions explain how to set up the tools required to build **pokeemerald Expansion**, which assembles the source files into a ROM (pokeemerald.gba).
-
-These instructions come with notes which can be expanded by clicking the "Note..." text.
-In general, you should not need to open these unless if you get an error or if you need additional clarification.
-
-If you run into trouble, ask for help on Discord or IRC (see [README.md](README.md)).
+After completing the install instructions for your OS, proceed to [Building pokeemerald-expansion](#building-pokeemerald-expansion).
## Windows
-Windows has instructions for building with three possible terminals, providing 3 different options in case the user stumbles upon unexpected errors.
-- [Windows 10/11 (WSL1)](#windows-1011-wsl1) (**Fastest, highly recommended**, Windows 10 and 11 only)
-- [Windows (msys2)](#windows-msys2) (Second fastest)
-- [Windows (Cygwin)](#windows-cygwin) (Slowest)
-
-Unscientific benchmarks suggest **msys2 is 2x slower** than WSL1, and **Cygwin is 5-6x slower** than WSL1.
-
- Note for advanced users: WSL2...
-
-> WSL2 is an option and is even faster than WSL1 if files are stored on the WSL2 file system, but some tools may have trouble interacting
-> with the WSL2 file system over the network drive. For example, tools which use Qt versions before 5.15.2 such as porymap
-> may have problems with parsing the \\wsl$ network drive path.
-
-
-All of the Windows instructions assume that the default drive is C:\\. If this differs to your actual drive letter, then replace C with the correct drive letter when reading the instructions.
+**Windows needs one of the systems to build the project**
**A note of caution**: As Windows 7 and Windows 8 are officially unsupported by Microsoft, some maintainers are unwilling to maintain the Windows 7/8 instructions. Thus, these instructions may break in the future with fixes taking longer than fixes to the Windows 10/11 instructions.
-## Windows 10/11 (WSL1)
-WSL1 is the preferred terminal to build **pokeemerald Expansion**. The following instructions will explain how to install WSL1 (referred to interchangeably as WSL).
-- If WSL (Debian or Ubuntu) is **not installed**, then go to [Installing WSL1](#Installing-WSL1).
-- Otherwise, if WSL is installed, but it **hasn't previously been set up for another decompilation project**, then go to [Setting up WSL1](#Setting-up-WSL1).
-- Otherwise, **open WSL** and go to [Choosing where to store pokeemerald Expansion (WSL1)](#Choosing-where-to-store-pokeemerald-expansion-WSL1).
+On Windows, the project can be built using the following systems:
+- WSL2, fastest
+- WSL1, 7 times slower than WSL2
+- Msys2, 20 times slower than WSL2 (**NOTE**: Currently broken on pret upstream)
+- Cygwin, 30 timer slower than WSL2 (**NOTE**: Currently broken on pret upstream)
-### Installing WSL1
-1. Open [Windows Powershell **as Administrator**](https://i.imgur.com/QKmVbP9.png), and run the following commands (Right Click or Shift+Insert is paste in the Powershell).
+**NOTE**: Only WSL systems are recommended.
- ```powershell
- wsl --install -d Ubuntu --enable-wsl1
- ```
+[WSL Install instructions](docs/install/windows/WSL.md)
-2. Once the process finishes, restart your machine.
+[Msys2 Install instructions](docs/install/windows/MSYS2.md)
-3. Open Windows Powershell **as Administrator** again (after restarting), and run the following command to configure Ubuntu to use WSL1.
-
- ```powershell
- wsl --set-version Ubuntu 1
- ```
-
- Note...
-
- > WSL may open automatically after restarting, but you can ignore it for now.
-
-
-### Setting up WSL1
-Some tips before proceeding:
-- In WSL, Copy and Paste is either done via
- - **right-click** (selection + right click to Copy, right click with no selection to Paste)
- - **Ctrl+Shift+C/Ctrl+Shift+V** (enabled by right-clicking the title bar, going to Properties, then checking the checkbox next to "Use Ctrl+Shift+C/V as Copy/Paste").
-- Some of the commands that you'll run will ask for your WSL password and/or confirmation to perform the stated action. This is to be expected, just enter your WSL password and/or the yes action when necessary.
-
-1. Open **Ubuntu** (e.g. using Search).
-2. WSL/Ubuntu will set up its own installation when it runs for the first time. Once WSL/Ubuntu finishes installing, it will ask for a username and password (to be input in).
-
- Note...
-
- > When typing in the password, there will be no visible response, but the terminal will still read in input.
-
-
-3. Update WSL/Ubuntu before continuing. Do this by running the following command. These commands will likely take a long time to finish:
-
- ```bash
- sudo apt update && sudo apt upgrade
- ```
-
-> Note: If the repository you plan to build has an **[older revision of the INSTALL.md](https://github.com/pret/pokeemerald/blob/571c598/INSTALL.md)**, then follow the [legacy WSL1 instructions](docs/legacy_WSL1_INSTALL.md) from here.
-
-4. Certain packages are required to build pokeemerald Expansion. Install these packages by running the following command:
-
- ```bash
- sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev
- ```
-
- Note...
-
- > If the above command does not work, try the above command but replacing `apt` with `apt-get`.
-
- This will install GCC v10 on Ubuntu 22.04. pokeemerald Expansion works with GCC v10, but remote repositories and the RHH Team use GCC v13 for stricter error-checking. If you want to upgrade from v10 to v13, also follow the devkitpro install instructions.
-
-### Installing devkitARM on WSL1
-
-1. Change directory to somewhere you can download a package, such as **C:\Users\\_\_\Downloads** (the Downloads location for most users). To do so, enter this command, where *\ is your **Windows** username:
-
- ```bash
- cd /mnt/c/Users//Downloads
- ```
-
-2. Once the directory has been changed, run the following commands to install devkitARM.
-
- ```bash
- sudo apt install wget
- wget https://apt.devkitpro.org/install-devkitpro-pacman
- chmod +x ./install-devkitpro-pacman
- sudo ./install-devkitpro-pacman
- sudo dkp-pacman -S gba-dev
- ```
- The last command will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation.
-
-3. Run the following command to set devkitPro related environment variables (alternatively, close and re-open WSL):
-
- ```bash
- source /etc/profile.d/devkit-env.sh
- ```
-
-devkitARM is now installed.
-
-### Installing Python on WSL1
-
-To install Python on WSL1, simply run the following commands:
-
-```bash
-sudo apt update && sudo apt upgrade
-sudo apt install python3
-```
-
-Python is now installed.
-
-### Choosing where to store pokeemerald Expansion (WSL1)
-WSL has its own file system that's not natively accessible from Windows, but Windows files *are* accessible from WSL. So you're going to want to store pokeemerald Expansion within Windows.
-
-For example, say you want to store pokeemerald Expansion in **C:\Users\\_\_\Desktop\decomps**. First, ensure that the folder already exists. Then, enter this command to **change directory** to said folder, where *\* is your **Windows** username:
-
-```bash
-cd /mnt/c/Users//Desktop/decomps
-```
-
-
- Notes...
-
-> Note 1: The Windows C:\ drive is called /mnt/c/ in WSL.
-> Note 2: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "/mnt/c/users//Desktop/decomp folder"`.
-> Note 3: Windows path names are case-insensitive so adhering to capitalization isn't needed
-
-
-If this works, then proceed to [Installation](#installation).
-
-Otherwise, ask for help on Discord or IRC (see [README.md](README.md)), or continue reading below for [Windows instructions using msys2](#windows-msys2).
-
-## Windows (msys2)
-
-- If devkitARM is **not installed**, then go to [Installing devkitARM](#installing-devkitarm).
-- If devkitARM is installed, but msys2 **hasn't previously been set up for another decompilation project**, then go to [Setting up msys2](#setting-up-msys2).
-- Otherwise, **open msys2** and go to [Choosing where to store pokeemerald Expansion (msys2)](#choosing-where-to-store-pokeemerald-expansion-msys2).
-
-### Installing devkitARM
-1. Download the devkitPro installer [here](https://github.com/devkitPro/installer/releases).
-2. Run the devkitPro installer. In the "Choose Components" screen, uncheck everything except GBA Development unless if you plan to install other devkitPro components for other purposes. Keep the install location as C:\devkitPro and leave the Start Menu option unchanged.
-
-### Setting up msys2
-
-Note that in msys2, Copy is Ctrl+Insert and Paste is Shift+Insert.
-
-1. Open msys2 at C:\devkitPro\msys2\msys2_shell.bat.
-
-2. Certain packages are required to build pokeemerald Expansion. Install these by running the following two commands:
-
- ```bash
- pacman -Sy msys2-keyring
- pacman -S make gcc zlib-devel git
- ```
-
- Note...
-
- > The commands will ask for confirmation, just enter the yes action when prompted.
-
-
-3. Download [libpng](https://sourceforge.net/projects/libpng/files/libpng16/1.6.37/libpng-1.6.37.tar.xz/download).
-
-4. Change directory to where libpng was downloaded. By default, msys2 will start in the current user's profile folder, located at **C:\Users\\_\_**, where *\* is your Windows username. In most cases, libpng should be saved within a subfolder of the profile folder. For example, if libpng was saved to **C:\Users\\_\_\Downloads** (the Downloads location for most users), enter this command:
-
- ```bash
- cd Downloads
- ```
-
-
- Notes...
-
- > Note 1: While not shown, msys uses forward slashes `/` instead of backwards slashes `\` as the directory separator.
- > Note 2: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "Downloads/My Downloads"`.
- > Note 3: Windows path names are case-insensitive so adhering to capitalization isn’t needed.
- > Note 4: If libpng was saved elsewhere, you will need to specify the full path to where libpng was downloaded, e.g. `cd c:/devkitpro/msys2` if it was saved there.
-
-
-5. Run the following commands to uncompress and install libpng.
-
- ```bash
- tar xf libpng-1.6.37.tar.xz
- cd libpng-1.6.37
- ./configure --prefix=/usr
- make check
- make install
- ```
-
-6. Then finally, run the following command to change back to the user profile folder.
-
- ```bash
- cd
- ```
-
-### Installing Python on msys2
-
-To install Python on msys2, simply run the following commands:
-
-```bash
-pacman -S mingw-w64-x86_64-python3
-```
-
-Python is now installed.
-
-### Choosing where to store pokeemerald Expansion (msys2)
-At this point, you can choose a folder to store pokeemerald Expansion into. If you're okay with storing pokeemerald Expansion in the user profile folder, then proceed to [Installation](#installation). Otherwise, you'll need to account for where pokeemerald Expansion is stored when changing directory to the pokeemerald-expansion folder.
-
-For example, if you want to store pokeemerald Expansion in **C:\Users\\_\_\Desktop\decomps** (where *\* is your **Windows** username), enter this command:
-
-```bash
-cd Desktop/decomps
-```
-
-If this works, then proceed to [Installation](#installation).
-
-Otherwise, ask for help on Discord or IRC (see [README.md](README.md)), or continue reading below for [Windows instructions using Cygwin](#windows-cygwin).
-
-## Windows (Cygwin)
-1. If devkitARM is **not installed**, then follow the instructions used to [install devkitARM](#installing-devkitarm) for the msys2 setup before continuing. *Remember to not continue following the msys2 instructions by mistake!*
-
-2.
- - If Cygwin is **not installed**, or does not have all of the required packages installed, then go to [Installing Cygwin](#installing-cygwin).
- - If Cygwin is installed, but **is not configured to work with devkitARM**, then go to [Configuring devkitARM for Cygwin](#configuring-devkitarm-for-cygwin).
- - Otherwise, **open Cygwin** and go to [Choosing where to store pokeemerald Expansion (Cygwin)](#choosing-where-to-store-pokeemerald-expansion-cygwin)
-
-### Installing Cygwin
-1. Download [Cygwin](https://cygwin.com/install.html): setup-x86_64.exe for 64-bit Windows, setup-x86.exe for 32-bit.
-
-2. Run the Cygwin setup. Within the Cygwin setup, leave the default settings until the "Choose A Download Site" screen.
-
-3. At "Choose a Download Site", select any mirror within the Available Download Sites.
-
-4. At "Select Packages", set the view to "Full" (top left) and search for the following packages:
- - `make`
- - `git`
- - `gcc-core`
- - `gcc-g++`
- - `libpng-devel`
-
- To quickly find these, use the search bar and type the name of each package. Ensure that the selected package name is the **exact** same as the one you're trying to download, e.g. `cmake` is **NOT** the same as `make`.
-
-5. For each package, double click on the text that says "**Skip**" next to each package to select the most recent version to install. If the text says anything other than "**Skip**", (e.g. Keep or a version number), then the package is or will be installed and you don't need to do anything.
-
-6. Once all required packages have been selected, finish the installation.
-
-### Configuring devkitARM for Cygwin
-
-Note that in Cygwin, Copy is Ctrl+Insert and Paste is Shift+Insert.
-
-1. Open **Cygwin**.
-
-2. Run the following commands to configure devkitPro to work with Cygwin.
-
- ```bash
- export DEVKITPRO=/cygdrive/c/devkitpro
- echo export DEVKITPRO=$DEVKITPRO >> ~/.bashrc
- export DEVKITARM=$DEVKITPRO/devkitARM
- echo export DEVKITARM=$DEVKITARM >> ~/.bashrc
- ```
-
-
- Note...
-
- > Replace the drive letter c with the actual drive letter if it is not c.
-
-
-### Choosing where to store pokeemerald Expansion (Cygwin)
-
-Cygwin has its own file system that's within Windows, at **C:\cygwin64\home\\_\_**. If you don't want to store pokeemerald Expansion there, you'll need to account for where ppokeemerald Expansion is stored when **changing directory** to the pokeemerald-expansion folder.
-
-For example, if you want to store pokeemerald Expansion in **C:\Users\\_\_\Desktop\decomps**, enter this command, where *\* is your **Windows** username:
-```bash
-cd c:/Users//Desktop/decomps
-```
-Note that the directory **must exist** in Windows. If you want to store pokeemerald Expansion in a dedicated folder that doesn't exist (e.g. the example provided above), then create the folder (e.g. using Windows Explorer) before executing the `cd` command.
-
-
- Notes...
-
-> Note 1: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "c:/users//Desktop/decomp folder"`.
-> Note 2: Windows path names are case-insensitive so adhering to capitalization isn't needed
-
-
-If this works, then proceed to [Installation](#installation). Otherwise, ask for help on Discord or IRC (see [README.md](README.md)).
-
-## macOS
-1. If the Xcode Command Line Tools are not installed, download the tools [here](https://developer.apple.com/xcode/resources/), open your Terminal, and run the following command:
-
- ```bash
- xcode-select --install
- ```
-
-2. - If libpng is **not installed**, then go to [Installing libpng (macOS)](#installing-libpng-macos).
- - If pkg-config is **not installed**, then go to [Installing pkg-config (macos)](#installing-pkg-config-macos).
- - If devkitARM is **not installed**, then go to [Installing devkitARM (macOS)](#installing-devkitarm-macos).
- - Otherwise, **open the Terminal** and go to [Choosing where to store pokeemerald Expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos)
-
-### Installing libpng (macOS)
-
- Note for advanced users...
-
-> This guide installs libpng via Homebrew as it is the easiest method, however advanced users can install libpng through other means if they so desire.
-
-
-1. Open the Terminal.
-2. If Homebrew is not installed, then install [Homebrew](https://brew.sh/) by following the instructions on the website.
-3. Run the following command to install libpng.
-
- ```bash
- brew install libpng
- ```
- libpng is now installed.
-
- Continue to [Installing pkg-config (macOS)](#installing-pkg-config-macos) if **pkg-config is not installed**. Otherwise, continue to [Installing devkitARM (macOS)](#installing-devkitarm-macos) if **devkitARM is not installed**.
-
- If both pkg-config and devkitARM are already installed, go to [Choosing where to store pokeemerald Expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos).
-
-### Installing pkg-config (macOS)
-
- Note for advanced users...
-
-> This guide installs pkg-config via Homebrew as it is the easiest method, however advanced users can install pkg-config through other means if they so desire.
-
-
-1. Open the Terminal.
-2. If Homebrew is not installed, then install [Homebrew](https://brew.sh/) by following the instructions on the website.
-3. Run the following command to install libpng.
-
- ```bash
- brew install pkg-config
- ```
- pkg-config is now installed.
-
- Continue to [Installing devkitARM (macOS)](#installing-devkitarm-macos) if **devkitARM is not installed**, otherwise, go to [Choosing where to store pokeemerald Expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos).
-
-### Installing devkitARM (macOS)
-1. Download the `devkitpro-pacman-installer.pkg` package from [here](https://github.com/devkitPro/pacman/releases).
-2. Open the package to install devkitPro pacman.
-3. In the Terminal, run the following commands to install devkitARM:
-
- ```bash
- sudo dkp-pacman -Sy
- sudo dkp-pacman -S gba-dev
- sudo dkp-pacman -S devkitarm-rules
- ```
-
- The command with gba-dev will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation.
-
-4. After the tools are installed, devkitARM must now be made accessible from anywhere by the system. To do so, run the following commands:
-
- ```bash
- export DEVKITPRO=/opt/devkitpro
- echo "export DEVKITPRO=$DEVKITPRO" >> ~/.zshrc
- export DEVKITARM=$DEVKITPRO/devkitARM
- echo "export DEVKITARM=$DEVKITARM" >> ~/.zshrc
-
- echo "if [ -f ~/.zshrc ]; then . ~/.zshrc; fi" >> ~/.zprofile
- ```
- *Note: Starting with macOS 10.15, the default Unix shell is now zsh. If you migrated from an older version of macOS, you might still be using bash. You can check my running `echo $0` in the terminal.*
-
- If your terminal is using bash instead of zsh...
-
- ```bash
- export DEVKITPRO=/opt/devkitpro
- echo "export DEVKITPRO=$DEVKITPRO" >> ~/.bashrc
- export DEVKITARM=$DEVKITPRO/devkitARM
- echo "export DEVKITARM=$DEVKITARM" >> ~/.bashrc
-
- echo "if [ -f ~/.bashrc ]; then . ~/.bashrc; fi" >> ~/.bash_profile
- ```
-
-
-### Installing Python (macOS)
-1. Download the latest Python package from [here](https://www.python.org/downloads/).
-2. Open the package to install Python.
-
-Python is now installed.
-
-### Choosing where to store pokeemerald Expansion (macOS)
-At this point, you can choose a folder to store pokeemerald Expansion into. If you're okay with storing pokeemerald Expansion in the user folder, then proceed to [Installation](#installation). Otherwise, you'll need to account for where pokeemerald Expansion is stored when changing directory to the pokeemerald-expansion folder.
-
-For example, if you want to store pokeemerald Expansion in **~/Desktop/decomps**, enter this command to **change directory** to the desired folder:
-```bash
-cd Desktop/decomps
-```
-Note that the directory **must exist** in the folder system. If you want to store pokeemerald Expansion in a dedicated folder that doesn't exist (e.g. the example provided above), then create the folder (e.g. using Finder) before executing the `cd` command.
-
-
- Note...
-
-> Note: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "Desktop/decomp folder"`
-
-
-If this works, then proceed to [Installation](#installation). Otherwise, ask for help on Discord or IRC (see [README.md](README.md)).
+[Cygwin Install instructions](docs/install/windows/CYGWIN.md)
## Linux
-Open Terminal and enter the following commands, depending on which distro you're using.
+The project can be built on any Linux distribution.
+Distributions with instructions:
+- [Ubuntu](docs/install/linux/UBUNTU.md)
+- [Debian](docs/install/linux/DEBIAN.md)
+- [Arch Linux](docs/install/linux/ARCH_LINUX.md)
+- [NixOS](docs/install/linux/NIXOS.md)
-### Debian/Ubuntu-based distributions
-Run the following command to install the necessary packages:
-```bash
-sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev
-```
-Then proceed to [Choosing where to store pokeemerald Expansion (Linux)](#choosing-where-to-store-pokeemerald-expansion-linux).
-
- Note for legacy repos...
+Other distributions have to infer what to do from [general instructions](docs/install/linux/OTHERS.md).
-> If the repository you plan to build has an **[older revision of the INSTALL.md](https://github.com/pret/pokeemerald/blob/571c598/INSTALL.md)**,
-> then you will have to install devkitARM. Install all the above packages except for the arm-none-eabi packages, and follow the instructions to
-> [install devkitARM on Debian/Ubuntu-based distributions](#installing-devkitarm-on-debianubuntu-based-distributions).
-
+## Mac
+Some extra considerations exist to get the testing system working.
-### Installing devkitARM on Debian/Ubuntu-based distributions
+[Mac instructions](docs/install/mac/MAC_OS.md)
-1. Change directory to somewhere you can download a packages, like a Downloads folder. Then, run the following commands to install devkitARM:
+## ChromeOS
+Only tested on x86_64 based systems.
- ```bash
- wget https://apt.devkitpro.org/install-devkitpro-pacman
- chmod +x ./install-devkitpro-pacman
- sudo ./install-devkitpro-pacman
- sudo dkp-pacman -S gba-dev
- ```
- The last command will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation.
+[Chrome OS instructions](docs/install/chromeos/CHROME_OS.md)
-4. Run the following command to set devkitPro related environment variables (alternatively, close and re-open the Terminal):
-
- ```bash
- source /etc/profile.d/devkit-env.sh
- ```
-
-devkitARM is now installed.
-
-### Arch Linux
-Run this command as root to install the necessary packages:
-```bash
-pacman -S base-devel arm-none-eabi-binutils arm-none-eabi-gcc arm-none-eabi-newlib git libpng
-```
-
-### Installing devkitARM on Arch Linux
-
-1. Follow [devkitPro's instructions](https://devkitpro.org/wiki/devkitPro_pacman#Customising_Existing_Pacman_Install) to configure `pacman` to download devkitPro packages.
-2. Install `gba-dev`: run the following command as root.
+# Building pokeemerald-expansion
+Follow these steps to build `pokeemerald-expansion`.
+1. Navigate to the directory you want to keep the project in, be aware of any system specific limitations.
+2. Download `pokeemerald-expansion` with `git`
```console
- pacman -S gba-dev
- ```
- This will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation.
-
-3. Run the following command to set devkitPro related environment variables (alternatively, close and re-open the Terminal):
-
- ```bash
- source /etc/profile.d/devkit-env.sh
- ```
-
-devkitARM is now installed.
-
-Then proceed to [Choosing where to store pokeemerald Expansion (Linux)](#choosing-where-to-store-pokeemerald-expansion-linux).
-
-### NixOS
-Run the following command to start an interactive shell with the necessary packages:
-```bash
-nix-shell -p pkgsCross.arm-embedded.stdenv.cc git pkg-config libpng
-```
-Then proceed to [Choosing where to store pokeemerald Expansion (Linux)](#choosing-where-to-store-pokeemerald-expansion-linux).
-
-### NixOS
-Run the following command to start an interactive shell with the necessary packages:
-```bash
-nix-shell -p pkgsCross.arm-embedded.stdenv.cc git pkg-config libpng
-```
-Then proceed to [Choosing where to store pokeemerald Expansion (Linux)](#choosing-where-to-store-pokeemerald-expansion-linux).
-
-### Other distributions
-_(Specific instructions for other distributions would be greatly appreciated!)_
-
-1. Try to find the required software in its repositories:
- - `gcc`
- - `g++`
- - `make`
- - `git`
- - `libpng-dev`
-
-2. Follow the instructions [here](https://devkitpro.org/wiki/devkitPro_pacman) to install devkitPro pacman. As a reminder, the goal is to configure an existing pacman installation to recognize devkitPro's repositories.
-3. Once devkitPro pacman is configured, run the following commands:
-
- ```bash
- sudo pacman -Sy
- sudo pacman -S gba-dev
- ```
-
- The last command will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation.
-
-### Installing Python in Linux
-Installing Python depends on your distribution, please refere to the instructions [here](https://docs.python-guide.org/starting/install3/linux/).
-
-### Choosing where to store pokeemerald Expansion (Linux)
-At this point, you can choose a folder to store pokeemerald Expansion into. If so, you'll have to account for the modified folder path when changing directory to the pokeemerald-expansion folder.
-
-If this works, then proceed to [Installation](#installation). Otherwise, ask for help on Discord or IRC (see [README.md](README.md)).
-
-## Installation
-
-
- Note for Windows users...
-
-> Consider adding an exception for the `pokeemerald-expansion` and/or `decomps` folder in Windows Security using
-> [these instructions](https://support.microsoft.com/help/4028485). This prevents Microsoft Defender from
-> scanning them which might improve performance while building.
-
-
-1. If pokeemerald Expansion is not already downloaded (some users may prefer to download pokeemerald Expansion via a git client like GitHub Desktop), run:
-
- ```bash
git clone https://github.com/rh-hideout/pokeemerald-expansion
```
+3. Navigate to the newly downloaded project.
-
- Note for WSL1...
+ ```console
+ cd pokeemerald-expansion
+ ```
+4. Build the project.
- > If you get an error stating `fatal: could not set 'core.filemode' to 'false'`, then run the following commands:
- > ```bash
- > cd
- > sudo umount /mnt/c
- > sudo mount -t drvfs C: /mnt/c -o metadata,noatime
- > cd
- > ```
- > Where *\* is the path of the folder [where you chose to store pokeemerald Expansion](#Choosing-where-to-store-pokeemerald-expansion-WSL1). Then run the `git clone` command again.
-
+ ```console
+ make
+ ```
+5. If everything worked correctly, something very similar to this should be seen.
-Now you're ready to build pokeemerald Expansion.
-
-## Build pokeemerald Expansion
-
-If you aren't in the pokeemerald-expansion directory already, then **change directory** to the pokeemerald-expansion folder:
-```bash
-cd pokeemerald-expansion
-```
-To build **pokeemerald.gba** (Note: to speed up builds, see [Parallel builds](#parallel-builds)):
-```bash
-make
-```
-If it has built successfully you will have the output file **pokeemerald.gba** in your project folder.
-
-Note for Windows...
-> If you switched terminals since the last build (e.g. from msys2 to WSL1), you must run `make clean-tools` once before any subsequent `make` commands.
-
+ ```console
+ arm-none-eabi-ld: warning: ../../pokeemerald.elf has a LOAD segment with RWX permissions
+ Memory region Used Size Region Size %age Used
+ EWRAM: 243354 B 256 KB 92.83%
+ IWRAM: 30492 B 32 KB 93.05%
+ ROM: 26072244 B 32 MB 77.70%
+ cd build/modern && arm-none-eabi-ld -T ../../ld_script_modern.ld --print-memory-usage -o ../../pokeemerald.elf | cat
+ tools/gbafix/gbafix pokeemerald.elf -t"POKEMON EMER" -cBPEE -m01 -r0 --silent
+ arm-none-eabi-objcopy -O binary pokeemerald.elf pokeemerald.gba
+ tools/gbafix/gbafix pokeemerald.gba -p --silent
+ ```
+ And the build ROM will be in the directory as `pokeemerald.gba`.
# Building guidance
diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc
index c9c95515f0..118aebab8f 100644
--- a/asm/macros/battle_script.inc
+++ b/asm/macros/battle_script.inc
@@ -928,8 +928,9 @@
.4byte \failInstr
.endm
- .macro setdestinybond
+ .macro trysetdestinybond failInstr:req
.byte 0xaa
+ .4byte \failInstr
.endm
.macro trysetdestinybondtohappen
diff --git a/charmap.txt b/charmap.txt
index 98ad683c81..cd0972f84a 100644
--- a/charmap.txt
+++ b/charmap.txt
@@ -46,6 +46,8 @@ LV = 34
'=' = 35
';' = 36
V_D_ARROW = 38
+NBSP = 39
+'~' = 39
'¿' = 51
'¡' = 52
PK = 53
diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s
index 80d50710ba..e2b76524a8 100644
--- a/data/battle_anim_scripts.s
+++ b/data/battle_anim_scripts.s
@@ -5561,44 +5561,40 @@ GrassPledgeMiddleFountain:
delay 4
return
+@Credits to Skeli
gBattleAnimMove_VoltSwitch::
- loadspritegfx ANIM_TAG_SPARK
+ loadspritegfx ANIM_TAG_SHADOW_BALL
+ loadspritegfx ANIM_TAG_IONS
loadspritegfx ANIM_TAG_SPARK_2
- loadspritegfx ANIM_TAG_THIN_RING
- monbg ANIM_ATTACKER
- setalpha 12, 8
- createsprite gUproarRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0, 0x3BDF, 8
- playsewithpan SE_M_CHARGE, SOUND_PAN_ATTACKER
+ playsewithpan SE_M_THUNDERBOLT, SOUND_PAN_ATTACKER
+ createsprite gVoltSwitchSpriteTemplate, ANIM_TARGET, 3, 0, 0, 0, 0, 32, 20
+ delay 30
+ createvisualtask AnimTask_ShakeMon2 2, ANIM_TARGET, 3, 0, 8, 1
+ call VoltSwitchElectricFlashes
+ delay 2
+ playsewithpan SE_M_THUNDERBOLT, SOUND_PAN_ATTACKER
+ createsprite gVoltSwitchSpriteTemplate ANIM_TARGET, 3, 0, 0, 0, 0, 32, -20
delay 4
- createsprite gUproarRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0, 0x3BDF, 8
- delay 4
- createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 3, 45, 1
- createsprite gUproarRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0, 0x3BDF, 8
- delay 4
- createsprite gUproarRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0, 0x3BDF, 8
- delay 4
- call ElectricityEffect
- playsewithpan SE_M_THUNDERBOLT2, SOUND_PAN_ATTACKER
- createvisualtask AnimTask_CanBattlerSwitch, 1, ANIM_ATTACKER
- jumpretfalse VoltSwitchContinue
- createvisualtask AnimTask_IsTargetSameSide 1
- jumprettrue VoltSwitchAgainstPartner
- createvisualtask AnimTask_SlideOffScreen, 5, ANIM_ATTACKER, -2
-VoltSwitchContinue:
+ call VoltSwitchElectricFlashes
+ delay 18
+ createvisualtask AnimTask_ShakeMon2 2, ANIM_TARGET, 3, 0, 8, 1
+ call VoltSwitchElectricFlashes
+ delay 6
+ call VoltSwitchElectricFlashes
waitforvisualfinish
- clearmonbg ANIM_ATTACKER
- blendoff
- createvisualtask AnimTask_CanBattlerSwitch, 1, ANIM_ATTACKER
- jumpretfalse VoltSwitchLast
- invisible ANIM_ATTACKER
-VoltSwitchLast:
- delay 8
end
-@ Attacking the same side requires a change of direction
-@ why would you attack your partner though?!
-VoltSwitchAgainstPartner:
- createvisualtask AnimTask_SlideOffScreen, 5, ANIM_ATTACKER, 2
- goto VoltSwitchContinue
+
+VoltSwitchElectricFlashes:
+ playsewithpan SE_M_CHARGE, SOUND_PAN_TARGET
+ createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, 5, 0, 5, 0
+ createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, -5, 10, 5, 1
+ createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, 15, 20, 5, 2
+ createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, -15, -10, 5, 0
+ createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, 25, 0, 5, 1
+ createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, -8, 8, 5, 2
+ createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, 2, -8, 5, 0
+ createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, -20, 15, 5, 1
+ return
gBattleAnimMove_StruggleBug::
loadspritegfx ANIM_TAG_MOVEMENT_WAVES
diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s
index 2c9bd46f52..5df1d1935f 100644
--- a/data/battle_scripts_1.s
+++ b/data/battle_scripts_1.s
@@ -298,12 +298,20 @@ BattleScript_CheckPrimalWeather:
jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_STRONG_WINDS, BattleScript_MysteriousAirCurrentBlowsOn
return
+BattleScript_MoveSwitchPursuit:
+ jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_MoveSwitchEnd
+ jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_MoveSwitchEnd
+ printstring STRINGID_PKMNWENTBACK
+ waitmessage B_WAIT_TIME_SHORT
+ jumpifnopursuitswitchdmg BattleScript_MoveSwitchOpenPartyScreen
+ end
+
BattleScript_MoveSwitch:
jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_MoveSwitchEnd
jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_MoveSwitchEnd
printstring STRINGID_PKMNWENTBACK
waitmessage B_WAIT_TIME_SHORT
-BattleScript_MoveSwitchOpenPartyScreen:
+BattleScript_MoveSwitchOpenPartyScreen::
openpartyscreen BS_ATTACKER, BattleScript_MoveSwitchEnd
switchoutabilities BS_ATTACKER
waitstate
@@ -864,7 +872,7 @@ BattleScript_EffectOctolock::
goto BattleScript_MoveEnd
BattleScript_OctolockEndTurn::
- playstatchangeanimation BS_ATTACKER, BIT_DEF | BIT_SPDEF, STAT_CHANGE_NEGATIVE
+ playstatchangeanimation BS_TARGET, BIT_DEF | BIT_SPDEF, STAT_CHANGE_NEGATIVE
setstatchanger STAT_DEF, 1, TRUE
statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_OctolockTryLowerSpDef
printfromtable gStatDownStringIds
@@ -1343,7 +1351,7 @@ BattleScript_EffectPartingShotTrySpAtk:
waitmessage B_WAIT_TIME_LONG
BattleScript_EffectPartingShotSwitch:
moveendall
- goto BattleScript_MoveSwitch
+ goto BattleScript_MoveSwitchPursuit
BattleScript_EffectPowder::
attackcanceler
@@ -2741,9 +2749,9 @@ BattleScript_GravityLoopDrop:
printstring STRINGID_GRAVITYGROUNDING
waitmessage B_WAIT_TIME_LONG
BattleScript_GravityLoopEnd:
- moveendto MOVEEND_NEXT_TARGET
+ moveendcase MOVEEND_TARGET_VISIBLE
jumpifnexttargetvalid BattleScript_GravityLoop
- end
+ goto BattleScript_MoveEnd
BattleScript_EffectRoost::
attackcanceler
@@ -2785,7 +2793,7 @@ BattleScript_EffectHitEscape::
jumpifbattleend BattleScript_HitEscapeEnd
jumpifbyte CMP_NOT_EQUAL, gBattleOutcome, 0, BattleScript_HitEscapeEnd
jumpifemergencyexited BS_TARGET, BattleScript_HitEscapeEnd
- goto BattleScript_MoveSwitch
+ goto BattleScript_MoveSwitchPursuit
BattleScript_HitEscapeEnd:
end
@@ -3415,7 +3423,7 @@ BattleScript_EffectOHKO::
attackcanceler
attackstring
ppreduce
- accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON
+ accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
typecalc
jumpifmovehadnoeffect BattleScript_HitFromAtkAnimation
tryKO BattleScript_KOFail
@@ -4063,7 +4071,7 @@ BattleScript_EffectDestinyBond::
attackcanceler
attackstring
ppreduce
- setdestinybond
+ trysetdestinybond BattleScript_ButItFailed
attackanimation
waitanimation
printstring STRINGID_PKMNTRYINGTOTAKEFOE
@@ -5767,19 +5775,10 @@ BattleScript_PrintFullBox::
BattleScript_ActionSwitch::
hpthresholds2 BS_ATTACKER
printstring STRINGID_RETURNMON
- jumpifbattletype BATTLE_TYPE_DOUBLE, BattleScript_PursuitSwitchDmgSetMultihit
- setmultihit 1
- goto BattleScript_PursuitSwitchDmgLoop
-BattleScript_PursuitSwitchDmgSetMultihit::
- setmultihit 2
-BattleScript_PursuitSwitchDmgLoop::
jumpifnopursuitswitchdmg BattleScript_DoSwitchOut
- swapattackerwithtarget
- trysetdestinybondtohappen
- call BattleScript_PursuitDmgOnSwitchOut
- swapattackerwithtarget
+ end2
+
BattleScript_DoSwitchOut::
- decrementmultihit BattleScript_PursuitSwitchDmgLoop
switchoutabilities BS_ATTACKER
updatedynamax
waitstate
@@ -5801,34 +5800,6 @@ BattleScript_DoSwitchOut::
moveendcase MOVEEND_MIRROR_MOVE
end2
-BattleScript_PursuitDmgOnSwitchOut::
- pause B_WAIT_TIME_SHORT
- orword gHitMarker, HITMARKER_OBEYS
- attackstring
- ppreduce
- critcalc
- damagecalc
- adjustdamage
- attackanimation
- waitanimation
- effectivenesssound
- hitanimation BS_TARGET
- waitstate
- healthbarupdate BS_TARGET
- datahpupdate BS_TARGET
- critmessage
- waitmessage B_WAIT_TIME_LONG
- resultmessage
- waitmessage B_WAIT_TIME_LONG
- tryfaintmon BS_TARGET
- moveendfromto MOVEEND_ABILITIES, MOVEEND_ATTACKER_INVISIBLE @ MOVEEND_CHOICE_MOVE has to be included
- jumpiffainted BS_TARGET, FALSE, BattleScript_PursuitDmgOnSwitchOutRet
- setbyte sGIVEEXP_STATE, 0
- getexp BS_TARGET
-BattleScript_PursuitDmgOnSwitchOutRet:
- bicword gHitMarker, HITMARKER_OBEYS
- return
-
BattleScript_Pausex20::
pause B_WAIT_TIME_SHORT
return
diff --git a/data/scripts/debug.inc b/data/scripts/debug.inc
index 9da3f529fc..0be780609d 100644
--- a/data/scripts/debug.inc
+++ b/data/scripts/debug.inc
@@ -449,7 +449,7 @@ Debug_EventScript_EWRAMCounters_Text::
.string "Fishing Chain: {STR_VAR_2}.$"
Debug_EventScript_FontTest_Text_1::
- .string "{FONT_SHORT_NARROWER}" @ Edit this to test your font
+ .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font
.string "Angel Adept Blind Bodice Clique\n"
.string "Coast Dunce Docile Enact Eosin\l"
.string "Furlong Focal Gnome Gondola Human\l"
@@ -463,7 +463,7 @@ Debug_EventScript_FontTest_Text_1::
.string "Zloty Zodiac.$"
Debug_EventScript_FontTest_Text_2::
- .string "{FONT_SHORT_NARROWER}" @ Edit this to test your font
+ .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font
.string "Angel angel adept for the nuance loads\n"
.string "of the arena cocoa and quaalude. Blind\l"
.string "blind bodice for the submit oboe of the\l"
@@ -474,7 +474,7 @@ Debug_EventScript_FontTest_Text_2::
.string "loud statehood and huddle.$"
Debug_EventScript_FontTest_Text_3::
- .string "{FONT_SHORT_NARROWER}" @ Edit this to test your font
+ .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font
.string "Enact enact eosin for the quench coed\n"
.string "of the pique canoe and bleep. Furlong\l"
.string "furlong focal for the genuflect\l"
@@ -486,7 +486,7 @@ Debug_EventScript_FontTest_Text_3::
.string "bathhouse.$"
Debug_EventScript_FontTest_Text_4::
- .string "{FONT_SHORT_NARROWER}" @ Edit this to test your font
+ .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font
.string "Inlet inlet iodine for the quince\n"
.string "champion of the ennui scampi and shiite.\l"
.string "Justin justin jocose for the djibouti\l"
@@ -498,7 +498,7 @@ Debug_EventScript_FontTest_Text_4::
.string "shallot.$"
Debug_EventScript_FontTest_Text_5::
- .string "{FONT_SHORT_NARROWER}" @ Edit this to test your font
+ .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font
.string "Milliner milliner modal for the alumna\n"
.string "solomon of the album custom and summon.\l"
.string "Number number nodule for the unmade\l"
@@ -510,7 +510,7 @@ Debug_EventScript_FontTest_Text_5::
.string "bishop and supplies.$"
Debug_EventScript_FontTest_Text_6::
- .string "{FONT_SHORT_NARROWER}" @ Edit this to test your font
+ .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font
.string "Quanta quanta qophs for the inquest\n"
.string "sheqel of the cinq coq and suqqu. Rhone\l"
.string "rhone roman for the burnt porous of the\l"
@@ -521,7 +521,7 @@ Debug_EventScript_FontTest_Text_6::
.string "of the peasant ingot and ottoman.$"
Debug_EventScript_FontTest_Text_7::
- .string "{FONT_SHORT_NARROWER}" @ Edit this to test your font
+ .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font
.string "Uncle uncle udder for the dunes cloud\n"
.string "of the hindu thou and continuum. Vulcan\l"
.string "vulcan vocal for the alluvial ovoid of\l"
@@ -533,12 +533,24 @@ Debug_EventScript_FontTest_Text_7::
.string "exxon.$"
Debug_EventScript_FontTest_Text_8::
- .string "{FONT_SHORT_NARROWER}" @ Edit this to test your font
+ .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font
.string "Yunnan yunnan young for the dynamo\n"
.string "coyote of the obloquy employ and\l"
.string "sayyid. Zloty zloty zodiac for the gizmo\l"
.string "ozone of the franz laissez and buzzing.$"
+
+Debug_EventScript_FontTest_Text_9:: @ Special thanks to Nintendo for this nice pangram to test other glyphs
+ .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font
+ .string "42 × 138 = 5796.\n"
+ .string "Mr Jock, TV quiz PhD: bags 20% fewer\l"
+ .string "lynx at a café; voilà, they're “worth”\l"
+ .string "♂1/♀1 = ¥1. That's 10 + 9 - 8 = 11\l"
+ .string "Nintendo GBA can connect to a Nintendo\l"
+ .string "GameCube console! He claimed-though I don't\l"
+ .string "believe him-to have done so in an eyes-shut\l"
+ .string "state…?$"
+
Debug_PrintFontTest::
msgbox Debug_EventScript_FontTest_Text_1, MSGBOX_DEFAULT
msgbox Debug_EventScript_FontTest_Text_2, MSGBOX_DEFAULT
@@ -548,6 +560,7 @@ Debug_PrintFontTest::
msgbox Debug_EventScript_FontTest_Text_6, MSGBOX_DEFAULT
msgbox Debug_EventScript_FontTest_Text_7, MSGBOX_DEFAULT
msgbox Debug_EventScript_FontTest_Text_8, MSGBOX_DEFAULT
+ msgbox Debug_EventScript_FontTest_Text_9, MSGBOX_DEFAULT
releaseall
end
diff --git a/docs/install/chromeos/CHROME_OS.md b/docs/install/chromeos/CHROME_OS.md
new file mode 100644
index 0000000000..7fa57e5968
--- /dev/null
+++ b/docs/install/chromeos/CHROME_OS.md
@@ -0,0 +1,14 @@
+# Instructions for ChromeOS
+
+1. Enable the Linux terminal by following the instructions on [this page](https://chromeos.dev/en/productivity/terminal). Be sure to allocate enough space for the Linux install.
+2. After the Linux terminal has finished installing, run the following command in the terminal to update and upgrade the Linux terminal:
+
+ ```console
+ sudo apt update && apt upgrade
+ ```
+3. Then install all dependencies by running the following command:
+
+ ```console
+ sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev python3
+ ```
+**NOTE**: The project must be kept in a directory inside the Linux filesystem, for example under `~/Decomps/pokeemerald-expansion`
diff --git a/docs/install/linux/ARCH_LINUX.md b/docs/install/linux/ARCH_LINUX.md
new file mode 100644
index 0000000000..1d69e5c39c
--- /dev/null
+++ b/docs/install/linux/ARCH_LINUX.md
@@ -0,0 +1,6 @@
+# Arch Linux instructions
+## Installing dependencies
+Run the following command from the command line:
+```console
+sudo pacman -S base-devel arm-none-eabi-binutils arm-none-eabi-gcc arm-none-eabi-newlib git libpng python
+```
diff --git a/docs/install/linux/DEBIAN.md b/docs/install/linux/DEBIAN.md
new file mode 100644
index 0000000000..a63d3f985e
--- /dev/null
+++ b/docs/install/linux/DEBIAN.md
@@ -0,0 +1,6 @@
+# Debian instructions
+## Installing dependencies
+Open a terminal and run the following command from the command line:
+```console
+sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev python3
+```
diff --git a/docs/install/linux/NIXOS.md b/docs/install/linux/NIXOS.md
new file mode 100644
index 0000000000..6c613466b6
--- /dev/null
+++ b/docs/install/linux/NIXOS.md
@@ -0,0 +1,5 @@
+# NixOS instructions
+Run the following command to start an interactive shell with the necessary packages:
+```bash
+nix-shell -p pkgsCross.arm-embedded.stdenv.cc git pkg-config libpng
+```
diff --git a/docs/install/linux/OTHERS.md b/docs/install/linux/OTHERS.md
new file mode 100644
index 0000000000..eb83331ed9
--- /dev/null
+++ b/docs/install/linux/OTHERS.md
@@ -0,0 +1,11 @@
+# Instructions for other distributions
+1. Try to find the required software in its repositories:
+ - `gcc`
+ - `g++`
+ - `arm-none-eabi-gcc`
+ - `arm-none-eabi-binutils`
+ - `arm-none-eabi-newlib`
+ - `make`
+ - `git`
+ - `libpng-dev`
+ - `python3`
diff --git a/docs/install/linux/UBUNTU.md b/docs/install/linux/UBUNTU.md
new file mode 100644
index 0000000000..41beb8067a
--- /dev/null
+++ b/docs/install/linux/UBUNTU.md
@@ -0,0 +1,6 @@
+# Ubuntu instructions
+## Installing dependencies
+Open a terminal and run the following command from the command line:
+```console
+sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev python3
+```
diff --git a/docs/install/mac/MAC_OS.md b/docs/install/mac/MAC_OS.md
new file mode 100644
index 0000000000..8ffa4df089
--- /dev/null
+++ b/docs/install/mac/MAC_OS.md
@@ -0,0 +1,93 @@
+# Instructions for macOS
+1. If the Xcode Command Line Tools are not installed, download the tools [here](https://developer.apple.com/xcode/resources/), open your Terminal, and run the following command:
+
+ ```bash
+ xcode-select --install
+ ```
+
+2. - If libpng is **not installed**, then go to [Installing libpng (macOS)](#installing-libpng-macos).
+ - If pkg-config is **not installed**, then go to [Installing pkg-config (macos)](#installing-pkg-config-macos).
+ - If devkitARM is **not installed**, then go to [Installing devkitARM (macOS)](#installing-devkitarm-macos).
+ - Otherwise, **open the Terminal** and go to [Choosing where to store pokeemerald-expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos)
+
+### Installing libpng (macOS)
+
+ Note for advanced users...
+
+> This guide installs libpng via Homebrew as it is the easiest method, however advanced users can install libpng through other means if they so desire.
+
+
+1. Open the Terminal.
+2. If Homebrew is not installed, then install [Homebrew](https://brew.sh/) by following the instructions on the website.
+3. Run the following command to install libpng.
+
+ ```bash
+ brew install libpng
+ ```
+ libpng is now installed.
+
+ Continue to [Installing pkg-config (macOS)](#installing-pkg-config-macos) if **pkg-config is not installed**. Otherwise, continue to [Installing devkitARM (macOS)](#installing-devkitarm-macos) if **devkitARM is not installed**.
+
+ If both pkg-config and devkitARM are already installed, go to [Choosing where to store pokeemerald-expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos).
+
+### Installing pkg-config (macOS)
+
+ Note for advanced users...
+
+> This guide installs pkg-config via Homebrew as it is the easiest method, however advanced users can install pkg-config through other means if they so desire.
+
+
+1. Open the Terminal.
+2. If Homebrew is not installed, then install [Homebrew](https://brew.sh/) by following the instructions on the website.
+3. Run the following command to install libpng.
+
+ ```bash
+ brew install pkg-config
+ ```
+ pkg-config is now installed.
+
+ Continue to [Installing devkitARM (macOS)](#installing-devkitarm-macos) if **devkitARM is not installed**, otherwise, go to [Choosing where to store pokeemerald-expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos).
+
+### Installing devkitARM (macOS)
+1. Download the `devkitpro-pacman-installer.pkg` package from [here](https://github.com/devkitPro/pacman/releases).
+2. Open the package to install devkitPro pacman.
+3. In the Terminal, run the following commands to install devkitARM:
+
+ ```bash
+ sudo dkp-pacman -Sy
+ sudo dkp-pacman -S gba-dev
+ sudo dkp-pacman -S devkitarm-rules
+ ```
+
+ The command with gba-dev will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation.
+
+4. After the tools are installed, devkitARM must now be made accessible from anywhere by the system. To do so, run the following commands:
+
+ ```bash
+ export DEVKITPRO=/opt/devkitpro
+ echo "export DEVKITPRO=$DEVKITPRO" >> ~/.zshrc
+ export DEVKITARM=$DEVKITPRO/devkitARM
+ echo "export DEVKITARM=$DEVKITARM" >> ~/.zshrc
+
+ echo "if [ -f ~/.zshrc ]; then . ~/.zshrc; fi" >> ~/.zprofile
+ ```
+ *Note: Starting with macOS 10.15, the default Unix shell is now zsh. If you migrated from an older version of macOS, you might still be using bash. You can check my running `echo $0` in the terminal.*
+
+ If your terminal is using bash instead of zsh...
+
+ ```bash
+ export DEVKITPRO=/opt/devkitpro
+ echo "export DEVKITPRO=$DEVKITPRO" >> ~/.bashrc
+ export DEVKITARM=$DEVKITPRO/devkitARM
+ echo "export DEVKITARM=$DEVKITARM" >> ~/.bashrc
+
+ echo "if [ -f ~/.bashrc ]; then . ~/.bashrc; fi" >> ~/.bash_profile
+ ```
+
+
+### Installing Python (macOS)
+1. Download the latest Python package from [here](https://www.python.org/downloads/).
+2. Open the package to install Python.
+
+Python is now installed.
+
diff --git a/docs/install/windows/CYGWIN.md b/docs/install/windows/CYGWIN.md
new file mode 100644
index 0000000000..c9ca728c22
--- /dev/null
+++ b/docs/install/windows/CYGWIN.md
@@ -0,0 +1,4 @@
+# cygwin
+Don't, just don't.
+Currently doesn't work on current Expansion versions.
+This is a bug from upstream pret `pokeemerald`.
diff --git a/docs/install/windows/MSYS2.md b/docs/install/windows/MSYS2.md
new file mode 100644
index 0000000000..ce7176b912
--- /dev/null
+++ b/docs/install/windows/MSYS2.md
@@ -0,0 +1,4 @@
+# msys2
+Don't, just don't.
+Currently doesn't work on current Expansion versions.
+This is a bug from upstream pret `pokeemerald`.
diff --git a/docs/install/windows/WSL.md b/docs/install/windows/WSL.md
new file mode 100644
index 0000000000..9534966488
--- /dev/null
+++ b/docs/install/windows/WSL.md
@@ -0,0 +1,87 @@
+# Windows WSL instructions
+## Choosing WSL version
+If you must store your project on the Windows file system (under /mnt/c/), you should use WSL1.
+If you want the best performance and least amount of issues with Windows interfering with compiling the project, use WSL2 and store the project on the Linux file system (under ~/).
+## Installing WSL
+1. Open [Windows Powershell **as Administrator**](https://i.imgur.com/QKmVbP9.png), and run the following commands (Right Click or Shift+Insert is paste in the Powershell).
+
+ ```powershell
+ wsl --install -d Ubuntu --enable-wsl1
+ ```
+
+2. Once the process finishes, restart your machine.
+
+### WSL1
+3a. Open Windows Powershell **as Administrator** again (after restarting), and run the following command to configure Ubuntu to use WSL1.
+
+ ```powershell
+ wsl --set-version Ubuntu 1
+ ```
+### WSL2
+3a. Open Windows Powershell **as Administrator** again (after restarting), and run the following command to configure Ubuntu to use WSL2.
+
+ ```powershell
+ wsl --set-version Ubuntu 2
+ ```
+
+
+ Note...
+
+ > WSL may open automatically after restarting, but you can ignore it for now.
+
+
+## Installing dependencies
+Some tips before proceeding:
+- In WSL, Copy and Paste is either done via
+ - **right-click** (selection + right click to Copy, right click with no selection to Paste)
+ - **Ctrl+Shift+C/Ctrl+Shift+V** (enabled by right-clicking the title bar, going to Properties, then checking the checkbox next to "Use Ctrl+Shift+C/V as Copy/Paste").
+- Some of the commands that you'll run will ask for your WSL password and/or confirmation to perform the stated action. This is to be expected, just enter your WSL password and/or the yes action when necessary.
+
+1. Open **Ubuntu** (e.g. using Search).
+2. WSL/Ubuntu will set up its own installation when it runs for the first time. Once WSL/Ubuntu finishes installing, it will ask for a username and password (to be input in).
+
+ Note...
+
+ > When typing in the password, there will be no visible response, but the terminal will still read in input.
+
+
+3. Update WSL/Ubuntu before continuing. Do this by running the following command. These commands will likely take a long time to finish:
+
+ ```bash
+ sudo apt update && sudo apt upgrade
+ ```
+
+4. Certain packages are required to build pokeemerald Expansion. Install these packages by running the following command:
+
+ ```bash
+ sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev python3
+ ```
+
+## Choosing a location to store pokeemerald Expansion, WSL1
+WSL has its own file system that's not natively accessible from Windows, but Windows files *are* accessible from WSL. So you're going to want to store pokeemerald Expansion within Windows.
+
+For example, say you want to store pokeemerald Expansion in **C:\Users\\_\_\Desktop\decomps**. First, ensure that the folder already exists. Then, enter this command to **change directory** to said folder, where *\* is your **Windows** username:
+
+```bash
+cd /mnt/c/Users//Desktop/decomps
+```
+
+
+ Notes...
+
+> Note 1: The Windows C:\ drive is called /mnt/c/ in WSL.
+> Note 2: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "/mnt/c/users//Desktop/decomp folder"`.
+> Note 3: Windows path names are case-insensitive so adhering to capitalization isn't needed
+
+
+## Choosing a location to store pokeemerald Expansion, WSL2
+WSL has its own file system that's not natively accessible from Windows, but Windows files *are* accessible from WSL. But accessing files on the Windows file system with WSL2 is very slow, so you're going to want to store pokeemerald Expansion within WSL2.
+To access the files on the WSL filesystem from Windowsm, you have to open the WSL filesystem as a network attached storage in the file explorer, it should be at the bottom of the left sidebar as "Ubuntu".
+
+Thus you're going to make sure that you're in the WSL filesystem, then create the folder for decomps if it doesn't already exist, then move into that folder.
+
+```bash
+cd ~/
+mkdir decomps
+cd decomps
+```
diff --git a/graphics/battle_anims/sprites/attack_order.png b/graphics/battle_anims/sprites/attack_order.png
index 18531b8304..624708545e 100644
Binary files a/graphics/battle_anims/sprites/attack_order.png and b/graphics/battle_anims/sprites/attack_order.png differ
diff --git a/graphics/battle_anims/sprites/aura_sphere.png b/graphics/battle_anims/sprites/aura_sphere.png
index 04c5030245..4ee16cd488 100644
Binary files a/graphics/battle_anims/sprites/aura_sphere.png and b/graphics/battle_anims/sprites/aura_sphere.png differ
diff --git a/graphics/battle_anims/sprites/blue_flare.pal b/graphics/battle_anims/sprites/blue_flare.pal
index 3b224c3459..87bb2254a3 100644
--- a/graphics/battle_anims/sprites/blue_flare.pal
+++ b/graphics/battle_anims/sprites/blue_flare.pal
@@ -1,6 +1,6 @@
JASC-PAL
0100
-256
+16
0 0 0
248 248 248
205 248 255
@@ -17,243 +17,3 @@ JASC-PAL
238 238 238
189 189 189
156 164 164
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
-0 0 0
diff --git a/graphics/battle_anims/sprites/dragon_pulse.png b/graphics/battle_anims/sprites/dragon_pulse.png
index cc6e28bc32..5a1f62321f 100644
Binary files a/graphics/battle_anims/sprites/dragon_pulse.png and b/graphics/battle_anims/sprites/dragon_pulse.png differ
diff --git a/graphics/battle_anims/sprites/embers.png b/graphics/battle_anims/sprites/embers.png
index 8bf2dd5aa6..c5799e7160 100644
Binary files a/graphics/battle_anims/sprites/embers.png and b/graphics/battle_anims/sprites/embers.png differ
diff --git a/graphics/battle_anims/sprites/fly.png b/graphics/battle_anims/sprites/fly.png
index dd1149de99..ff648a6e2e 100644
Binary files a/graphics/battle_anims/sprites/fly.png and b/graphics/battle_anims/sprites/fly.png differ
diff --git a/graphics/battle_anims/sprites/horn_hit_new.png b/graphics/battle_anims/sprites/horn_hit_new.png
index 9bdf61d7d9..0e1a9f2076 100644
Binary files a/graphics/battle_anims/sprites/horn_hit_new.png and b/graphics/battle_anims/sprites/horn_hit_new.png differ
diff --git a/graphics/battle_anims/sprites/mean_look.png b/graphics/battle_anims/sprites/mean_look.png
index 30e6eb5eea..ee9ad320b0 100644
Binary files a/graphics/battle_anims/sprites/mean_look.png and b/graphics/battle_anims/sprites/mean_look.png differ
diff --git a/graphics/battle_anims/sprites/poison_jab.png b/graphics/battle_anims/sprites/poison_jab.png
index e7871a2c9d..b03f4f8d7e 100644
Binary files a/graphics/battle_anims/sprites/poison_jab.png and b/graphics/battle_anims/sprites/poison_jab.png differ
diff --git a/graphics/battle_anims/sprites/power_gem.png b/graphics/battle_anims/sprites/power_gem.png
index 8d9ad469e3..439610c71b 100644
Binary files a/graphics/battle_anims/sprites/power_gem.png and b/graphics/battle_anims/sprites/power_gem.png differ
diff --git a/graphics/battle_anims/sprites/psycho_cut.png b/graphics/battle_anims/sprites/psycho_cut.png
index 3eb1de7d2a..f40d21f706 100644
Binary files a/graphics/battle_anims/sprites/psycho_cut.png and b/graphics/battle_anims/sprites/psycho_cut.png differ
diff --git a/graphics/battle_anims/sprites/stealth_rock.png b/graphics/battle_anims/sprites/stealth_rock.png
index 8b38ae1c17..9334a3419a 100644
Binary files a/graphics/battle_anims/sprites/stealth_rock.png and b/graphics/battle_anims/sprites/stealth_rock.png differ
diff --git a/graphics/battle_anims/sprites/stone_edge.png b/graphics/battle_anims/sprites/stone_edge.png
index 44f678d8db..80377da7ee 100644
Binary files a/graphics/battle_anims/sprites/stone_edge.png and b/graphics/battle_anims/sprites/stone_edge.png differ
diff --git a/graphics/battle_anims/sprites/wood_hammer.png b/graphics/battle_anims/sprites/wood_hammer.png
index 5768605f80..16e1749835 100644
Binary files a/graphics/battle_anims/sprites/wood_hammer.png and b/graphics/battle_anims/sprites/wood_hammer.png differ
diff --git a/graphics/fonts/latin_narrow.png b/graphics/fonts/latin_narrow.png
index 08652d45f4..434638ed17 100644
Binary files a/graphics/fonts/latin_narrow.png and b/graphics/fonts/latin_narrow.png differ
diff --git a/graphics/fonts/latin_narrower.png b/graphics/fonts/latin_narrower.png
index 22847ef099..19a6a98fb6 100644
Binary files a/graphics/fonts/latin_narrower.png and b/graphics/fonts/latin_narrower.png differ
diff --git a/graphics/fonts/latin_short.png b/graphics/fonts/latin_short.png
index 7eba3e748b..98ad3c5cc3 100644
Binary files a/graphics/fonts/latin_short.png and b/graphics/fonts/latin_short.png differ
diff --git a/graphics/fonts/latin_short_narrow.png b/graphics/fonts/latin_short_narrow.png
index cf48712719..6bf1bae0cf 100644
Binary files a/graphics/fonts/latin_short_narrow.png and b/graphics/fonts/latin_short_narrow.png differ
diff --git a/graphics/fonts/latin_short_narrower.png b/graphics/fonts/latin_short_narrower.png
index 9c79ae474f..5c4f4c1d4d 100644
Binary files a/graphics/fonts/latin_short_narrower.png and b/graphics/fonts/latin_short_narrower.png differ
diff --git a/graphics/fonts/latin_small.png b/graphics/fonts/latin_small.png
index 371cd5a968..41bb38cff8 100644
Binary files a/graphics/fonts/latin_small.png and b/graphics/fonts/latin_small.png differ
diff --git a/graphics/fonts/latin_small_narrow.png b/graphics/fonts/latin_small_narrow.png
index 3a88def3ad..ff07b857d7 100644
Binary files a/graphics/fonts/latin_small_narrow.png and b/graphics/fonts/latin_small_narrow.png differ
diff --git a/graphics/fonts/latin_small_narrower.png b/graphics/fonts/latin_small_narrower.png
index d03f1b8ad0..c20fa4ae48 100644
Binary files a/graphics/fonts/latin_small_narrower.png and b/graphics/fonts/latin_small_narrower.png differ
diff --git a/graphics/pokemon/enamorus/anim_front.png b/graphics/pokemon/enamorus/anim_front.png
new file mode 100644
index 0000000000..e4b21fc52a
Binary files /dev/null and b/graphics/pokemon/enamorus/anim_front.png differ
diff --git a/graphics/pokemon/enamorus/back.png b/graphics/pokemon/enamorus/back.png
index 1b2b00e218..17668de576 100755
Binary files a/graphics/pokemon/enamorus/back.png and b/graphics/pokemon/enamorus/back.png differ
diff --git a/graphics/pokemon/enamorus/front.png b/graphics/pokemon/enamorus/front.png
deleted file mode 100755
index c679b07e57..0000000000
Binary files a/graphics/pokemon/enamorus/front.png and /dev/null differ
diff --git a/graphics/pokemon/enamorus/normal.pal b/graphics/pokemon/enamorus/normal.pal
index 08f6e5ebf1..b8986ffd46 100755
--- a/graphics/pokemon/enamorus/normal.pal
+++ b/graphics/pokemon/enamorus/normal.pal
@@ -2,18 +2,18 @@ JASC-PAL
0100
16
153 211 165
-74 74 74
+255 255 255
180 180 189
-252 252 252
+105 106 115
16 16 16
-118 50 58
-147 33 30
-224 116 156
-243 46 46
-174 74 87
-199 46 41
-243 84 143
-187 62 94
-255 197 60
-239 228 176
-0 0 0
+237 129 170
+185 81 133
+126 44 70
+255 203 81
+201 50 96
+157 36 61
+40 40 40
+177 109 135
+123 79 110
+82 50 75
+111 26 47
diff --git a/graphics/pokemon/enamorus/shiny.pal b/graphics/pokemon/enamorus/shiny.pal
index 180ae687e5..41b6650a75 100644
--- a/graphics/pokemon/enamorus/shiny.pal
+++ b/graphics/pokemon/enamorus/shiny.pal
@@ -1,19 +1,19 @@
JASC-PAL
0100
16
-152 208 160
-74 74 74
-180 180 189
+153 211 165
255 255 255
-0 0 0
-131 57 82
-164 24 24
-230 131 164
-255 90 0
-189 82 106
-222 74 41
-255 139 238
-205 98 189
+194 184 173
+115 107 104
+16 16 16
+251 142 224
+198 83 185
+127 58 131
255 197 32
-0 0 0
-0 0 0
+246 81 4
+205 35 35
+40 40 40
+230 131 164
+189 82 106
+107 51 74
+140 29 49
diff --git a/graphics/pokemon/enamorus/therian/back.png b/graphics/pokemon/enamorus/therian/back.png
index a563156e4d..04a5286fc1 100644
Binary files a/graphics/pokemon/enamorus/therian/back.png and b/graphics/pokemon/enamorus/therian/back.png differ
diff --git a/graphics/pokemon/enamorus/therian/front.png b/graphics/pokemon/enamorus/therian/front.png
index 8ac7c93f06..e51457cf8e 100644
Binary files a/graphics/pokemon/enamorus/therian/front.png and b/graphics/pokemon/enamorus/therian/front.png differ
diff --git a/graphics/pokemon/enamorus/therian/normal.pal b/graphics/pokemon/enamorus/therian/normal.pal
index 096dfb36af..e2ddf78389 100644
--- a/graphics/pokemon/enamorus/therian/normal.pal
+++ b/graphics/pokemon/enamorus/therian/normal.pal
@@ -1,19 +1,19 @@
JASC-PAL
0100
16
-156 213 164
-131 41 49
-213 106 156
+152 208 160
+112 48 56
+72 72 72
+144 32 24
+192 40 40
+240 40 40
+184 56 88
+168 72 80
+248 192 56
+240 80 136
+224 112 152
+176 176 184
16 16 16
-213 65 57
-74 74 74
-255 255 255
-180 180 189
-255 197 57
-123 164 131
-98 115 98
-148 197 156
-230 246 230
-49 57 49
-213 106 156
+248 248 248
+0 0 0
0 0 0
diff --git a/graphics/pokemon/enamorus/therian/shiny.pal b/graphics/pokemon/enamorus/therian/shiny.pal
index 58c5564621..a84be28f03 100644
--- a/graphics/pokemon/enamorus/therian/shiny.pal
+++ b/graphics/pokemon/enamorus/therian/shiny.pal
@@ -1,19 +1,19 @@
JASC-PAL
0100
16
-156 213 164
-131 41 49
-213 106 156
+152 208 160
+112 56 80
+72 72 72
+136 32 32
+192 72 48
+240 88 16
+176 96 176
+168 80 104
+248 192 56
+232 128 224
+200 128 152
+176 176 184
16 16 16
-213 65 57
-74 74 74
-255 255 255
-180 180 189
-255 197 57
-123 164 131
-98 115 98
-148 197 156
-230 246 230
-49 57 49
-238 131 230
+248 248 248
+0 0 0
0 0 0
diff --git a/graphics/pokemon/ogerpon/back.png b/graphics/pokemon/ogerpon/back.png
index 75f309fd67..8cd9136f9e 100644
Binary files a/graphics/pokemon/ogerpon/back.png and b/graphics/pokemon/ogerpon/back.png differ
diff --git a/graphics/pokemon/ogerpon/cornerstone/back.png b/graphics/pokemon/ogerpon/cornerstone/back.png
index 7e40fee557..ffface9d68 100644
Binary files a/graphics/pokemon/ogerpon/cornerstone/back.png and b/graphics/pokemon/ogerpon/cornerstone/back.png differ
diff --git a/graphics/pokemon/ogerpon/cornerstone/front.png b/graphics/pokemon/ogerpon/cornerstone/front.png
index 8e96be70e7..9b7f279238 100644
Binary files a/graphics/pokemon/ogerpon/cornerstone/front.png and b/graphics/pokemon/ogerpon/cornerstone/front.png differ
diff --git a/graphics/pokemon/ogerpon/cornerstone/normal.pal b/graphics/pokemon/ogerpon/cornerstone/normal.pal
index 852898a6b7..eb11f81f7e 100644
--- a/graphics/pokemon/ogerpon/cornerstone/normal.pal
+++ b/graphics/pokemon/ogerpon/cornerstone/normal.pal
@@ -1,18 +1,19 @@
JASC-PAL
0100
-15
-148 209 161
-0 0 0
-42 44 41
-21 158 7
-74 76 73
-61 113 53
-25 27 24
-109 99 108
-133 139 139
-53 134 168
-55 189 227
-194 139 62
-255 197 74
-212 230 247
-144 92 38
+16
+238 230 180
+49 49 49
+148 156 148
+16 16 16
+65 115 49
+90 172 49
+90 98 106
+41 41 41
+74 74 74
+0 213 255
+24 24 24
+0 148 180
+255 222 65
+255 255 255
+238 156 0
+139 98 57
diff --git a/graphics/pokemon/ogerpon/cornerstone/shiny.pal b/graphics/pokemon/ogerpon/cornerstone/shiny.pal
index c4956ce774..71dd9d6e9e 100644
--- a/graphics/pokemon/ogerpon/cornerstone/shiny.pal
+++ b/graphics/pokemon/ogerpon/cornerstone/shiny.pal
@@ -1,18 +1,19 @@
JASC-PAL
0100
-15
-148 209 161
-0 0 0
-42 44 41
-21 158 7
-74 76 73
-61 113 53
-25 27 24
-109 99 108
-133 139 139
-53 134 168
-55 189 227
-194 139 62
-255 197 74
-212 230 247
-124 162 56
+16
+238 230 180
+49 49 49
+148 156 148
+16 16 16
+65 115 49
+90 172 49
+90 98 106
+41 41 41
+74 74 74
+0 213 255
+24 24 24
+0 148 180
+255 222 65
+255 255 255
+164 205 24
+139 98 57
diff --git a/graphics/pokemon/ogerpon/front.png b/graphics/pokemon/ogerpon/front.png
index dec38ef0b8..6c2a769081 100644
Binary files a/graphics/pokemon/ogerpon/front.png and b/graphics/pokemon/ogerpon/front.png differ
diff --git a/graphics/pokemon/ogerpon/hearthflame/back.png b/graphics/pokemon/ogerpon/hearthflame/back.png
index d6d927f19d..73f95efbf2 100644
Binary files a/graphics/pokemon/ogerpon/hearthflame/back.png and b/graphics/pokemon/ogerpon/hearthflame/back.png differ
diff --git a/graphics/pokemon/ogerpon/hearthflame/front.png b/graphics/pokemon/ogerpon/hearthflame/front.png
index d8b9cb7b23..098041cf76 100644
Binary files a/graphics/pokemon/ogerpon/hearthflame/front.png and b/graphics/pokemon/ogerpon/hearthflame/front.png differ
diff --git a/graphics/pokemon/ogerpon/hearthflame/normal.pal b/graphics/pokemon/ogerpon/hearthflame/normal.pal
index 3f478af8aa..2ed9b8c050 100644
--- a/graphics/pokemon/ogerpon/hearthflame/normal.pal
+++ b/graphics/pokemon/ogerpon/hearthflame/normal.pal
@@ -1,19 +1,19 @@
JASC-PAL
0100
16
-148 210 164
-0 0 0
-41 44 41
-16 157 0
-230 60 49
-57 113 49
-49 133 172
-131 28 24
-213 230 246
-255 198 74
-172 105 32
-156 153 172
-49 190 230
-164 52 49
-74 76 74
-189 137 90
+238 230 180
+74 74 74
+213 156 24
+255 222 65
+65 115 49
+90 172 49
+16 16 16
+41 41 41
+238 57 41
+156 16 16
+82 8 8
+255 255 255
+238 156 0
+123 106 49
+0 213 255
+139 98 57
diff --git a/graphics/pokemon/ogerpon/hearthflame/shiny.pal b/graphics/pokemon/ogerpon/hearthflame/shiny.pal
index fee0f8de7b..81f60abe80 100644
--- a/graphics/pokemon/ogerpon/hearthflame/shiny.pal
+++ b/graphics/pokemon/ogerpon/hearthflame/shiny.pal
@@ -1,19 +1,19 @@
JASC-PAL
0100
16
-148 210 164
-0 0 0
-41 44 41
-16 157 0
-230 60 49
-57 113 49
-49 133 172
-131 28 24
-213 230 246
-255 198 74
-124 162 56
-156 153 172
-49 190 230
-164 52 49
-74 76 74
-189 137 90
+238 230 180
+74 74 74
+213 156 24
+255 222 65
+65 115 49
+90 172 49
+16 16 16
+41 41 41
+238 57 41
+156 16 16
+82 8 8
+255 255 255
+164 205 24
+123 106 49
+0 213 255
+139 98 57
diff --git a/graphics/pokemon/ogerpon/normal.pal b/graphics/pokemon/ogerpon/normal.pal
index a1ac4baf96..f578e22342 100644
--- a/graphics/pokemon/ogerpon/normal.pal
+++ b/graphics/pokemon/ogerpon/normal.pal
@@ -1,18 +1,19 @@
JASC-PAL
0100
-15
-148 209 161
-0 1 0
-42 44 41
-21 158 7
-27 70 15
-61 113 53
-17 106 68
-83 133 90
-74 76 73
-175 216 159
-251 253 250
-139 99 57
-0 164 153
-120 81 39
-219 157 92
+16
+238 230 180
+41 41 41
+65 115 49
+74 74 74
+8 164 156
+90 172 49
+16 16 16
+8 106 65
+180 222 164
+255 255 255
+98 164 24
+82 180 98
+238 156 0
+139 98 57
+255 222 65
+222 156 90
diff --git a/graphics/pokemon/ogerpon/shiny.pal b/graphics/pokemon/ogerpon/shiny.pal
index 08c751ebda..02b6d9c5ae 100644
--- a/graphics/pokemon/ogerpon/shiny.pal
+++ b/graphics/pokemon/ogerpon/shiny.pal
@@ -1,18 +1,19 @@
JASC-PAL
0100
-15
-148 209 161
-0 1 0
-42 44 41
-21 158 7
-27 70 15
-61 113 53
-17 106 68
-83 133 90
-74 76 73
-175 216 159
-251 253 250
-139 99 57
-0 164 153
-124 162 56
-219 157 92
+16
+238 230 180
+41 41 41
+65 115 49
+74 74 74
+8 164 156
+90 172 49
+16 16 16
+8 106 65
+180 222 164
+255 255 255
+98 164 24
+82 180 98
+164 205 24
+139 98 57
+255 222 65
+222 156 90
diff --git a/graphics/pokemon/ogerpon/wellspring/back.png b/graphics/pokemon/ogerpon/wellspring/back.png
index 87d82032f4..d90a8afe3e 100644
Binary files a/graphics/pokemon/ogerpon/wellspring/back.png and b/graphics/pokemon/ogerpon/wellspring/back.png differ
diff --git a/graphics/pokemon/ogerpon/wellspring/front.png b/graphics/pokemon/ogerpon/wellspring/front.png
index 77ffb489a5..556f9f2688 100644
Binary files a/graphics/pokemon/ogerpon/wellspring/front.png and b/graphics/pokemon/ogerpon/wellspring/front.png differ
diff --git a/graphics/pokemon/ogerpon/wellspring/normal.pal b/graphics/pokemon/ogerpon/wellspring/normal.pal
index db40508a52..b91b6ee255 100644
--- a/graphics/pokemon/ogerpon/wellspring/normal.pal
+++ b/graphics/pokemon/ogerpon/wellspring/normal.pal
@@ -1,19 +1,19 @@
JASC-PAL
0100
16
-148 209 161
-0 0 0
-42 44 41
-21 158 7
-11 64 121
-61 113 53
-74 76 73
-15 90 170
-0 126 229
-53 134 168
-71 85 100
-55 189 227
-212 230 247
-147 91 33
-169 122 74
-152 155 171
+238 230 180
+65 115 49
+90 172 49
+16 16 16
+8 65 131
+41 41 41
+0 131 230
+74 74 74
+139 98 57
+8 90 180
+57 213 255
+205 222 255
+238 156 0
+255 222 65
+255 255 255
+156 205 222
diff --git a/graphics/pokemon/ogerpon/wellspring/shiny.pal b/graphics/pokemon/ogerpon/wellspring/shiny.pal
index 7c44d3352d..4f4e60c157 100644
--- a/graphics/pokemon/ogerpon/wellspring/shiny.pal
+++ b/graphics/pokemon/ogerpon/wellspring/shiny.pal
@@ -1,19 +1,19 @@
JASC-PAL
0100
16
-148 209 161
-0 0 0
-42 44 41
-21 158 7
-11 64 121
-61 113 53
-74 76 73
-15 90 170
-0 126 229
-53 134 168
-71 85 100
-55 189 227
-212 230 247
-124 162 56
-169 122 74
-152 155 171
+238 230 180
+65 115 49
+90 172 49
+16 16 16
+8 65 131
+41 41 41
+0 131 230
+74 74 74
+139 98 57
+8 90 180
+57 213 255
+205 222 255
+164 205 24
+255 222 65
+255 255 255
+156 205 222
diff --git a/graphics/pokemon/sinistcha/back.png b/graphics/pokemon/sinistcha/back.png
index dbb51bbf33..b9df7c5e4d 100644
Binary files a/graphics/pokemon/sinistcha/back.png and b/graphics/pokemon/sinistcha/back.png differ
diff --git a/graphics/pokemon/sinistcha/front.png b/graphics/pokemon/sinistcha/front.png
index 4131a22b9f..eeb1b7a71a 100644
Binary files a/graphics/pokemon/sinistcha/front.png and b/graphics/pokemon/sinistcha/front.png differ
diff --git a/graphics/pokemon/sinistcha/normal.pal b/graphics/pokemon/sinistcha/normal.pal
index 16008ccdf1..0697645151 100644
--- a/graphics/pokemon/sinistcha/normal.pal
+++ b/graphics/pokemon/sinistcha/normal.pal
@@ -1,18 +1,19 @@
JASC-PAL
0100
-15
-115 197 164
+16
+153 210 164
+37 27 27
76 58 58
+57 103 37
105 68 27
-147 138 68
-159 153 130
-219 210 145
-167 186 114
-45 33 33
-51 99 34
+106 91 32
93 158 74
120 196 99
-247 215 98
+160 151 80
+135 132 126
+167 186 114
+204 195 116
+247 218 103
+193 185 174
5 5 5
-208 210 193
-241 237 235
+230 225 219
diff --git a/graphics/pokemon/sinistcha/shiny.pal b/graphics/pokemon/sinistcha/shiny.pal
index c769e9d1a1..6b9d62ab8c 100644
--- a/graphics/pokemon/sinistcha/shiny.pal
+++ b/graphics/pokemon/sinistcha/shiny.pal
@@ -1,18 +1,19 @@
JASC-PAL
0100
-15
-115 197 164
+16
+153 210 164
+10 48 0
32 88 15
-105 68 27
-147 138 68
-159 153 130
-219 210 145
-167 186 114
-45 33 33
-51 99 34
+57 103 37
+143 133 51
+106 91 32
93 158 74
120 196 99
-247 215 98
+160 151 80
+135 132 126
+167 186 114
+204 195 116
+247 218 103
+193 185 174
5 5 5
-208 210 193
-241 237 235
+230 225 219
diff --git a/include/battle.h b/include/battle.h
index fc2d73e62d..8dc45b9ff0 100644
--- a/include/battle.h
+++ b/include/battle.h
@@ -836,6 +836,9 @@ struct BattleStruct
u8 monCausingSleepClause[NUM_BATTLE_SIDES]; // Stores which pokemon on a given side is causing Sleep Clause to be active as the mon's index in the party
u8 sleepClauseEffectExempt:4; // Stores whether effect should be exempt from triggering Sleep Clause (Effect Spore)
u8 usedMicleBerry:4;
+ u8 pursuitTarget:4; // Each battler as a bit.
+ u8 pursuitSwitchByMove:1;
+ u8 pursuitStoredSwitch; // Stored id for the Pursuit target's switch
s32 battlerExpReward;
// Simultaneous hp reduction for spread moves
@@ -866,10 +869,6 @@ STATIC_ASSERT(sizeof(((struct BattleStruct *)0)->palaceFlags) * 8 >= MAX_BATTLER
#define IS_MOVE_STATUS(move)(gMovesInfo[move].category == DAMAGE_CATEGORY_STATUS)
#define IS_MOVE_RECOIL(move)(gMovesInfo[move].recoil > 0 || gMovesInfo[move].effect == EFFECT_RECOIL_IF_MISS)
-#define BATTLER_MAX_HP(battlerId)(gBattleMons[battlerId].hp == gBattleMons[battlerId].maxHP)
-#define TARGET_TURN_DAMAGED ((gSpecialStatuses[gBattlerTarget].physicalDmg != 0 || gSpecialStatuses[gBattlerTarget].specialDmg != 0) || (gBattleStruct->enduredDamage & (1u << gBattlerTarget)))
-#define BATTLER_TURN_DAMAGED(battlerId) ((gSpecialStatuses[battlerId].physicalDmg != 0 || gSpecialStatuses[battlerId].specialDmg != 0) || (gBattleStruct->enduredDamage & (1u << battler)))
-
/* Checks if 'battlerId' is any of the types.
* Passing multiple types is more efficient than calling this multiple
* times with one type because it shares the 'GetBattlerTypes' result. */
@@ -1193,6 +1192,18 @@ extern bool8 gLastUsedBallMenuPresent;
extern u8 gPartyCriticalHits[PARTY_SIZE];
extern u8 gCategoryIconSpriteId;
+static inline bool32 IsBattlerTurnDamaged(u32 battler)
+{
+ return gSpecialStatuses[battler].physicalDmg != 0
+ || gSpecialStatuses[battler].specialDmg != 0
+ || gBattleStruct->enduredDamage & (1u << battler);
+}
+
+static inline bool32 IsBattlerAtMaxHp(u32 battler)
+{
+ return gBattleMons[battler].hp == gBattleMons[battler].maxHP;
+}
+
static inline u32 GetBattlerPosition(u32 battler)
{
return gBattlerPositions[battler];
diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h
index 56dd8aa6e1..729d173933 100644
--- a/include/battle_ai_util.h
+++ b/include/battle_ai_util.h
@@ -44,7 +44,7 @@ void RestoreBattlerData(u32 battlerId);
u32 GetAIChosenMove(u32 battlerId);
u32 GetTotalBaseStat(u32 species);
bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler);
-bool32 AtMaxHp(u32 battler);
+bool32 AI_BattlerAtMaxHp(u32 battler);
u32 GetHealthPercentage(u32 battler);
bool32 IsBattlerTrapped(u32 battler, bool32 switching);
s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler2, u32 moveConsidered);
diff --git a/include/battle_anim.h b/include/battle_anim.h
index 96ba0c52ab..ef933a1c08 100644
--- a/include/battle_anim.h
+++ b/include/battle_anim.h
@@ -464,6 +464,7 @@ void AnimElectricPuff(struct Sprite *sprite);
void AnimSparkElectricityFlashing(struct Sprite *sprite);
void AnimGrowingShockWaveOrb(struct Sprite *sprite);
void AnimElectricity(struct Sprite *);
+void AnimTask_VoltSwitch(struct Sprite* sprite);
extern const union AffineAnimCmd *const gAffineAnims_GrowingElectricOrb[];
extern const union AffineAnimCmd *const gAffineAnims_FlashingSpark[];
extern const union AnimCmd *const gAnims_ThunderboltOrb[];
diff --git a/include/battle_scripts.h b/include/battle_scripts.h
index bf4b34509f..cac3ce990f 100644
--- a/include/battle_scripts.h
+++ b/include/battle_scripts.h
@@ -46,6 +46,8 @@ extern const u8 BattleScript_PrintFailedToRunString[];
extern const u8 BattleScript_PrintCantEscapeFromBattle[];
extern const u8 BattleScript_PrintFullBox[];
extern const u8 BattleScript_ActionSwitch[];
+extern const u8 BattleScript_DoSwitchOut[];
+extern const u8 BattleScript_MoveSwitchOpenPartyScreen[];
extern const u8 BattleScript_Pausex20[];
extern const u8 BattleScript_LevelUp[];
extern const u8 BattleScript_RainContinuesOrEnds[];
diff --git a/include/battle_util.h b/include/battle_util.h
index 2b0192aa71..20a228eef6 100644
--- a/include/battle_util.h
+++ b/include/battle_util.h
@@ -331,5 +331,6 @@ void TryDeactivateSleepClause(u32 battlerSide, u32 indexInParty);
bool32 IsSleepClauseActiveForSide(u32 battlerSide);
bool32 IsSleepClauseEnabled();
void ClearDamageCalcResults(void);
+u32 DoesDestinyBondFail(u32 battler);
#endif // GUARD_BATTLE_UTIL_H
diff --git a/include/config/battle.h b/include/config/battle.h
index 861e3e3fad..9657d4646e 100644
--- a/include/config/battle.h
+++ b/include/config/battle.h
@@ -125,6 +125,8 @@
#define B_POWDER_RAIN GEN_LATEST // In Gen7+, Powder doesn't damage the user of a Fire type move in heavy rain.
#define B_AFTER_YOU_TURN_ORDER GEN_LATEST // In Gen8+, After You doesn't fail if the turn order wouldn't change after use.
#define B_QUASH_TURN_ORDER GEN_LATEST // In Gen8+, Quash-affected battlers move according to speed order. Before Gen8, Quash-affected battlers move in the order they were affected by Quash.
+#define B_DESTINY_BOND_FAIL GEN_LATEST // In Gen7+, Destiny Bond fails if used repeatedly.
+#define B_PURSUIT_TARGET GEN_LATEST // In Gen4+, Pursuit attacks a switching opponent even if they weren't targeting them. Before Gen4, Pursuit only attacks a switching opponent that it originally targeted.
// Ability settings
#define B_ABILITY_WEATHER GEN_LATEST // In Gen6+, ability-induced weather lasts 5 turns. Before, it lasted until the battle ended or until it was changed by a move or a different weather-affecting ability.
@@ -177,6 +179,7 @@
#define B_DREAM_BALL_MODIFIER GEN_LATEST // In Gen8+, Dream Ball's catch multiplier is x4 when the target is asleep or has the ability Comatose.
#define B_SPORT_BALL_MODIFIER GEN_LATEST // In Gen8+, Sport Ball's catch multiplier was reduced from x1.5 to x1.
#define B_SAFARI_BALL_MODIFIER GEN_LATEST // In Gen8+, Safari Ball's catch multiplier was reduced from x1.5 to x1.
+#define B_FRIEND_BALL_MODIFIER GEN_LATEST // In Gen8+, Friend Ball's friendship boost was reduced from 200 to 150.
#define B_SERENE_GRACE_BOOST GEN_LATEST // In Gen5+, Serene Grace boosts the added flinch chance of King's Rock and Razor Fang.
// Flag settings
@@ -220,6 +223,7 @@
#define B_SECRET_POWER_ANIMATION GEN_LATEST // Secret Power's animations change depending on terrain and generation.
#define B_NATURE_POWER_MOVES GEN_LATEST // Nature Power calls different moves depending on terrain and generation. See sNaturePowerMoves.
#define B_CAMOUFLAGE_TYPES GEN_LATEST // Camouflage changes the user to different types depending on terrain and generation. See sTerrainToType.
+#define B_NEW_TERRAIN_BACKGROUNDS FALSE // If set to TRUE, uses new terrain backgrounds for Electric, Misty, Grassy and Psychic Terrain.
// Interface settings
#define B_ABILITY_POP_UP TRUE // In Gen5+, the Pokémon abilities are displayed in a pop-up, when they activate in battle.
diff --git a/include/config/pokemon.h b/include/config/pokemon.h
index 23015614c0..65542a6ccd 100644
--- a/include/config/pokemon.h
+++ b/include/config/pokemon.h
@@ -17,6 +17,7 @@
// GEN_1/2/3/4/5/6/7: Yellow, Crystal, RSE, HGSS, B2W2, ORAS, USUM learnsets respectively.
// GEN_8: Use the following priority: BDSP for Gen1-4 Pokémon, then LA for species introduced in that game, then SwSh for species present in those games. Otherwise, use GEN_7.
// GEN_9: SV For species present in those games. Otherwise use GEN_8.
+#define P_EVOLUTION_LEVEL_1_LEARN GEN_LATEST // In Gen 8+, Pokémon evolving while at level 1 do not get the chance to learn their level 1 moves, while before they did.
// Evolution settings
#define P_FRIENDSHIP_EVO_THRESHOLD GEN_LATEST // Since Gen 8, Pokémon that evolve by friendship evolve at or above 160 friendship instead of 220.
diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h
index 609090b12e..50e39b767e 100644
--- a/include/constants/battle_script_commands.h
+++ b/include/constants/battle_script_commands.h
@@ -88,138 +88,138 @@
#define CMP_COMMON_BITS 4
#define CMP_NO_COMMON_BITS 5
-// Cmd_various
-#define VARIOUS_CANCEL_MULTI_TURN_MOVES 0
-#define VARIOUS_IS_RUNNING_IMPOSSIBLE 1
-#define VARIOUS_GET_MOVE_TARGET 2
-#define VARIOUS_GET_BATTLER_FAINTED 3
-#define VARIOUS_RESET_SWITCH_IN_ABILITY_BITS 4
-#define VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP 5
-#define VARIOUS_RESET_PLAYER_FAINTED 6
-#define VARIOUS_PALACE_FLAVOR_TEXT 7
-#define VARIOUS_ARENA_JUDGMENT_WINDOW 8
-#define VARIOUS_ARENA_OPPONENT_MON_LOST 9
-#define VARIOUS_ARENA_PLAYER_MON_LOST 10
-#define VARIOUS_ARENA_BOTH_MONS_LOST 11
-#define VARIOUS_EMIT_YESNOBOX 12
-#define VARIOUS_DRAW_ARENA_REF_TEXT_BOX 13
-#define VARIOUS_ERASE_ARENA_REF_TEXT_BOX 14
-#define VARIOUS_ARENA_JUDGMENT_STRING 15
-#define VARIOUS_ARENA_WAIT_STRING 16
-#define VARIOUS_WAIT_CRY 17
-#define VARIOUS_RETURN_OPPONENT_MON1 18
-#define VARIOUS_RETURN_OPPONENT_MON2 19
-#define VARIOUS_VOLUME_DOWN 20
-#define VARIOUS_VOLUME_UP 21
-#define VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT 22
-#define VARIOUS_PALACE_TRY_ESCAPE_STATUS 23
-#define VARIOUS_SET_TELEPORT_OUTCOME 24
-#define VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC 25
-#define VARIOUS_STAT_TEXT_BUFFER 26
-#define VARIOUS_SWITCHIN_ABILITIES 27
-#define VARIOUS_INSTANT_HP_DROP 28
-#define VARIOUS_CLEAR_STATUS 29
-#define VARIOUS_RESTORE_PP 30
-#define VARIOUS_TRY_ACTIVATE_MOXIE 31
-#define VARIOUS_TRY_ACTIVATE_FELL_STINGER 32
-#define VARIOUS_PLAY_MOVE_ANIMATION 33
-#define VARIOUS_SET_LUCKY_CHANT 34
-#define VARIOUS_SUCKER_PUNCH_CHECK 35
-#define VARIOUS_SET_SIMPLE_BEAM 36
-#define VARIOUS_TRY_ENTRAINMENT 37
-#define VARIOUS_SET_LAST_USED_ABILITY 38
-#define VARIOUS_INVERT_STAT_STAGES 39
-#define VARIOUS_TRY_ME_FIRST 40
-#define VARIOUS_JUMP_IF_BATTLE_END 41
-#define VARIOUS_TRY_ELECTRIFY 42
-#define VARIOUS_TRY_REFLECT_TYPE 43
-#define VARIOUS_TRY_SOAK 44
-#define VARIOUS_HANDLE_MEGA_EVO 45
-#define VARIOUS_TRY_LAST_RESORT 46
-#define VARIOUS_SET_ARG_TO_BATTLE_DAMAGE 47
-#define VARIOUS_TRY_AUTOTOMIZE 48
-#define VARIOUS_ABILITY_POPUP 49
-#define VARIOUS_JUMP_IF_TARGET_ALLY 50
-#define VARIOUS_TRY_SYNCHRONOISE 51
-#define VARIOUS_PSYCHO_SHIFT 52
-#define VARIOUS_CURE_STATUS 53
-#define VARIOUS_POWER_TRICK 54
-#define VARIOUS_AFTER_YOU 55
-#define VARIOUS_BESTOW 56
-#define VARIOUS_JUMP_IF_NOT_GROUNDED 57
-#define VARIOUS_HANDLE_TRAINER_SLIDE_MSG 58
-#define VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF 59
-#define VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON 60
-#define VARIOUS_SET_AURORA_VEIL 61
-#define VARIOUS_TRY_THIRD_TYPE 62
-#define VARIOUS_ACUPRESSURE 63
-#define VARIOUS_SET_POWDER 64
-#define VARIOUS_SPECTRAL_THIEF 65
-#define VARIOUS_GRAVITY_ON_AIRBORNE_MONS 66
-#define VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS 67
-#define VARIOUS_JUMP_IF_ROAR_FAILS 68
-#define VARIOUS_TRY_INSTRUCT 69
-#define VARIOUS_JUMP_IF_NOT_BERRY 70
-#define VARIOUS_TRACE_ABILITY 71
-#define VARIOUS_UPDATE_NICK 72
-#define VARIOUS_TRY_ILLUSION_OFF 73
-#define VARIOUS_SET_SPRITEIGNORE0HP 74
-#define VARIOUS_HANDLE_FORM_CHANGE 75
-#define VARIOUS_GET_STAT_VALUE 76
-#define VARIOUS_JUMP_IF_FULL_HP 77
-#define VARIOUS_LOSE_TYPE 78
-#define VARIOUS_TRY_ACTIVATE_SOULHEART 79
-#define VARIOUS_TRY_ACTIVATE_RECEIVER 80
-#define VARIOUS_TRY_ACTIVATE_BEAST_BOOST 81
-#define VARIOUS_TRY_FRISK 82
-#define VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED 83
-#define VARIOUS_TRY_FAIRY_LOCK 84
-#define VARIOUS_JUMP_IF_NO_ALLY 85
-#define VARIOUS_POISON_TYPE_IMMUNITY 86
-#define VARIOUS_JUMP_IF_HOLD_EFFECT 87
-#define VARIOUS_INFATUATE_WITH_BATTLER 88
-#define VARIOUS_SET_LAST_USED_ITEM 89
-#define VARIOUS_PARALYZE_TYPE_IMMUNITY 90
-#define VARIOUS_JUMP_IF_ABSENT 91
-#define VARIOUS_DESTROY_ABILITY_POPUP 92
-#define VARIOUS_TOTEM_BOOST 93
-#define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 94
-#define VARIOUS_MOVEEND_ITEM_EFFECTS 95
-#define VARIOUS_TERRAIN_SEED 96
-#define VARIOUS_MAKE_INVISIBLE 97
-#define VARIOUS_ROOM_SERVICE 98
-#define VARIOUS_EERIE_SPELL_PP_REDUCE 99
-#define VARIOUS_JUMP_IF_TEAM_HEALTHY 100
-#define VARIOUS_TRY_HEAL_QUARTER_HP 101
-#define VARIOUS_JUMP_IF_PRANKSTER_BLOCKED 102
-#define VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER 103
-#define VARIOUS_GET_ROTOTILLER_TARGETS 104
-#define VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED 105
-#define VARIOUS_TRY_ACTIVATE_BATTLE_BOND 106
-#define VARIOUS_CONSUME_BERRY 107
-#define VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL 108
-#define VARIOUS_JUMP_IF_SPECIES 109
-#define VARIOUS_UPDATE_ABILITY_POPUP 110
-#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 111
-#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 112
-#define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 113
-#define VARIOUS_TRY_NO_RETREAT 114
-#define VARIOUS_CHECK_POLTERGEIST 115
-#define VARIOUS_CUT_1_3_HP_RAISE_STATS 116
-#define VARIOUS_TRY_END_NEUTRALIZING_GAS 117
-#define VARIOUS_JUMP_IF_UNDER_200 118
-#define VARIOUS_SET_SKY_DROP 119
-#define VARIOUS_CLEAR_SKY_DROP 120
-#define VARIOUS_SKY_DROP_YAWN 121
-#define VARIOUS_CURE_CERTAIN_STATUSES 122
-#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 123
-#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 124
-#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 125
-#define VARIOUS_SAVE_BATTLER_ITEM 126
-#define VARIOUS_RESTORE_BATTLER_ITEM 127
-#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 128
-#define VARIOUS_SWAP_SIDE_STATUSES 129
-#define VARIOUS_SWAP_STATS 130
+enum CmdVarious
+{
+ VARIOUS_CANCEL_MULTI_TURN_MOVES,
+ VARIOUS_IS_RUNNING_IMPOSSIBLE,
+ VARIOUS_GET_MOVE_TARGET,
+ VARIOUS_GET_BATTLER_FAINTED,
+ VARIOUS_RESET_SWITCH_IN_ABILITY_BITS,
+ VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP,
+ VARIOUS_RESET_PLAYER_FAINTED,
+ VARIOUS_PALACE_FLAVOR_TEXT,
+ VARIOUS_ARENA_JUDGMENT_WINDOW,
+ VARIOUS_ARENA_OPPONENT_MON_LOST,
+ VARIOUS_ARENA_PLAYER_MON_LOST,
+ VARIOUS_ARENA_BOTH_MONS_LOST,
+ VARIOUS_EMIT_YESNOBOX,
+ VARIOUS_DRAW_ARENA_REF_TEXT_BOX,
+ VARIOUS_ERASE_ARENA_REF_TEXT_BOX,
+ VARIOUS_ARENA_JUDGMENT_STRING,
+ VARIOUS_ARENA_WAIT_STRING,
+ VARIOUS_WAIT_CRY,
+ VARIOUS_RETURN_OPPONENT_MON1,
+ VARIOUS_RETURN_OPPONENT_MON2,
+ VARIOUS_VOLUME_DOWN,
+ VARIOUS_VOLUME_UP,
+ VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT,
+ VARIOUS_PALACE_TRY_ESCAPE_STATUS,
+ VARIOUS_SET_TELEPORT_OUTCOME,
+ VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC,
+ VARIOUS_STAT_TEXT_BUFFER,
+ VARIOUS_SWITCHIN_ABILITIES,
+ VARIOUS_INSTANT_HP_DROP,
+ VARIOUS_CLEAR_STATUS,
+ VARIOUS_RESTORE_PP,
+ VARIOUS_TRY_ACTIVATE_MOXIE,
+ VARIOUS_TRY_ACTIVATE_FELL_STINGER,
+ VARIOUS_PLAY_MOVE_ANIMATION,
+ VARIOUS_SET_LUCKY_CHANT,
+ VARIOUS_SUCKER_PUNCH_CHECK,
+ VARIOUS_SET_SIMPLE_BEAM,
+ VARIOUS_TRY_ENTRAINMENT,
+ VARIOUS_SET_LAST_USED_ABILITY,
+ VARIOUS_INVERT_STAT_STAGES,
+ VARIOUS_TRY_ME_FIRST,
+ VARIOUS_JUMP_IF_BATTLE_END,
+ VARIOUS_TRY_ELECTRIFY,
+ VARIOUS_TRY_SOAK,
+ VARIOUS_TRY_LAST_RESORT,
+ VARIOUS_SET_ARG_TO_BATTLE_DAMAGE,
+ VARIOUS_TRY_AUTOTOMIZE,
+ VARIOUS_ABILITY_POPUP,
+ VARIOUS_JUMP_IF_TARGET_ALLY,
+ VARIOUS_TRY_SYNCHRONOISE,
+ VARIOUS_PSYCHO_SHIFT,
+ VARIOUS_CURE_STATUS,
+ VARIOUS_POWER_TRICK,
+ VARIOUS_AFTER_YOU,
+ VARIOUS_BESTOW,
+ VARIOUS_JUMP_IF_NOT_GROUNDED,
+ VARIOUS_HANDLE_TRAINER_SLIDE_MSG,
+ VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF,
+ VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON,
+ VARIOUS_SET_AURORA_VEIL,
+ VARIOUS_TRY_THIRD_TYPE,
+ VARIOUS_ACUPRESSURE,
+ VARIOUS_SET_POWDER,
+ VARIOUS_SPECTRAL_THIEF,
+ VARIOUS_GRAVITY_ON_AIRBORNE_MONS,
+ VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS,
+ VARIOUS_JUMP_IF_ROAR_FAILS,
+ VARIOUS_TRY_INSTRUCT,
+ VARIOUS_JUMP_IF_NOT_BERRY,
+ VARIOUS_TRACE_ABILITY,
+ VARIOUS_UPDATE_NICK,
+ VARIOUS_TRY_ILLUSION_OFF,
+ VARIOUS_SET_SPRITEIGNORE0HP,
+ VARIOUS_HANDLE_FORM_CHANGE,
+ VARIOUS_GET_STAT_VALUE,
+ VARIOUS_JUMP_IF_FULL_HP,
+ VARIOUS_LOSE_TYPE,
+ VARIOUS_TRY_ACTIVATE_SOULHEART,
+ VARIOUS_TRY_ACTIVATE_RECEIVER,
+ VARIOUS_TRY_ACTIVATE_BEAST_BOOST,
+ VARIOUS_TRY_FRISK,
+ VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED,
+ VARIOUS_TRY_FAIRY_LOCK,
+ VARIOUS_JUMP_IF_NO_ALLY,
+ VARIOUS_POISON_TYPE_IMMUNITY,
+ VARIOUS_JUMP_IF_HOLD_EFFECT,
+ VARIOUS_INFATUATE_WITH_BATTLER,
+ VARIOUS_SET_LAST_USED_ITEM,
+ VARIOUS_PARALYZE_TYPE_IMMUNITY,
+ VARIOUS_JUMP_IF_ABSENT,
+ VARIOUS_DESTROY_ABILITY_POPUP,
+ VARIOUS_TOTEM_BOOST,
+ VARIOUS_TRY_ACTIVATE_GRIM_NEIGH,
+ VARIOUS_MOVEEND_ITEM_EFFECTS,
+ VARIOUS_TERRAIN_SEED,
+ VARIOUS_MAKE_INVISIBLE,
+ VARIOUS_ROOM_SERVICE,
+ VARIOUS_EERIE_SPELL_PP_REDUCE,
+ VARIOUS_JUMP_IF_TEAM_HEALTHY,
+ VARIOUS_TRY_HEAL_QUARTER_HP,
+ VARIOUS_JUMP_IF_PRANKSTER_BLOCKED,
+ VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER,
+ VARIOUS_GET_ROTOTILLER_TARGETS,
+ VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED,
+ VARIOUS_TRY_ACTIVATE_BATTLE_BOND,
+ VARIOUS_CONSUME_BERRY,
+ VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL,
+ VARIOUS_JUMP_IF_SPECIES,
+ VARIOUS_UPDATE_ABILITY_POPUP,
+ VARIOUS_JUMP_IF_WEATHER_AFFECTED,
+ VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED,
+ VARIOUS_SET_ATTACKER_STICKY_WEB_USER,
+ VARIOUS_TRY_NO_RETREAT,
+ VARIOUS_CHECK_POLTERGEIST,
+ VARIOUS_CUT_1_3_HP_RAISE_STATS,
+ VARIOUS_TRY_END_NEUTRALIZING_GAS,
+ VARIOUS_JUMP_IF_UNDER_200,
+ VARIOUS_SET_SKY_DROP,
+ VARIOUS_CLEAR_SKY_DROP,
+ VARIOUS_SKY_DROP_YAWN,
+ VARIOUS_CURE_CERTAIN_STATUSES,
+ VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES,
+ VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY,
+ VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT,
+ VARIOUS_SAVE_BATTLER_ITEM,
+ VARIOUS_RESTORE_BATTLER_ITEM,
+ VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM,
+ VARIOUS_SWAP_SIDE_STATUSES,
+ VARIOUS_SWAP_STATS,
+};
// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 1
@@ -302,6 +302,7 @@ enum MoveEndEffects
MOVEEND_SAME_MOVE_TURNS,
MOVEEND_SET_EVOLUTION_TRACKER,
MOVEEND_CLEAR_BITS,
+ MOVEEND_PURSUIT_NEXT_ACTION,
MOVEEND_COUNT,
};
diff --git a/include/constants/characters.h b/include/constants/characters.h
index 3725cecce0..6ac3c5224c 100644
--- a/include/constants/characters.h
+++ b/include/constants/characters.h
@@ -54,6 +54,7 @@
#define CHAR_SEMICOLON 0x36
#define CHAR_BARD_WORD_DELIMIT 0x37 // Empty space to separate words in Bard's song
#define CHAR_V_D_ARROW 0x38
+#define CHAR_NBSP 0x39
#define CHAR_INV_QUESTION_MARK 0x51
#define CHAR_INV_EXCL_MARK 0x52
#define CHAR_PK 0x53
diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h
index ab0f6b8453..86ddde5032 100644
--- a/include/constants/pokemon.h
+++ b/include/constants/pokemon.h
@@ -323,8 +323,9 @@ enum EvolutionMode {
// - Unown has 1 frame, presumably to avoid the work of animating all 28 of its forms
#define MAX_MON_PIC_FRAMES 2
-#define BATTLE_ALIVE_EXCEPT_BATTLER 0
-#define BATTLE_ALIVE_SIDE 1
+#define BATTLE_ALIVE_EXCEPT_BATTLER 0
+#define BATTLE_ALIVE_EXCEPT_BATTLER_SIDE 1
+#define BATTLE_ALIVE_SIDE 2
#define SKIP_FRONT_ANIM (1 << 7)
diff --git a/include/fpmath.h b/include/fpmath.h
index 6e3edd64e0..69265652e6 100644
--- a/include/fpmath.h
+++ b/include/fpmath.h
@@ -12,7 +12,8 @@ typedef u32 uq4_12_t;
// Converts a number to Q4.12 fixed-point format
#define Q_4_12(n) ((q4_12_t)((n) * 4096))
-#define UQ_4_12(n) ((uq4_12_t)((n) * 4096))
+#define UQ_4_12(n) ((uq4_12_t)((n) * 4096 + 0.5))
+#define UQ_4_12_FLOORED(n) ((uq4_12_t)((n) * 4096))
// Converts a number to Q24.8 fixed-point format
#define Q_24_8(n) ((s32)((n) << 8))
diff --git a/include/gba/defines.h b/include/gba/defines.h
index c54dac8c13..0bf7110810 100644
--- a/include/gba/defines.h
+++ b/include/gba/defines.h
@@ -13,6 +13,8 @@
#define COMMON_DATA __attribute__((section("common_data")))
#define UNUSED __attribute__((unused))
+#define ARM_FUNC __attribute__((target("arm")))
+
#if MODERN
#define NOINLINE __attribute__((noinline))
#else
diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c
index a7e462ff97..033599154e 100644
--- a/src/battle_ai_main.c
+++ b/src/battle_ai_main.c
@@ -1663,7 +1663,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
}
else
{
- if (AtMaxHp(battlerAtk))
+ if (AI_BattlerAtMaxHp(battlerAtk))
ADJUST_SCORE(-10);
else if (aiData->hpPercents[battlerAtk] >= 80)
ADJUST_SCORE(-5); // do it if nothing better
@@ -1802,7 +1802,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
case EFFECT_RESTORE_HP:
case EFFECT_SOFTBOILED:
case EFFECT_ROOST:
- if (AtMaxHp(battlerAtk))
+ if (AI_BattlerAtMaxHp(battlerAtk))
ADJUST_SCORE(-10);
else if (aiData->hpPercents[battlerAtk] >= 90)
ADJUST_SCORE(-9); //No point in healing, but should at least do it if nothing better
@@ -1812,7 +1812,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
case EFFECT_MOONLIGHT:
if ((AI_GetWeather(aiData) & (B_WEATHER_RAIN | B_WEATHER_SANDSTORM | B_WEATHER_HAIL | B_WEATHER_SNOW | B_WEATHER_FOG)))
ADJUST_SCORE(-3);
- else if (AtMaxHp(battlerAtk))
+ else if (AI_BattlerAtMaxHp(battlerAtk))
ADJUST_SCORE(-10);
else if (aiData->hpPercents[battlerAtk] >= 90)
ADJUST_SCORE(-9); //No point in healing, but should at least do it if nothing better
@@ -1822,7 +1822,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
ADJUST_SCORE(-10);
else if (battlerDef == BATTLE_PARTNER(battlerAtk))
break; //Always heal your ally
- else if (AtMaxHp(battlerAtk))
+ else if (AI_BattlerAtMaxHp(battlerAtk))
ADJUST_SCORE(-10);
else if (aiData->hpPercents[battlerAtk] >= 90)
ADJUST_SCORE(-8); //No point in healing, but should at least do it if nothing better
@@ -1875,6 +1875,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
ADJUST_SCORE(-10);
break;
case EFFECT_DESTINY_BOND:
+ if (DoesDestinyBondFail(battlerAtk))
+ ADJUST_SCORE(-10);
if (gBattleMons[battlerDef].status2 & STATUS2_DESTINY_BOND)
ADJUST_SCORE(-10);
else if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX)
@@ -2388,7 +2390,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
{
if (gStatuses3[battlerDef] & STATUS3_HEAL_BLOCK)
return 0; // cannot even select
- if (AtMaxHp(battlerDef))
+ if (AI_BattlerAtMaxHp(battlerDef))
ADJUST_SCORE(-10);
else if (gBattleMons[battlerDef].hp > gBattleMons[battlerDef].maxHP / 2)
ADJUST_SCORE(-5);
@@ -2557,8 +2559,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
ADJUST_SCORE(-10);
break;
case EFFECT_JUNGLE_HEALING:
- if (AtMaxHp(battlerAtk)
- && AtMaxHp(BATTLE_PARTNER(battlerAtk))
+ if (AI_BattlerAtMaxHp(battlerAtk)
+ && AI_BattlerAtMaxHp(BATTLE_PARTNER(battlerAtk))
&& !(gBattleMons[battlerAtk].status1 & STATUS1_ANY)
&& !(gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_ANY))
ADJUST_SCORE(-10);
@@ -2683,7 +2685,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
if (IsMoveEffectWeather(move))
ADJUST_SCORE(-10);
break;
- }
+ }
} // check partner move effect
// Adjust for always crit moves
diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c
index 228e5202c5..a6415edd7c 100644
--- a/src/battle_ai_util.c
+++ b/src/battle_ai_util.c
@@ -290,7 +290,7 @@ u32 GetHealthPercentage(u32 battlerId)
return (u32)((100 * gBattleMons[battlerId].hp) / gBattleMons[battlerId].maxHP);
}
-bool32 AtMaxHp(u32 battlerId)
+bool32 AI_BattlerAtMaxHp(u32 battlerId)
{
if (AI_DATA->hpPercents[battlerId] == 100)
return TRUE;
@@ -1142,7 +1142,7 @@ s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler, u32 moveConsidered)
static bool32 CanEndureHit(u32 battler, u32 battlerTarget, u32 move)
{
- if (!BATTLER_MAX_HP(battlerTarget) || gMovesInfo[move].effect == EFFECT_MULTI_HIT)
+ if (!AI_BattlerAtMaxHp(battlerTarget) || gMovesInfo[move].effect == EFFECT_MULTI_HIT)
return FALSE;
if (gMovesInfo[move].strikeCount > 1 && !(gMovesInfo[move].effect == EFFECT_DRAGON_DARTS && IsValidDoubleBattle(battlerTarget)))
return FALSE;
@@ -1564,7 +1564,7 @@ bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbil
gPotentialItemEffectBattler = battlerDef;
if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < AI_DATA->holdEffectParams[battlerDef])
return FALSE; //probabilistically speaking, focus band should activate so dont OHKO
- else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && AtMaxHp(battlerDef))
+ else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && AI_BattlerAtMaxHp(battlerDef))
return FALSE;
if (!DoesBattlerIgnoreAbilityChecks(atkAbility, move) && defAbility == ABILITY_STURDY)
@@ -2761,7 +2761,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov
return SHOULD_PIVOT; // Won't get the two turns, pivot
if (!IS_MOVE_STATUS(move) && ((AI_DATA->shouldSwitch & (1u << battlerAtk))
- || (AtMaxHp(battlerDef) && (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH
+ || (AI_BattlerAtMaxHp(battlerDef) && (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH
|| (B_STURDY >= GEN_5 && defAbility == ABILITY_STURDY)
|| defAbility == ABILITY_MULTISCALE
|| defAbility == ABILITY_SHADOW_SHIELD))))
@@ -2769,7 +2769,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov
}
else if (!hasStatBoost)
{
- if (!IS_MOVE_STATUS(move) && (AtMaxHp(battlerDef) && (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH
+ if (!IS_MOVE_STATUS(move) && (AI_BattlerAtMaxHp(battlerDef) && (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH
|| (B_STURDY >= GEN_5 && defAbility == ABILITY_STURDY)
|| defAbility == ABILITY_MULTISCALE
|| defAbility == ABILITY_SHADOW_SHIELD)))
@@ -2848,7 +2848,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov
// can knock out foe in 2 hits
if (IS_MOVE_STATUS(move) && ((AI_DATA->shouldSwitch & (1u << battlerAtk)) //Damaging move
//&& (switchScore >= SWITCHING_INCREASE_RESIST_ALL_MOVES + SWITCHING_INCREASE_KO_FOE //remove hazards
- || (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH && AtMaxHp(battlerDef))))
+ || (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH && AI_BattlerAtMaxHp(battlerDef))))
return DONT_PIVOT; // Pivot to break the sash
else
return CAN_TRY_PIVOT;
diff --git a/src/battle_anim_electric.c b/src/battle_anim_electric.c
index 64114227e1..929dc972f0 100644
--- a/src/battle_anim_electric.c
+++ b/src/battle_anim_electric.c
@@ -589,6 +589,17 @@ const struct SpriteTemplate gIonSpriteTemplate =
.callback = AnimIon,
};
+const struct SpriteTemplate gVoltSwitchSpriteTemplate =
+{
+ .tileTag = ANIM_TAG_SHADOW_BALL,
+ .paletteTag = ANIM_TAG_IONS,
+ .oam = &gOamData_AffineNormal_ObjNormal_32x32,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gAffineAnims_ShadowBall,
+ .callback = AnimTask_VoltSwitch,
+};
+
// functions
static void AnimLightning(struct Sprite *sprite)
{
@@ -1523,3 +1534,52 @@ static void AnimIon_Step(struct Sprite *sprite)
if (sprite->animEnded)
DestroySprite(sprite);
}
+
+//Volt Switch//
+
+//Launches the projectiles for Volt Switch
+//arg 0: initial x pixel offset
+//arg 1: initial y pixel offset
+//arg 2: target x pixel offset
+//arg 3: target y pixel offset
+//arg 4: duration
+//arg 5: wave amplitude
+static void VoltSwitch_Step(struct Sprite* sprite)
+{
+ sprite->invisible = FALSE;
+
+ if (TranslateAnimHorizontalArc(sprite))
+ {
+ //Merge coords into one
+ sprite->x += sprite->x2;
+ sprite->y += sprite->y2;
+ sprite->x2 = 0;
+ sprite->y2 = 0;
+
+ //Come straight back to the attacker
+ sprite->data[0] = 0x14; //Duration
+ sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2);
+ sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET);
+
+ sprite->callback = StartAnimLinearTranslation;
+ StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
+ }
+}
+
+void AnimTask_VoltSwitch(struct Sprite* sprite)
+{
+ InitSpritePosToAnimAttacker(sprite, 0);
+
+ if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT)
+ gBattleAnimArgs[2] = -gBattleAnimArgs[2];
+ else
+ sprite->y += 10; //Move slightly down
+
+ sprite->data[0] = gBattleAnimArgs[4];
+ sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[2]; //Target X
+ sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3]; //Target Y
+ sprite->data[5] = gBattleAnimArgs[5];
+ InitAnimArcTranslation(sprite);
+
+ sprite->callback = VoltSwitch_Step;
+}
diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c
index 3396999487..00e73735e8 100644
--- a/src/battle_controller_player.c
+++ b/src/battle_controller_player.c
@@ -1759,7 +1759,6 @@ static void MoveSelectionDisplayMoveDescription(u32 battler)
u16 move = moveInfo->moves[gMoveSelectionCursor[battler]];
u16 pwr = gMovesInfo[move].power;
u16 acc = gMovesInfo[move].accuracy;
- u8 cat = gMovesInfo[move].category;
u8 pwr_num[3], acc_num[3];
u8 cat_desc[7] = _("CAT: ");
@@ -1796,7 +1795,7 @@ static void MoveSelectionDisplayMoveDescription(u32 battler)
if (gCategoryIconSpriteId == 0xFF)
gCategoryIconSpriteId = CreateSprite(&gSpriteTemplate_CategoryIcons, 38, 64, 1);
- StartSpriteAnim(&gSprites[gCategoryIconSpriteId], cat);
+ StartSpriteAnim(&gSprites[gCategoryIconSpriteId], GetBattleMoveCategory(move));
CopyWindowToVram(B_WIN_MOVE_DESCRIPTION, COPYWIN_FULL);
}
diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c
index 1523bcbd6e..98ee89af9b 100644
--- a/src/battle_dynamax.c
+++ b/src/battle_dynamax.c
@@ -151,7 +151,7 @@ u16 GetNonDynamaxHP(u32 battler)
return gBattleMons[battler].hp;
else
{
- u16 mult = UQ_4_12(1.0/1.5); // placeholder
+ u16 mult = UQ_4_12_FLOORED(1.0/1.5); // placeholder
u16 hp = UQ_4_12_TO_INT((gBattleMons[battler].hp * mult) + UQ_4_12_ROUND);
return hp;
}
@@ -164,7 +164,7 @@ u16 GetNonDynamaxMaxHP(u32 battler)
return gBattleMons[battler].maxHP;
else
{
- u16 mult = UQ_4_12(1.0/1.5); // placeholder
+ u16 mult = UQ_4_12_FLOORED(1.0/1.5); // placeholder
u16 maxHP = UQ_4_12_TO_INT((gBattleMons[battler].maxHP * mult) + UQ_4_12_ROUND);
return maxHP;
}
@@ -202,7 +202,7 @@ void UndoDynamax(u32 battler)
if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX)
{
struct Pokemon *mon = (side == B_SIDE_PLAYER) ? &gPlayerParty[monId] : &gEnemyParty[monId];
- u16 mult = UQ_4_12(1.0/1.5); // placeholder
+ u16 mult = UQ_4_12_FLOORED(1.0/1.5); // placeholder
gBattleMons[battler].hp = UQ_4_12_TO_INT((GetMonData(mon, MON_DATA_HP) * mult + 1) + UQ_4_12_ROUND); // round up
SetMonData(mon, MON_DATA_HP, &gBattleMons[battler].hp);
CalculateMonStats(mon);
diff --git a/src/battle_main.c b/src/battle_main.c
index c7c72564f0..7c02c7abcf 100644
--- a/src/battle_main.c
+++ b/src/battle_main.c
@@ -3114,6 +3114,9 @@ static void BattleStartClearSetData(void)
gBattleStruct->swapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky
gBattleStruct->categoryOverride = FALSE; // used for Z-Moves and Max Moves
+ gBattleStruct->pursuitTarget = 0;
+ gBattleStruct->pursuitSwitchByMove = FALSE;
+ gBattleStruct->pursuitStoredSwitch = 0;
gSelectedMonPartyId = PARTY_SIZE; // Revival Blessing
gCategoryIconSpriteId = 0xFF;
@@ -3355,6 +3358,9 @@ const u8* FaintClearSetData(u32 battler)
gBattleStruct->lastTakenMoveFrom[battler][1] = 0;
gBattleStruct->lastTakenMoveFrom[battler][2] = 0;
gBattleStruct->lastTakenMoveFrom[battler][3] = 0;
+ gBattleStruct->pursuitTarget = 0;
+ gBattleStruct->pursuitSwitchByMove = FALSE;
+ gBattleStruct->pursuitStoredSwitch = 0;
gBattleStruct->palaceFlags &= ~(1u << battler);
gBattleStruct->boosterEnergyActivates &= ~(1u << battler);
@@ -4848,7 +4854,7 @@ s8 GetMovePriority(u32 battler, u16 move)
return gMovesInfo[MOVE_MAX_GUARD].priority;
if (ability == ABILITY_GALE_WINGS
- && (B_GALE_WINGS < GEN_7 || BATTLER_MAX_HP(battler))
+ && (B_GALE_WINGS < GEN_7 || IsBattlerAtMaxHp(battler))
&& gMovesInfo[move].type == TYPE_FLYING)
{
priority++;
@@ -5164,6 +5170,9 @@ static void TurnValuesCleanUp(bool8 var0)
gSideTimers[B_SIDE_OPPONENT].followmeTimer = 0;
gBattleStruct->usedEjectItem = 0;
+ gBattleStruct->pursuitTarget = 0;
+ gBattleStruct->pursuitSwitchByMove = FALSE;
+ gBattleStruct->pursuitStoredSwitch = 0;
gBattleStruct->pledgeMove = FALSE; // combined pledge move may not have been used due to a canceller
ClearDamageCalcResults();
}
@@ -5180,11 +5189,26 @@ static void PopulateArrayWithBattlers(u8 *battlers)
battlers[i] = i;
}
+static bool32 TryActivateGimmick(u32 battler)
+{
+ if ((gBattleStruct->gimmick.toActivate & (1u << battler)) && !(gProtectStructs[battler].noValidMoves))
+ {
+ gBattlerAttacker = gBattleScripting.battler = battler;
+ gBattleStruct->gimmick.toActivate &= ~(1u << battler);
+ if (gGimmicksInfo[gBattleStruct->gimmick.usableGimmick[battler]].ActivateGimmick != NULL)
+ {
+ gGimmicksInfo[gBattleStruct->gimmick.usableGimmick[battler]].ActivateGimmick(battler);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
static bool32 TryDoGimmicksBeforeMoves(void)
{
if (!(gHitMarker & HITMARKER_RUN) && gBattleStruct->gimmick.toActivate)
{
- u32 i, battler;
+ u32 i;
u8 order[MAX_BATTLERS_COUNT];
PopulateArrayWithBattlers(order);
@@ -5192,16 +5216,8 @@ static bool32 TryDoGimmicksBeforeMoves(void)
for (i = 0; i < gBattlersCount; i++)
{
// Search through each battler and activate their gimmick if they have one prepared.
- if ((gBattleStruct->gimmick.toActivate & (1u << order[i])) && !(gProtectStructs[order[i]].noValidMoves))
- {
- battler = gBattlerAttacker = gBattleScripting.battler = order[i];
- gBattleStruct->gimmick.toActivate &= ~(1u << battler);
- if (gGimmicksInfo[gBattleStruct->gimmick.usableGimmick[battler]].ActivateGimmick != NULL)
- {
- gGimmicksInfo[gBattleStruct->gimmick.usableGimmick[battler]].ActivateGimmick(battler);
- return TRUE;
- }
- }
+ if (TryActivateGimmick(order[i]))
+ return TRUE;
}
}
@@ -5251,7 +5267,7 @@ static bool32 TryDoMoveEffectsBeforeMoves(void)
static void TryChangeTurnOrder(void)
{
u32 i, j;
- for (i = 0; i < gBattlersCount - 1; i++)
+ for (i = gCurrentTurnActionNumber; i < gBattlersCount - 1; i++)
{
for (j = i + 1; j < gBattlersCount; j++)
{
@@ -5369,11 +5385,19 @@ static void RunTurnActionsFunctions(void)
// Mega Evolve / Focus Punch-like moves after switching, items, running, but before using a move.
if (gCurrentActionFuncId == B_ACTION_USE_MOVE && !gBattleStruct->effectsBeforeUsingMoveDone)
{
- if (TryDoGimmicksBeforeMoves())
- return;
- else if (TryDoMoveEffectsBeforeMoves())
- return;
- gBattleStruct->effectsBeforeUsingMoveDone = TRUE;
+ if (!gBattleStruct->pursuitTarget)
+ {
+ if (TryDoGimmicksBeforeMoves())
+ return;
+ else if (TryDoMoveEffectsBeforeMoves())
+ return;
+ gBattleStruct->effectsBeforeUsingMoveDone = TRUE;
+ }
+ else
+ {
+ if (TryActivateGimmick(gBattlerByTurnOrder[gCurrentTurnActionNumber]))
+ return;
+ }
}
*(&gBattleStruct->savedTurnActionNumber) = gCurrentTurnActionNumber;
diff --git a/src/battle_message.c b/src/battle_message.c
index 88b33a2c03..684857edb1 100644
--- a/src/battle_message.c
+++ b/src/battle_message.c
@@ -3119,7 +3119,10 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize)
{
while (*toCpy != EOS)
{
- dst[dstID] = *toCpy;
+ if (*toCpy == CHAR_SPACE)
+ dst[dstID] = CHAR_NBSP;
+ else
+ dst[dstID] = *toCpy;
dstID++;
toCpy++;
}
diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c
index 469f9f7eb2..863dcc6f0e 100644
--- a/src/battle_script_commands.c
+++ b/src/battle_script_commands.c
@@ -329,6 +329,7 @@ static void BestowItem(u32 battlerAtk, u32 battlerDef);
static bool8 IsFinalStrikeEffect(u32 moveEffect);
static void TryUpdateRoundTurnOrder(void);
static bool32 ChangeOrderTargetAfterAttacker(void);
+static bool32 SetTargetToNextPursuiter(u32 battlerDef);
void ApplyExperienceMultipliers(s32 *expAmount, u8 expGetterMonId, u8 faintedBattler);
static void RemoveAllWeather(void);
static void RemoveAllTerrains(void);
@@ -508,7 +509,7 @@ static void Cmd_settypetorandomresistance(void);
static void Cmd_setalwayshitflag(void);
static void Cmd_copymovepermanently(void);
static void Cmd_trychoosesleeptalkmove(void);
-static void Cmd_setdestinybond(void);
+static void Cmd_trysetdestinybond(void);
static void Cmd_trysetdestinybondtohappen(void);
static void Cmd_settailwind(void);
static void Cmd_tryspiteppreduce(void);
@@ -767,7 +768,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
Cmd_setalwayshitflag, //0xA7
Cmd_copymovepermanently, //0xA8
Cmd_trychoosesleeptalkmove, //0xA9
- Cmd_setdestinybond, //0xAA
+ Cmd_trysetdestinybond, //0xAA
Cmd_trysetdestinybondtohappen, //0xAB
Cmd_settailwind, //0xAC
Cmd_tryspiteppreduce, //0xAD
@@ -1487,6 +1488,10 @@ static bool32 AccuracyCalcHelper(u32 move, u32 battler)
{
effect = TRUE;
}
+ else if (gBattleStruct->pursuitTarget & (1u << battler))
+ {
+ effect = TRUE;
+ }
else if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !(gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE))
{
effect = TRUE;
@@ -1729,7 +1734,6 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u
{
// Smart target to partner if miss
gBattlerTarget = BATTLE_PARTNER(battlerDef);
- gBattleStruct->moveResultFlags[battlerDef] &= ~MOVE_RESULT_MISSED;
AccuracyCheck(TRUE, nextInstr, failInstr, move);
return;
}
@@ -2203,12 +2207,12 @@ static void Cmd_adjustdamage(void)
RecordItemEffectBattle(battlerDef, holdEffect);
gSpecialStatuses[battlerDef].focusBanded = TRUE;
}
- else if (B_STURDY >= GEN_5 && GetBattlerAbility(battlerDef) == ABILITY_STURDY && BATTLER_MAX_HP(battlerDef))
+ else if (B_STURDY >= GEN_5 && GetBattlerAbility(battlerDef) == ABILITY_STURDY && IsBattlerAtMaxHp(battlerDef))
{
RecordAbilityBattle(battlerDef, ABILITY_STURDY);
gSpecialStatuses[battlerDef].sturdied = TRUE;
}
- else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && BATTLER_MAX_HP(battlerDef))
+ else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && IsBattlerAtMaxHp(battlerDef))
{
RecordItemEffectBattle(battlerDef, holdEffect);
gSpecialStatuses[battlerDef].focusSashed = TRUE;
@@ -2318,7 +2322,7 @@ static inline bool32 DoesBattlerNegateDamage(u32 battler)
return FALSE;
if (ability == ABILITY_DISGUISE && species == SPECIES_MIMIKYU)
return TRUE;
- if (ability == ABILITY_ICE_FACE && species == SPECIES_EISCUE && GetBattleMoveCategory(gCurrentMove) == DAMAGE_CATEGORY_SPECIAL)
+ if (ability == ABILITY_ICE_FACE && species == SPECIES_EISCUE && GetBattleMoveCategory(gCurrentMove) == DAMAGE_CATEGORY_PHYSICAL)
return TRUE;
return FALSE;
@@ -5992,7 +5996,7 @@ static void Cmd_moveend(void)
&& gBattlerAttacker != gBattlerTarget
&& GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget)
&& MoveResultHasEffect(gBattlerTarget)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& gMovesInfo[gCurrentMove].power != 0
&& CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
{
@@ -6277,7 +6281,7 @@ static void Cmd_moveend(void)
if (gBattlerAttacker != gBattlerTarget
&& gMovesInfo[gCurrentMove].category != DAMAGE_CATEGORY_STATUS
&& MoveResultHasEffect(gBattlerTarget)
- && TARGET_TURN_DAMAGED)
+ && IsBattlerTurnDamaged(gBattlerTarget))
{
gBattleStruct->timesGotHit[GetBattlerSide(gBattlerTarget)][gBattlerPartyIndexes[gBattlerTarget]]++;
}
@@ -6506,7 +6510,7 @@ static void Cmd_moveend(void)
else
{
if (gMovesInfo[gCurrentMove].effect == EFFECT_DRAGON_DARTS
- && gBattleStruct->moveTarget[gBattlerAttacker] == gBattlerTarget // Haven't already changed targets
+ && !(gBattleStruct->moveResultFlags[BATTLE_PARTNER(gBattlerTarget)] & MOVE_RESULT_MISSED) // didn't miss the other target
&& CanTargetPartner(gBattlerAttacker, gBattlerTarget)
&& !TargetFullyImmuneToCurrMove(gBattlerAttacker, BATTLE_PARTNER(gBattlerTarget)))
gBattlerTarget = BATTLE_PARTNER(gBattlerTarget); // Target the partner in doubles for second hit.
@@ -6558,7 +6562,7 @@ static void Cmd_moveend(void)
&& gBattleMons[gBattlerAttacker].item == ITEM_NONE
&& gBattleMons[gBattlerTarget].item != ITEM_NONE
&& IsBattlerAlive(gBattlerAttacker)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item)
&& !gSpecialStatuses[gBattlerAttacker].gemBoost // In base game, gems are consumed after magician would activate.
&& !(gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerTarget)] & (1u << gBattlerPartyIndexes[gBattlerTarget]))
@@ -6604,7 +6608,7 @@ static void Cmd_moveend(void)
continue;
// Since we check if battler was damaged, we don't need to check move result.
// In fact, doing so actually prevents multi-target moves from activating eject button properly
- if (!BATTLER_TURN_DAMAGED(battler))
+ if (!IsBattlerTurnDamaged(battler))
continue;
}
else if (ejectPackBattlers & (1u << battler))
@@ -6699,7 +6703,7 @@ static void Cmd_moveend(void)
if (redCardBattlers & (1u << battler)
&& IsBattlerAlive(battler)
&& !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)
- && BATTLER_TURN_DAMAGED(battler)
+ && IsBattlerTurnDamaged(battler)
&& CanBattlerSwitch(gBattlerAttacker))
{
gLastUsedItem = gBattleMons[battler].item;
@@ -6748,7 +6752,7 @@ static void Cmd_moveend(void)
// Attacker is mon who made contact, battler is mon with pickpocket
if (battler != gBattlerAttacker // Cannot pickpocket yourself
&& GetBattlerAbility(battler) == ABILITY_PICKPOCKET // Target must have pickpocket ability
- && BATTLER_TURN_DAMAGED(battler) // Target needs to have been damaged
+ && IsBattlerTurnDamaged(battler) // Target needs to have been damaged
&& !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) // Subsitute unaffected
&& IsBattlerAlive(battler) // Battler must be alive to pickpocket
&& gBattleMons[battler].item == ITEM_NONE // Pickpocketer can't have an item already
@@ -6947,6 +6951,32 @@ static void Cmd_moveend(void)
}
}
+ gBattleScripting.moveendState++;
+ break;
+ case MOVEEND_PURSUIT_NEXT_ACTION:
+ if (gBattleStruct->pursuitTarget & (1u << gBattlerTarget))
+ {
+ u32 storedTarget = gBattlerTarget;
+ if (SetTargetToNextPursuiter(gBattlerTarget))
+ {
+ ChangeOrderTargetAfterAttacker();
+ *(gBattleStruct->moveTarget + gBattlerTarget) = storedTarget;
+ gBattlerTarget = storedTarget;
+ }
+ else if (IsBattlerAlive(gBattlerTarget))
+ {
+ gBattlerAttacker = gBattlerTarget;
+ if (gBattleStruct->pursuitSwitchByMove)
+ gBattlescriptCurrInstr = BattleScript_MoveSwitchOpenPartyScreen;
+ else
+ gBattlescriptCurrInstr = BattleScript_DoSwitchOut;
+ *(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = gBattleStruct->pursuitStoredSwitch;
+ gBattleStruct->pursuitTarget = 0;
+ gBattleStruct->pursuitSwitchByMove = FALSE;
+ gBattleStruct->pursuitStoredSwitch = 0;
+ effect = TRUE;
+ }
+ }
gBattleScripting.moveendState++;
break;
case MOVEEND_COUNT:
@@ -8483,7 +8513,7 @@ static bool32 TryCheekPouch(u32 battler, u32 itemId)
&& GetBattlerAbility(battler) == ABILITY_CHEEK_POUCH
&& !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)
&& gBattleStruct->ateBerry[GetBattlerSide(battler)] & (1u << gBattlerPartyIndexes[battler])
- && !BATTLER_MAX_HP(battler))
+ && !IsBattlerAtMaxHp(battler))
{
gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 3;
if (gBattleStruct->moveDamage[battler] == 0)
@@ -9434,13 +9464,14 @@ static void Cmd_various(void)
s32 i;
u8 data[10];
u32 battler, bits;
+ enum CmdVarious variousId = cmd->id;
if (gBattleControllerExecFlags)
return;
battler = GetBattlerForBattleScript(cmd->battler);
- switch (cmd->id)
+ switch (variousId)
{
// Roar will fail in a double wild battle when used by the player against one of the two alive wild mons.
// Also when an opposing wild mon uses it againt its partner.
@@ -9554,7 +9585,7 @@ static void Cmd_various(void)
case VARIOUS_JUMP_IF_FULL_HP:
{
VARIOUS_ARGS(const u8 *jumpInstr);
- if (BATTLER_MAX_HP(battler))
+ if (IsBattlerAtMaxHp(battler))
gBattlescriptCurrInstr = cmd->jumpInstr;
else
gBattlescriptCurrInstr = cmd->nextInstr;
@@ -9656,7 +9687,7 @@ static void Cmd_various(void)
{
VARIOUS_ARGS(const u8 *failInstr);
if ((gStatuses3[battler] & (STATUS3_SEMI_INVULNERABLE | STATUS3_HEAL_BLOCK))
- || BATTLER_MAX_HP(battler)
+ || IsBattlerAtMaxHp(battler)
|| !gBattleMons[battler].hp
|| !(IsBattlerGrounded(battler)))
{
@@ -12665,7 +12696,7 @@ static void Cmd_tryKO(void)
gSpecialStatuses[gBattlerTarget].focusBanded = TRUE;
RecordItemEffectBattle(gBattlerTarget, holdEffect);
}
- else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && BATTLER_MAX_HP(gBattlerTarget))
+ else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && IsBattlerAtMaxHp(gBattlerTarget))
{
gSpecialStatuses[gBattlerTarget].focusSashed = TRUE;
RecordItemEffectBattle(gBattlerTarget, holdEffect);
@@ -13446,12 +13477,18 @@ static void Cmd_trychoosesleeptalkmove(void)
}
}
-static void Cmd_setdestinybond(void)
+static void Cmd_trysetdestinybond(void)
{
- CMD_ARGS();
-
- gBattleMons[gBattlerAttacker].status2 |= STATUS2_DESTINY_BOND;
- gBattlescriptCurrInstr = cmd->nextInstr;
+ CMD_ARGS(const u8 *failInstr);
+ if (DoesDestinyBondFail(gBattlerAttacker))
+ {
+ gBattlescriptCurrInstr = cmd->failInstr;
+ }
+ else
+ {
+ gBattleMons[gBattlerAttacker].status2 |= STATUS2_DESTINY_BOND;
+ gBattlescriptCurrInstr = cmd->nextInstr;
+ }
}
static void TrySetDestinyBondToHappen(void)
@@ -13961,45 +13998,44 @@ static void Cmd_magnitudedamagecalculation(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}
+static bool32 SetTargetToNextPursuiter(u32 battlerDef)
+{
+ u32 i;
+ for (i = gCurrentTurnActionNumber + 1; i < gBattlersCount; i++)
+ {
+ u32 battler = gBattlerByTurnOrder[i];
+ if (gChosenActionByBattler[battler] == B_ACTION_USE_MOVE
+ && gMovesInfo[gChosenMoveByBattler[battler]].effect == EFFECT_PURSUIT
+ && IsBattlerAlive(battlerDef)
+ && IsBattlerAlive(battler)
+ && GetBattlerSide(battler) != GetBattlerSide(battlerDef)
+ && (B_PURSUIT_TARGET >= GEN_4 || *(gBattleStruct->moveTarget + battler) == battlerDef)
+ && !IsGimmickSelected(battler, GIMMICK_Z_MOVE)
+ && !IsGimmickSelected(battler, GIMMICK_DYNAMAX)
+ && GetActiveGimmick(battler) != GIMMICK_DYNAMAX)
+ {
+ gBattlerTarget = battler;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
static void Cmd_jumpifnopursuitswitchdmg(void)
{
CMD_ARGS(const u8 *jumpInstr);
- if (gMultiHitCounter == 1)
- {
- if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
- gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
- else
- gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
- }
- else
- {
- if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
- gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
- else
- gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
- }
+ u32 savedTarget = gBattlerTarget;
- if (gChosenActionByBattler[gBattlerTarget] == B_ACTION_USE_MOVE
- && gBattlerAttacker == *(gBattleStruct->moveTarget + gBattlerTarget)
- && !(gBattleMons[gBattlerTarget].status1 & (STATUS1_SLEEP | STATUS1_FREEZE))
- && gBattleMons[gBattlerAttacker].hp
- && !gDisableStructs[gBattlerTarget].truantCounter
- && gMovesInfo[gChosenMoveByBattler[gBattlerTarget]].effect == EFFECT_PURSUIT)
+ if (SetTargetToNextPursuiter(gBattlerAttacker))
{
- s32 i;
-
- for (i = 0; i < gBattlersCount; i++)
- {
- if (gBattlerByTurnOrder[i] == gBattlerTarget)
- gActionsByTurnOrder[i] = B_ACTION_TRY_FINISH;
- }
-
- gCurrentMove = gChosenMove = gChosenMoveByBattler[gBattlerTarget];
- gCurrMovePos = gChosenMovePos = *(gBattleStruct->chosenMovePositions + gBattlerTarget);
+ ChangeOrderTargetAfterAttacker();
+ gBattleStruct->pursuitTarget = 1u << gBattlerAttacker;
+ gBattleStruct->pursuitSwitchByMove = gActionsByTurnOrder[gCurrentTurnActionNumber] == B_ACTION_USE_MOVE;
+ gBattleStruct->pursuitStoredSwitch = gBattleStruct->monToSwitchIntoId[gBattlerAttacker];
+ *(gBattleStruct->moveTarget + gBattlerTarget) = gBattlerAttacker;
+ gBattlerTarget = savedTarget;
gBattlescriptCurrInstr = cmd->nextInstr;
- gBattleScripting.animTurn = 1;
- gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED;
}
else
{
@@ -15664,13 +15700,18 @@ static void Cmd_handleballthrow(void)
else
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
- if (gLastUsedItem == BALL_HEAL)
+ if (ballId == BALL_HEAL)
{
MonRestorePP(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]]);
HealStatusConditions(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], STATUS1_ANY, gBattlerTarget);
gBattleMons[gBattlerTarget].hp = gBattleMons[gBattlerTarget].maxHP;
SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_HP, &gBattleMons[gBattlerTarget].hp);
}
+ else if (ballId == BALL_FRIEND)
+ {
+ u32 friendship = (B_FRIEND_BALL_MODIFIER >= GEN_8 ? 150 : 200);
+ SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_FRIENDSHIP, &friendship);
+ }
}
else // mon may be caught, calculate shakes
{
@@ -15725,6 +15766,11 @@ static void Cmd_handleballthrow(void)
gBattleMons[gBattlerTarget].hp = gBattleMons[gBattlerTarget].maxHP;
SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_HP, &gBattleMons[gBattlerTarget].hp);
}
+ else if (ballId == BALL_FRIEND)
+ {
+ u32 friendship = (B_FRIEND_BALL_MODIFIER >= GEN_8 ? 150 : 200);
+ SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_FRIENDSHIP, &friendship);
+ }
}
else // not caught
{
@@ -17192,7 +17238,7 @@ void BS_TryHealPulse(void)
{
NATIVE_ARGS(const u8 *failInstr);
- if (BATTLER_MAX_HP(gBattlerTarget))
+ if (IsBattlerAtMaxHp(gBattlerTarget))
{
gBattlescriptCurrInstr = cmd->failInstr;
}
@@ -17449,7 +17495,7 @@ void BS_TryActivateGulpMissile(void)
if (MoveResultHasEffect(gBattlerTarget)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& gBattleMons[gBattlerTarget].species != SPECIES_CRAMORANT
&& GetBattlerAbility(gBattlerTarget) == ABILITY_GULP_MISSILE)
{
@@ -17650,7 +17696,7 @@ void BS_TryHitSwitchTarget(void)
if (IsBattlerAlive(gBattlerAttacker)
&& IsBattlerAlive(gBattlerTarget)
&& MoveResultHasEffect(gBattlerTarget)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_1ST_HIT
&& GetBattlerAbility(gBattlerTarget) != ABILITY_GUARD_DOG)
{
diff --git a/src/battle_util.c b/src/battle_util.c
index 4b764776e2..fe671a8204 100644
--- a/src/battle_util.c
+++ b/src/battle_util.c
@@ -62,6 +62,8 @@ static u32 GetFlingPowerFromItemId(u32 itemId);
static void SetRandomMultiHitCounter();
static u32 GetBattlerItemHoldEffectParam(u32 battler, u32 item);
static bool32 CanBeInfinitelyConfused(u32 battler);
+ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12(u32 percent);
+ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12_Floored(u32 percent);
extern const u8 *const gBattlescriptsForRunningByItem[];
extern const u8 *const gBattlescriptsForUsingItem[];
@@ -117,6 +119,9 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move)
|| ability == ABILITY_PROPELLER_TAIL || ability == ABILITY_STALWART)
return FALSE;
+ if (gMovesInfo[move].effect == EFFECT_PURSUIT && gBattleStruct->pursuitTarget)
+ return FALSE;
+
if (gSideTimers[defSide].followmePowder && !IsAffectedByPowder(battlerAtk, ability, GetBattlerHoldEffect(battlerAtk, TRUE)))
return FALSE;
@@ -224,6 +229,7 @@ void HandleAction_UseMove(void)
}
else if (IsDoubleBattle()
&& gSideTimers[side].followmeTimer == 0
+ && !(gBattleStruct->pursuitTarget & (1u << *(gBattleStruct->moveTarget + gBattlerAttacker)))
&& (gMovesInfo[gCurrentMove].power != 0 || (moveTarget != MOVE_TARGET_USER && moveTarget != MOVE_TARGET_ALL_BATTLERS))
&& ((GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC)
|| (GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_STORM_DRAIN && moveType == TYPE_WATER)))
@@ -703,7 +709,7 @@ void HandleAction_ActionFinished(void)
gBattleScripting.multihitMoveEffect = 0;
gBattleResources->battleScriptsStack->size = 0;
- if (B_RECALC_TURN_AFTER_ACTIONS >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove)
+ if (B_RECALC_TURN_AFTER_ACTIONS >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove && !gBattleStruct->pursuitTarget)
{
// i starts at `gCurrentTurnActionNumber` because we don't want to recalculate turn order for mon that have already
// taken action. It's been previously increased, which we want in order to not recalculate the turn of the mon that just finished its action
@@ -757,113 +763,18 @@ static const u8 sHoldEffectToType[][2] =
{HOLD_EFFECT_FAIRY_POWER, TYPE_FAIRY},
};
-// percent in UQ_4_12 format
-static const uq4_12_t sPercentToModifier[] =
-{
- UQ_4_12(0.00), // 0
- UQ_4_12(0.01), // 1
- UQ_4_12(0.02), // 2
- UQ_4_12(0.03), // 3
- UQ_4_12(0.04), // 4
- UQ_4_12(0.05), // 5
- UQ_4_12(0.06), // 6
- UQ_4_12(0.07), // 7
- UQ_4_12(0.08), // 8
- UQ_4_12(0.09), // 9
- UQ_4_12(0.10), // 10
- UQ_4_12(0.11), // 11
- UQ_4_12(0.12), // 12
- UQ_4_12(0.13), // 13
- UQ_4_12(0.14), // 14
- UQ_4_12(0.15), // 15
- UQ_4_12(0.16), // 16
- UQ_4_12(0.17), // 17
- UQ_4_12(0.18), // 18
- UQ_4_12(0.19), // 19
- UQ_4_12(0.20), // 20
- UQ_4_12(0.21), // 21
- UQ_4_12(0.22), // 22
- UQ_4_12(0.23), // 23
- UQ_4_12(0.24), // 24
- UQ_4_12(0.25), // 25
- UQ_4_12(0.26), // 26
- UQ_4_12(0.27), // 27
- UQ_4_12(0.28), // 28
- UQ_4_12(0.29), // 29
- UQ_4_12(0.30), // 30
- UQ_4_12(0.31), // 31
- UQ_4_12(0.32), // 32
- UQ_4_12(0.33), // 33
- UQ_4_12(0.34), // 34
- UQ_4_12(0.35), // 35
- UQ_4_12(0.36), // 36
- UQ_4_12(0.37), // 37
- UQ_4_12(0.38), // 38
- UQ_4_12(0.39), // 39
- UQ_4_12(0.40), // 40
- UQ_4_12(0.41), // 41
- UQ_4_12(0.42), // 42
- UQ_4_12(0.43), // 43
- UQ_4_12(0.44), // 44
- UQ_4_12(0.45), // 45
- UQ_4_12(0.46), // 46
- UQ_4_12(0.47), // 47
- UQ_4_12(0.48), // 48
- UQ_4_12(0.49), // 49
- UQ_4_12(0.50), // 50
- UQ_4_12(0.51), // 51
- UQ_4_12(0.52), // 52
- UQ_4_12(0.53), // 53
- UQ_4_12(0.54), // 54
- UQ_4_12(0.55), // 55
- UQ_4_12(0.56), // 56
- UQ_4_12(0.57), // 57
- UQ_4_12(0.58), // 58
- UQ_4_12(0.59), // 59
- UQ_4_12(0.60), // 60
- UQ_4_12(0.61), // 61
- UQ_4_12(0.62), // 62
- UQ_4_12(0.63), // 63
- UQ_4_12(0.64), // 64
- UQ_4_12(0.65), // 65
- UQ_4_12(0.66), // 66
- UQ_4_12(0.67), // 67
- UQ_4_12(0.68), // 68
- UQ_4_12(0.69), // 69
- UQ_4_12(0.70), // 70
- UQ_4_12(0.71), // 71
- UQ_4_12(0.72), // 72
- UQ_4_12(0.73), // 73
- UQ_4_12(0.74), // 74
- UQ_4_12(0.75), // 75
- UQ_4_12(0.76), // 76
- UQ_4_12(0.77), // 77
- UQ_4_12(0.78), // 78
- UQ_4_12(0.79), // 79
- UQ_4_12(0.80), // 80
- UQ_4_12(0.81), // 81
- UQ_4_12(0.82), // 82
- UQ_4_12(0.83), // 83
- UQ_4_12(0.84), // 84
- UQ_4_12(0.85), // 85
- UQ_4_12(0.86), // 86
- UQ_4_12(0.87), // 87
- UQ_4_12(0.88), // 88
- UQ_4_12(0.89), // 89
- UQ_4_12(0.90), // 90
- UQ_4_12(0.91), // 91
- UQ_4_12(0.92), // 92
- UQ_4_12(0.93), // 93
- UQ_4_12(0.94), // 94
- UQ_4_12(0.95), // 95
- UQ_4_12(0.96), // 96
- UQ_4_12(0.97), // 97
- UQ_4_12(0.98), // 98
- UQ_4_12(0.99), // 99
- UQ_4_12(1.00), // 100
-};
-
// code
+
+ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12(u32 percent)
+{
+ return (4096 * percent + 50) / 100;
+}
+
+ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12_Floored(u32 percent)
+{
+ return (4096 * percent) / 100;
+}
+
u8 GetBattlerForBattleScript(u8 caseId)
{
u8 ret = 0;
@@ -2344,7 +2255,7 @@ u8 DoBattlerEndTurnEffects(void)
else if (gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW)
&& ability == ABILITY_ICE_BODY
&& !(gStatuses3[battler] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
- && !BATTLER_MAX_HP(battler)
+ && !IsBattlerAtMaxHp(battler)
&& !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))
{
gBattleScripting.battler = battler;
@@ -2371,7 +2282,7 @@ u8 DoBattlerEndTurnEffects(void)
break;
case ENDTURN_INGRAIN: // ingrain
if ((gStatuses3[battler] & STATUS3_ROOTED)
- && !BATTLER_MAX_HP(battler)
+ && !IsBattlerAtMaxHp(battler)
&& !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)
&& IsBattlerAlive(battler))
{
@@ -2383,7 +2294,7 @@ u8 DoBattlerEndTurnEffects(void)
break;
case ENDTURN_AQUA_RING: // aqua ring
if ((gStatuses3[battler] & STATUS3_AQUA_RING)
- && !BATTLER_MAX_HP(battler)
+ && !IsBattlerAtMaxHp(battler)
&& !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)
&& IsBattlerAlive(battler))
{
@@ -2461,7 +2372,7 @@ u8 DoBattlerEndTurnEffects(void)
{
if (ability == ABILITY_POISON_HEAL)
{
- if (!BATTLER_MAX_HP(battler) && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))
+ if (!IsBattlerAtMaxHp(battler) && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))
{
gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8;
if (gBattleStruct->moveDamage[battler] == 0)
@@ -2489,7 +2400,7 @@ u8 DoBattlerEndTurnEffects(void)
{
if (ability == ABILITY_POISON_HEAL)
{
- if (!BATTLER_MAX_HP(battler) && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))
+ if (!IsBattlerAtMaxHp(battler) && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))
{
gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8;
if (gBattleStruct->moveDamage[battler] == 0)
@@ -2615,15 +2526,14 @@ u8 DoBattlerEndTurnEffects(void)
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_OCTOLOCK:
- {
if (gDisableStructs[battler].octolock)
{
+ gBattlerAttacker = gDisableStructs[battler].battlerPreventingEscape;
gBattlerTarget = battler;
BattleScriptExecute(BattleScript_OctolockEndTurn);
effect++;
}
gBattleStruct->turnEffectsTracker++;
- }
break;
case ENDTURN_UPROAR: // uproar
if (gBattleMons[battler].status2 & STATUS2_UPROAR)
@@ -3786,7 +3696,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
}
}
if (moveTarget == MOVE_TARGET_BOTH)
- gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerAttacker);
+ gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER_SIDE, gBattlerAttacker);
else
gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER, gBattlerAttacker);
@@ -4136,7 +4046,7 @@ static inline u8 GetBattlerSideFaintCounter(u32 battler)
// Supreme Overlord adds a x0.1 damage boost for each fainted ally.
static inline uq4_12_t GetSupremeOverlordModifier(u32 battler)
{
- return UQ_4_12(1.0) + (UQ_4_12(0.1) * gBattleStruct->supremeOverlordCounter[battler]);
+ return UQ_4_12(1.0) + (PercentToUQ4_12(gBattleStruct->supremeOverlordCounter[battler] * 10));
}
static inline bool32 HadMoreThanHalfHpNowDoesnt(u32 battler)
@@ -5238,7 +5148,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
// Dry Skin works similarly to Rain Dish in Rain
case ABILITY_RAIN_DISH:
if (IsBattlerWeatherAffected(battler, B_WEATHER_RAIN)
- && !BATTLER_MAX_HP(battler)
+ && !IsBattlerAtMaxHp(battler)
&& !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))
{
BattleScriptPushCursorAndCallback(BattleScript_RainDishActivates);
@@ -5493,7 +5403,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
{
case MOVE_ABSORBED_BY_DRAIN_HP_ABILITY:
gBattleStruct->pledgeMove = FALSE;
- if (BATTLER_MAX_HP(battler) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battler] & STATUS3_HEAL_BLOCK))
+ if (IsBattlerAtMaxHp(battler) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battler] & STATUS3_HEAL_BLOCK))
{
if ((gProtectStructs[gBattlerAttacker].notFirstStrike))
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless;
@@ -5565,7 +5475,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
{
case ABILITY_JUSTIFIED:
if (MoveResultHasEffect(battler)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& IsBattlerAlive(battler)
&& moveType == TYPE_DARK
&& CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
@@ -5579,7 +5489,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
break;
case ABILITY_RATTLED:
if (MoveResultHasEffect(battler)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& IsBattlerAlive(battler)
&& (moveType == TYPE_DARK || moveType == TYPE_BUG || moveType == TYPE_GHOST)
&& CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN))
@@ -5593,7 +5503,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
break;
case ABILITY_WATER_COMPACTION:
if (MoveResultHasEffect(battler)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& IsBattlerAlive(battler)
&& moveType == TYPE_WATER
&& CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN))
@@ -5608,7 +5518,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_STAMINA:
if (MoveResultHasEffect(battler)
&& gBattlerAttacker != gBattlerTarget
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& IsBattlerAlive(battler)
&& CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN))
{
@@ -5621,7 +5531,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
break;
case ABILITY_BERSERK:
if (MoveResultHasEffect(battler)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& IsBattlerAlive(battler)
&& HadMoreThanHalfHpNowDoesnt(battler)
&& (gMultiHitCounter == 0 || gMultiHitCounter == 1)
@@ -5638,7 +5548,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_EMERGENCY_EXIT:
case ABILITY_WIMP_OUT:
if (MoveResultHasEffect(battler)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& IsBattlerAlive(battler)
// Had more than half of hp before, now has less
&& HadMoreThanHalfHpNowDoesnt(battler)
@@ -5656,7 +5566,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
break;
case ABILITY_WEAK_ARMOR:
if (MoveResultHasEffect(battler)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& IsBattlerAlive(battler)
&& IS_MOVE_PHYSICAL(gCurrentMove)
&& (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN) // Don't activate if both Speed and Defense cannot be raised.
@@ -5672,7 +5582,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
break;
case ABILITY_CURSED_BODY:
if (MoveResultHasEffect(battler)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& gDisableStructs[gBattlerAttacker].disabledMove == MOVE_NONE
&& IsBattlerAlive(gBattlerAttacker)
&& !IsAbilityOnSide(gBattlerAttacker, ABILITY_AROMA_VEIL)
@@ -5692,7 +5602,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_MUMMY:
if (MoveResultHasEffect(battler)
&& IsBattlerAlive(gBattlerAttacker)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
&& IsMoveMakingContact(move, gBattlerAttacker)
&& gBattleStruct->overwrittenAbilities[gBattlerAttacker] != GetBattlerAbility(gBattlerTarget)
@@ -5717,7 +5627,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_WANDERING_SPIRIT:
if (MoveResultHasEffect(battler)
&& IsBattlerAlive(gBattlerAttacker)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
&& IsMoveMakingContact(move, gBattlerAttacker)
&& !(GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)
@@ -5741,7 +5651,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_ANGER_POINT:
if (MoveResultHasEffect(battler)
&& gSpecialStatuses[battler].criticalHit
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& IsBattlerAlive(battler)
&& CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
{
@@ -5755,7 +5665,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
if (MoveResultHasEffect(battler)
&& move != MOVE_STRUGGLE
&& gMovesInfo[move].power != 0
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& !IS_BATTLER_OF_TYPE(battler, moveType)
&& moveType != TYPE_STELLAR
&& moveType != TYPE_MYSTERY
@@ -5774,7 +5684,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
&& IsBattlerAlive(gBattlerAttacker)
&& (CompareStat(gBattlerAttacker, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN) || GetBattlerAbility(gBattlerAttacker) == ABILITY_MIRROR_ARMOR)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
&& IsMoveMakingContact(move, gBattlerAttacker))
{
@@ -5791,7 +5701,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
if (MoveResultHasEffect(gBattlerTarget)
&& IsBattlerAlive(gBattlerAttacker)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
&& IsMoveMakingContact(move, gBattlerAttacker))
{
@@ -5870,7 +5780,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
&& MoveResultHasEffect(gBattlerTarget)
&& IsBattlerAlive(gBattlerAttacker)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& CanBeSlept(gBattlerAttacker, ability, NOT_BLOCKED_BY_SLEEP_CLAUSE)
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
&& IsMoveMakingContact(move, gBattlerAttacker))
@@ -5894,7 +5804,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
if (MoveResultHasEffect(gBattlerTarget)
&& IsBattlerAlive(gBattlerAttacker)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& CanBePoisoned(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
&& IsMoveMakingContact(move, gBattlerAttacker))
@@ -5915,7 +5825,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
if (MoveResultHasEffect(gBattlerTarget)
&& IsBattlerAlive(gBattlerAttacker)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& CanBeParalyzed(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
&& IsMoveMakingContact(move, gBattlerAttacker))
@@ -5935,7 +5845,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
&& (IsMoveMakingContact(move, gBattlerAttacker))
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& CanBeBurned(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))
&& (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_FLAME_BODY, 30) : RandomChance(RNG_FLAME_BODY, 1, 3)))
{
@@ -5951,7 +5861,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
if (MoveResultHasEffect(gBattlerTarget)
&& IsBattlerAlive(gBattlerAttacker)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& IsBattlerAlive(gBattlerTarget)
&& (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_CUTE_CHARM, 30) : RandomChance(RNG_CUTE_CHARM, 1, 3))
&& !(gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION)
@@ -5968,7 +5878,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
}
break;
case ABILITY_ILLUSION:
- if (gBattleStruct->illusion[gBattlerTarget].on && !gBattleStruct->illusion[gBattlerTarget].broken && TARGET_TURN_DAMAGED)
+ if (gBattleStruct->illusion[gBattlerTarget].on && !gBattleStruct->illusion[gBattlerTarget].broken && IsBattlerTurnDamaged(gBattlerTarget))
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_IllusionOff;
@@ -5979,7 +5889,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
if (MoveResultHasEffect(gBattlerTarget)
&& IsBattlerAlive(gBattlerAttacker)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
- && TARGET_TURN_DAMAGED)
+ && IsBattlerTurnDamaged(gBattlerTarget))
{
gEffectBattler = gBattlerTarget;
BattleScriptPushCursor();
@@ -5989,7 +5899,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
break;
case ABILITY_STEAM_ENGINE:
if (MoveResultHasEffect(gBattlerTarget)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& IsBattlerAlive(battler)
&& CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN)
&& (moveType == TYPE_FIRE || moveType == TYPE_WATER))
@@ -6004,7 +5914,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_SAND_SPIT:
if (MoveResultHasEffect(gBattlerTarget)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& !(gBattleWeather & B_WEATHER_SANDSTORM && WEATHER_HAS_EFFECT))
{
if (gBattleWeather & B_WEATHER_PRIMAL_ANY && WEATHER_HAS_EFFECT)
@@ -6025,7 +5935,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_PERISH_BODY:
if (MoveResultHasEffect(gBattlerTarget)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& IsBattlerAlive(battler)
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
&& (IsMoveMakingContact(move, gBattlerAttacker))
@@ -6046,7 +5956,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_GULP_MISSILE:
if (MoveResultHasEffect(gBattlerTarget)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& IsBattlerAlive(battler)
&& gBattleMons[gBattlerTarget].species != SPECIES_CRAMORANT)
{
@@ -6077,7 +5987,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_SEED_SOWER:
if (MoveResultHasEffect(gBattlerTarget)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& IsBattlerAlive(gBattlerTarget)
&& TryChangeBattleTerrain(gBattlerTarget, STATUS_FIELD_GRASSY_TERRAIN, &gFieldTimers.terrainTimer))
{
@@ -6088,7 +5998,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
break;
case ABILITY_THERMAL_EXCHANGE:
if (MoveResultHasEffect(gBattlerTarget)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& IsBattlerAlive(gBattlerTarget)
&& CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)
&& moveType == TYPE_FIRE)
@@ -6103,7 +6013,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_ANGER_SHELL:
if (MoveResultHasEffect(gBattlerTarget)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& (gMultiHitCounter == 0 || gMultiHitCounter == 1) // Activates after all hits from a multi-hit move.
&& IsBattlerAlive(gBattlerTarget)
&& HadMoreThanHalfHpNowDoesnt(gBattlerTarget)
@@ -6121,7 +6031,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_ELECTROMORPHOSIS:
if (MoveResultHasEffect(gBattlerTarget)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& IsBattlerAlive(gBattlerTarget))
{
BattleScriptPushCursor();
@@ -6134,7 +6044,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
&& (!gBattleStruct->isSkyBattle)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
&& IS_MOVE_PHYSICAL(gCurrentMove)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& (gSideTimers[GetBattlerSide(gBattlerAttacker)].toxicSpikesAmount != 2))
{
SWAP(gBattlerAttacker, gBattlerTarget, i);
@@ -6155,7 +6065,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
&& CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget))
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
&& IsMoveMakingContact(move, gBattlerAttacker)
- && TARGET_TURN_DAMAGED // Need to actually hit the target
+ && IsBattlerTurnDamaged(gBattlerTarget) // Need to actually hit the target
&& RandomPercentage(RNG_POISON_TOUCH, 30))
{
gBattleScripting.moveEffect = MOVE_EFFECT_POISON;
@@ -6171,7 +6081,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
&& IsBattlerAlive(gBattlerTarget)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
&& CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget))
- && TARGET_TURN_DAMAGED // Need to actually hit the target
+ && IsBattlerTurnDamaged(gBattlerTarget) // Need to actually hit the target
&& RandomWeighted(RNG_TOXIC_CHAIN, 7, 3))
{
gBattleScripting.moveEffect = MOVE_EFFECT_TOXIC;
@@ -6187,7 +6097,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
&& IsBattlerAlive(gBattlerTarget)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
&& RandomChance(RNG_STENCH, 1, 10)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& !MoveHasAdditionalEffect(gCurrentMove, MOVE_EFFECT_FLINCH))
{
gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH;
@@ -6199,7 +6109,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
break;
case ABILITY_GULP_MISSILE:
if ((gBattleMons[gBattlerAttacker].species == SPECIES_CRAMORANT)
- && ((gCurrentMove == MOVE_SURF && TARGET_TURN_DAMAGED) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER)
+ && ((gCurrentMove == MOVE_SURF && IsBattlerTurnDamaged(gBattlerTarget)) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER)
&& TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT))
{
BattleScriptPushCursor();
@@ -7001,7 +6911,7 @@ static u8 TrySetEnigmaBerry(u32 battler)
{
if (IsBattlerAlive(battler)
&& !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)
- && ((BATTLER_TURN_DAMAGED(battler) && gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_SUPER_EFFECTIVE) || gBattleScripting.overrideBerryRequirements)
+ && ((IsBattlerTurnDamaged(battler) && gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_SUPER_EFFECTIVE) || gBattleScripting.overrideBerryRequirements)
&& !(gBattleScripting.overrideBerryRequirements && gBattleMons[battler].hp == gBattleMons[battler].maxHP)
&& (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)))
{
@@ -7025,7 +6935,7 @@ static u8 DamagedStatBoostBerryEffect(u32 battler, u8 statId, u8 category)
|| (!DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)
&& GetBattleMoveCategory(gCurrentMove) == category
&& battler != gBattlerAttacker
- && BATTLER_TURN_DAMAGED(battler)))
+ && IsBattlerTurnDamaged(battler)))
)
{
BufferStatChange(battler, statId, STRINGID_STATROSE);
@@ -8082,7 +7992,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
atkHoldEffectParam *= 2;
if (gBattleStruct->moveDamage[battler] != 0 // Need to have done damage
&& MoveResultHasEffect(gBattlerTarget)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& !gMovesInfo[gCurrentMove].ignoresKingsRock
&& gBattleMons[gBattlerTarget].hp
&& RandomPercentage(RNG_HOLD_EFFECT_FLINCH, atkHoldEffectParam)
@@ -8174,7 +8084,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
switch (battlerHoldEffect)
{
case HOLD_EFFECT_AIR_BALLOON:
- if (TARGET_TURN_DAMAGED)
+ if (IsBattlerTurnDamaged(gBattlerTarget))
{
effect = ITEM_EFFECT_OTHER;
BattleScriptPushCursor();
@@ -8182,7 +8092,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
}
break;
case HOLD_EFFECT_ROCKY_HELMET:
- if (TARGET_TURN_DAMAGED
+ if (IsBattlerTurnDamaged(gBattlerTarget)
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
&& IsMoveMakingContact(gCurrentMove, gBattlerAttacker)
&& IsBattlerAlive(gBattlerAttacker)
@@ -8200,7 +8110,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
break;
case HOLD_EFFECT_WEAKNESS_POLICY:
if (IsBattlerAlive(battler)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_SUPER_EFFECTIVE)
{
effect = ITEM_STATS_CHANGE;
@@ -8210,7 +8120,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
break;
case HOLD_EFFECT_SNOWBALL:
if (IsBattlerAlive(battler)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& moveType == TYPE_ICE)
{
effect = ITEM_STATS_CHANGE;
@@ -8221,7 +8131,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
break;
case HOLD_EFFECT_LUMINOUS_MOSS:
if (IsBattlerAlive(battler)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& moveType == TYPE_WATER)
{
effect = ITEM_STATS_CHANGE;
@@ -8232,7 +8142,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
break;
case HOLD_EFFECT_CELL_BATTERY:
if (IsBattlerAlive(battler)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& moveType == TYPE_ELECTRIC)
{
effect = ITEM_STATS_CHANGE;
@@ -8243,7 +8153,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
break;
case HOLD_EFFECT_ABSORB_BULB:
if (IsBattlerAlive(battler)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& moveType == TYPE_WATER)
{
effect = ITEM_STATS_CHANGE;
@@ -8257,7 +8167,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
break;
case HOLD_EFFECT_JABOCA_BERRY: // consume and damage attacker if used physical move
if (IsBattlerAlive(battler)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)
&& IS_MOVE_PHYSICAL(gCurrentMove)
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD)
@@ -8277,7 +8187,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
break;
case HOLD_EFFECT_ROWAP_BERRY: // consume and damage attacker if used special move
if (IsBattlerAlive(battler)
- && TARGET_TURN_DAMAGED
+ && IsBattlerTurnDamaged(gBattlerTarget)
&& !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)
&& IS_MOVE_SPECIAL(gCurrentMove)
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD)
@@ -8314,7 +8224,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
}
break;
case HOLD_EFFECT_STICKY_BARB:
- if (TARGET_TURN_DAMAGED
+ if (IsBattlerTurnDamaged(gBattlerTarget)
&& MoveResultHasEffect(gBattlerTarget)
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
&& IsMoveMakingContact(gCurrentMove, gBattlerAttacker)
@@ -8697,7 +8607,7 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move)
&& IsMoveMakingContact(move, gBattlerAttacker)
&& GetBattlerAbility(gBattlerAttacker) == ABILITY_UNSEEN_FIST)
isProtected = FALSE;
- else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_CRAFTY_SHIELD && IS_MOVE_STATUS(move))
+ else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_CRAFTY_SHIELD && IS_MOVE_STATUS(move) && gMovesInfo[move].effect != EFFECT_COACHING)
isProtected = TRUE;
else if (gMovesInfo[move].ignoresProtect)
isProtected = FALSE;
@@ -9054,7 +8964,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData
basePower *= 2;
break;
case EFFECT_PURSUIT:
- if (gActionsByTurnOrder[GetBattlerTurnOrderNum(battlerDef)] == B_ACTION_SWITCH)
+ if (gBattleStruct->pursuitTarget & (1u << battlerDef))
basePower *= 2;
break;
case EFFECT_NATURAL_GIFT:
@@ -9302,7 +9212,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageCalculationData *
if (gProtectStructs[battlerAtk].helpingHand)
modifier = uq4_12_multiply(modifier, UQ_4_12(1.5));
if (gSpecialStatuses[battlerAtk].gemBoost)
- modifier = uq4_12_multiply(modifier, UQ_4_12(1.0) + sPercentToModifier[gSpecialStatuses[battlerAtk].gemParam]);
+ modifier = uq4_12_multiply(modifier, uq4_12_add(UQ_4_12(1.0), PercentToUQ4_12(gSpecialStatuses[battlerAtk].gemParam)));
if (gStatuses3[battlerAtk] & STATUS3_CHARGED_UP && moveType == TYPE_ELECTRIC)
modifier = uq4_12_multiply(modifier, UQ_4_12(2.0));
if (gStatuses3[battlerAtk] & STATUS3_ME_FIRST)
@@ -9491,18 +9401,18 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageCalculationData *
if (holdEffectParamAtk > 100)
holdEffectParamAtk = 100;
- holdEffectModifier = UQ_4_12(1.0) + sPercentToModifier[holdEffectParamAtk];
+ holdEffectModifier = uq4_12_add(UQ_4_12(1.0), PercentToUQ4_12(holdEffectParamAtk));
// attacker's hold effect
switch (holdEffectAtk)
{
case HOLD_EFFECT_MUSCLE_BAND:
if (IS_MOVE_PHYSICAL(move))
- modifier = uq4_12_multiply(modifier, holdEffectModifier);
+ modifier = uq4_12_multiply(modifier, uq4_12_add(UQ_4_12(1.0), PercentToUQ4_12_Floored(holdEffectParamAtk)));
break;
case HOLD_EFFECT_WISE_GLASSES:
if (IS_MOVE_SPECIAL(move))
- modifier = uq4_12_multiply(modifier, holdEffectModifier);
+ modifier = uq4_12_multiply(modifier, uq4_12_add(UQ_4_12(1.0), PercentToUQ4_12_Floored(holdEffectParamAtk)));
break;
case HOLD_EFFECT_LUSTROUS_ORB:
if (GET_BASE_SPECIES_ID(gBattleMons[battlerAtk].species) == SPECIES_PALKIA && (moveType == TYPE_WATER || moveType == TYPE_DRAGON))
@@ -9768,11 +9678,11 @@ static inline u32 CalcAttackStat(struct DamageCalculationData *damageCalcData, u
break;
case ABILITY_ORICHALCUM_PULSE:
if ((weather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT && IS_MOVE_PHYSICAL(move))
- modifier = uq4_12_multiply(modifier, UQ_4_12(1.33));
+ modifier = uq4_12_multiply(modifier, UQ_4_12(1.3333));
break;
case ABILITY_HADRON_ENGINE:
if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && IS_MOVE_SPECIAL(move))
- modifier = uq4_12_multiply(modifier, UQ_4_12(1.33));
+ modifier = uq4_12_multiply(modifier, UQ_4_12(1.3333));
break;
}
@@ -10191,7 +10101,7 @@ static inline uq4_12_t GetDefenderAbilitiesModifier(u32 move, u32 moveType, u32
{
case ABILITY_MULTISCALE:
case ABILITY_SHADOW_SHIELD:
- if (BATTLER_MAX_HP(battlerDef))
+ if (IsBattlerAtMaxHp(battlerDef))
return UQ_4_12(0.5);
break;
case ABILITY_FILTER:
@@ -10234,19 +10144,23 @@ static inline uq4_12_t GetDefenderPartnerAbilitiesModifier(u32 battlerPartnerDef
static inline uq4_12_t GetAttackerItemsModifier(u32 battlerAtk, uq4_12_t typeEffectivenessModifier, u32 holdEffectAtk)
{
- u32 percentBoost;
+ u32 metronomeTurns;
+ uq4_12_t metronomeBoostBase;
switch (holdEffectAtk)
{
case HOLD_EFFECT_METRONOME:
- percentBoost = min((gBattleStruct->sameMoveTurns[battlerAtk] * GetBattlerHoldEffectParam(battlerAtk)), 100);
- return uq4_12_add(sPercentToModifier[percentBoost], UQ_4_12(1.0));
+ metronomeBoostBase = PercentToUQ4_12(GetBattlerHoldEffectParam(battlerAtk));
+ metronomeTurns = min(gBattleStruct->sameMoveTurns[battlerAtk], 5);
+ // according to bulbapedia this is the "correct" way to calculate the metronome boost
+ // due to the limited domain of damage numbers it will never really matter whether this is off by one
+ return uq4_12_add(UQ_4_12(1.0), metronomeBoostBase * metronomeTurns);
break;
case HOLD_EFFECT_EXPERT_BELT:
if (typeEffectivenessModifier >= UQ_4_12(2.0))
return UQ_4_12(1.2);
break;
case HOLD_EFFECT_LIFE_ORB:
- return UQ_4_12(1.3);
+ return UQ_4_12_FLOORED(1.3);
break;
}
return UQ_4_12(1.0);
@@ -11284,7 +11198,7 @@ u8 GetBattleMoveCategory(u32 moveId)
if (IS_MOVE_STATUS(moveId))
return DAMAGE_CATEGORY_STATUS;
- return gTypesInfo[GetMoveType(gCurrentMove)].damageCategory;
+ return gTypesInfo[GetMoveType(moveId)].damageCategory;
}
static bool32 TryRemoveScreens(u32 battler)
@@ -12099,3 +12013,12 @@ void ClearDamageCalcResults(void)
gBattleStruct->printedStrongWindsWeakenedAttack = FALSE;
gBattleStruct->numSpreadTargets = 0;
}
+
+bool32 DoesDestinyBondFail(u32 battler)
+{
+ if (B_DESTINY_BOND_FAIL >= GEN_7
+ && gMovesInfo[gLastResultingMoves[battler]].effect == EFFECT_DESTINY_BOND
+ && !(gBattleStruct->lastMoveFailed & (1u << battler)))
+ return TRUE;
+ return FALSE;
+}
diff --git a/src/data/graphics/pokemon.h b/src/data/graphics/pokemon.h
index 39b11560d4..8801942e53 100644
--- a/src/data/graphics/pokemon.h
+++ b/src/data/graphics/pokemon.h
@@ -18880,7 +18880,7 @@ const u32 gObjectEventPic_Substitute[] = INCBIN_COMP("graphics/pokemon/question_
#endif //P_FAMILY_LANDORUS
#if P_FAMILY_ENAMORUS
- const u32 gMonFrontPic_EnamorusIncarnate[] = INCBIN_U32("graphics/pokemon/enamorus/front.4bpp.lz");
+ const u32 gMonFrontPic_EnamorusIncarnate[] = INCBIN_U32("graphics/pokemon/enamorus/anim_front.4bpp.lz");
const u32 gMonPalette_EnamorusIncarnate[] = INCBIN_U32("graphics/pokemon/enamorus/normal.gbapal.lz");
const u32 gMonBackPic_EnamorusIncarnate[] = INCBIN_U32("graphics/pokemon/enamorus/back.4bpp.lz");
const u32 gMonShinyPalette_EnamorusIncarnate[] = INCBIN_U32("graphics/pokemon/enamorus/shiny.gbapal.lz");
diff --git a/src/data/pokemon/species_info/gen_8_families.h b/src/data/pokemon/species_info/gen_8_families.h
index 37eefda7f9..ee08542523 100644
--- a/src/data/pokemon/species_info/gen_8_families.h
+++ b/src/data/pokemon/species_info/gen_8_families.h
@@ -2655,7 +2655,7 @@ const struct SpeciesInfo gSpeciesInfoGen8[] =
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_Dipplin,
.backPicSize = MON_COORDS_SIZE(64, 64),
- .backPicYOffset = 0,
+ .backPicYOffset = 1,
//.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_Dipplin,
.shinyPalette = gMonShinyPalette_Dipplin,
@@ -7660,7 +7660,7 @@ const struct SpeciesInfo gSpeciesInfoGen8[] =
.trainerOffset = 1,
.frontPic = gMonFrontPic_EnamorusIncarnate,
.frontPicSize = MON_COORDS_SIZE(64, 64),
- .frontPicYOffset = 1,
+ .frontPicYOffset = 0,
.frontAnimFrames = sAnims_EnamorusIncarnate,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.enemyMonElevation = 7,
@@ -7672,7 +7672,7 @@ const struct SpeciesInfo gSpeciesInfoGen8[] =
.shinyPalette = gMonShinyPalette_EnamorusIncarnate,
.iconSprite = gMonIcon_EnamorusIncarnate,
.iconPalIndex = 1,
- SHADOW(0, 17, SHADOW_SIZE_M)
+ SHADOW(-3, 19, SHADOW_SIZE_M)
FOOTPRINT(Enamorus)
OVERWORLD(
sPicTable_EnamorusIncarnate,
@@ -7730,7 +7730,7 @@ const struct SpeciesInfo gSpeciesInfoGen8[] =
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_EnamorusTherian,
.backPicSize = MON_COORDS_SIZE(64, 64),
- .backPicYOffset = 2,
+ .backPicYOffset = 0,
//.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_EnamorusTherian,
.shinyPalette = gMonShinyPalette_EnamorusTherian,
diff --git a/src/data/pokemon/species_info/gen_9_families.h b/src/data/pokemon/species_info/gen_9_families.h
index d617d36f1b..7402619b9a 100644
--- a/src/data/pokemon/species_info/gen_9_families.h
+++ b/src/data/pokemon/species_info/gen_9_families.h
@@ -7086,13 +7086,13 @@ const struct SpeciesInfo gSpeciesInfoGen9[] =
.trainerOffset = 0,
.frontPic = gMonFrontPic_Sinistcha,
.frontPicSize = MON_COORDS_SIZE(64, 64),
- .frontPicYOffset = 10,
+ .frontPicYOffset = 3,
.frontAnimFrames = sAnims_Sinistcha,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.enemyMonElevation = 10,
.backPic = gMonBackPic_Sinistcha,
.backPicSize = MON_COORDS_SIZE(64, 64),
- .backPicYOffset = 13,
+ .backPicYOffset = 4,
//.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_Sinistcha,
.shinyPalette = gMonShinyPalette_Sinistcha,
@@ -7147,13 +7147,13 @@ const struct SpeciesInfo gSpeciesInfoGen9[] =
.trainerOffset = 0,
.frontPic = gMonFrontPic_Sinistcha,
.frontPicSize = MON_COORDS_SIZE(64, 64),
- .frontPicYOffset = 10,
+ .frontPicYOffset = 3,
.frontAnimFrames = sAnims_Sinistcha,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.enemyMonElevation = 10,
.backPic = gMonBackPic_Sinistcha,
.backPicSize = MON_COORDS_SIZE(64, 64),
- .backPicYOffset = 13,
+ .backPicYOffset = 4,
//.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_Sinistcha,
.shinyPalette = gMonShinyPalette_Sinistcha,
@@ -7370,78 +7370,78 @@ const struct SpeciesInfo gSpeciesInfoGen9[] =
#endif //P_FAMILY_FEZANDIPITI
#if P_FAMILY_OGERPON
-#define OGERPON_SPECIES_INFO(Form1, Form2, type, ability, color, iconpalette, isTeraform) \
- { \
- .baseHP = 80, \
- .baseAttack = 120, \
- .baseDefense = 84, \
- .baseSpeed = 110, \
- .baseSpAttack = 60, \
- .baseSpDefense = 96, \
- .types = MON_TYPES(TYPE_GRASS, type), \
- .forceTeraType = type, \
- .catchRate = 5, \
- .expYield = 275, \
- .evYield_Attack = 3, \
- .genderRatio = MON_FEMALE, \
- .eggCycles = 10, \
- .friendship = STANDARD_FRIENDSHIP, \
- .growthRate = GROWTH_SLOW, \
- .eggGroups = MON_EGG_GROUPS(EGG_GROUP_NO_EGGS_DISCOVERED), \
- .abilities = { ability, ABILITY_NONE }, \
- .bodyColor = color, \
- .speciesName = _("Ogerpon"), \
- .cryId = CRY_OGERPON, \
- .natDexNum = NATIONAL_DEX_OGERPON, \
- .categoryName = _("Mask"), \
- .height = 12, \
- .weight = 398, \
- .description = gOgerpon##Form1##MaskPokedexText, \
- .pokemonScale = 356, \
- .pokemonOffset = 17, \
- .trainerScale = 256, \
- .trainerOffset = 0, \
- .frontPic = gMonFrontPic_Ogerpon##Form2, \
- .frontPicSize = MON_COORDS_SIZE(64, 64), \
- .frontPicYOffset = 0, \
- .frontAnimFrames = sAnims_Ogerpon, \
- /*.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,*/ \
- .backPic = gMonBackPic_Ogerpon##Form2, \
- .backPicSize = MON_COORDS_SIZE(64, 64), \
- .backPicYOffset = 0, \
- /*.backAnimId = BACK_ANIM_NONE,*/ \
- .palette = gMonPalette_Ogerpon##Form2, \
- .shinyPalette = gMonShinyPalette_Ogerpon##Form2, \
- .iconSprite = gMonIcon_Ogerpon##Form1, \
- .iconPalIndex = iconpalette, \
- SHADOW(7, 13, SHADOW_SIZE_L) \
- FOOTPRINT(Ogerpon) \
- OVERWORLD( \
- sPicTable_Ogerpon##Form2, \
- SIZE_32x32, \
- SHADOW_SIZE_M, \
- TRACKS_FOOT, \
- gOverworldPalette_Ogerpon##Form2, \
- gShinyOverworldPalette_Ogerpon##Form2 \
- ) \
- .levelUpLearnset = sOgerponLevelUpLearnset, \
- .teachableLearnset = sOgerponTeachableLearnset, \
- .formSpeciesIdTable = sOgerponFormSpeciesIdTable, \
- .formChangeTable = sOgerponFormChangeTable, \
- .isLegendary = TRUE, \
- .isTeraForm = isTeraform, \
- .perfectIVCount = LEGENDARY_PERFECT_IV_COUNT, \
+#define OGERPON_SPECIES_INFO(Form1, Form2, type, ability, color, frontYOffset, backYOffset, iconpalette, isTeraform) \
+ { \
+ .baseHP = 80, \
+ .baseAttack = 120, \
+ .baseDefense = 84, \
+ .baseSpeed = 110, \
+ .baseSpAttack = 60, \
+ .baseSpDefense = 96, \
+ .types = MON_TYPES(TYPE_GRASS, type), \
+ .forceTeraType = type, \
+ .catchRate = 5, \
+ .expYield = 275, \
+ .evYield_Attack = 3, \
+ .genderRatio = MON_FEMALE, \
+ .eggCycles = 10, \
+ .friendship = STANDARD_FRIENDSHIP, \
+ .growthRate = GROWTH_SLOW, \
+ .eggGroups = MON_EGG_GROUPS(EGG_GROUP_NO_EGGS_DISCOVERED), \
+ .abilities = { ability, ABILITY_NONE }, \
+ .bodyColor = color, \
+ .speciesName = _("Ogerpon"), \
+ .cryId = CRY_OGERPON, \
+ .natDexNum = NATIONAL_DEX_OGERPON, \
+ .categoryName = _("Mask"), \
+ .height = 12, \
+ .weight = 398, \
+ .description = gOgerpon##Form1##MaskPokedexText, \
+ .pokemonScale = 356, \
+ .pokemonOffset = 17, \
+ .trainerScale = 256, \
+ .trainerOffset = 0, \
+ .frontPic = gMonFrontPic_Ogerpon##Form2, \
+ .frontPicSize = MON_COORDS_SIZE(64, 64), \
+ .frontPicYOffset = frontYOffset, \
+ .frontAnimFrames = sAnims_Ogerpon, \
+ /*.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,*/ \
+ .backPic = gMonBackPic_Ogerpon##Form2, \
+ .backPicSize = MON_COORDS_SIZE(64, 64), \
+ .backPicYOffset = backYOffset, \
+ /*.backAnimId = BACK_ANIM_NONE,*/ \
+ .palette = gMonPalette_Ogerpon##Form2, \
+ .shinyPalette = gMonShinyPalette_Ogerpon##Form2, \
+ .iconSprite = gMonIcon_Ogerpon##Form1, \
+ .iconPalIndex = iconpalette, \
+ SHADOW(7, 13, SHADOW_SIZE_L) \
+ FOOTPRINT(Ogerpon) \
+ OVERWORLD( \
+ sPicTable_Ogerpon##Form2, \
+ SIZE_32x32, \
+ SHADOW_SIZE_M, \
+ TRACKS_FOOT, \
+ gOverworldPalette_Ogerpon##Form2, \
+ gShinyOverworldPalette_Ogerpon##Form2 \
+ ) \
+ .levelUpLearnset = sOgerponLevelUpLearnset, \
+ .teachableLearnset = sOgerponTeachableLearnset, \
+ .formSpeciesIdTable = sOgerponFormSpeciesIdTable, \
+ .formChangeTable = sOgerponFormChangeTable, \
+ .isLegendary = TRUE, \
+ .isTeraForm = isTeraform, \
+ .perfectIVCount = LEGENDARY_PERFECT_IV_COUNT, \
}
- [SPECIES_OGERPON_TEAL] = OGERPON_SPECIES_INFO(Teal, Teal, TYPE_GRASS, ABILITY_DEFIANT, BODY_COLOR_GREEN, 1, FALSE),
- [SPECIES_OGERPON_WELLSPRING] = OGERPON_SPECIES_INFO(Wellspring, Wellspring, TYPE_WATER, ABILITY_WATER_ABSORB, BODY_COLOR_BLUE, 0, FALSE),
- [SPECIES_OGERPON_HEARTHFLAME] = OGERPON_SPECIES_INFO(Hearthflame, Hearthflame, TYPE_FIRE, ABILITY_MOLD_BREAKER, BODY_COLOR_RED, 0, FALSE),
- [SPECIES_OGERPON_CORNERSTONE] = OGERPON_SPECIES_INFO(Cornerstone, Cornerstone, TYPE_ROCK, ABILITY_STURDY, BODY_COLOR_GRAY, 0, FALSE),
+ [SPECIES_OGERPON_TEAL] = OGERPON_SPECIES_INFO(Teal, Teal, TYPE_GRASS, ABILITY_DEFIANT, BODY_COLOR_GREEN, 1, 7, 1, FALSE),
+ [SPECIES_OGERPON_WELLSPRING] = OGERPON_SPECIES_INFO(Wellspring, Wellspring, TYPE_WATER, ABILITY_WATER_ABSORB, BODY_COLOR_BLUE, 1, 7, 0, FALSE),
+ [SPECIES_OGERPON_HEARTHFLAME] = OGERPON_SPECIES_INFO(Hearthflame, Hearthflame, TYPE_FIRE, ABILITY_MOLD_BREAKER, BODY_COLOR_RED, 1, 7, 0, FALSE),
+ [SPECIES_OGERPON_CORNERSTONE] = OGERPON_SPECIES_INFO(Cornerstone, Cornerstone, TYPE_ROCK, ABILITY_STURDY, BODY_COLOR_GRAY, 1, 7, 0, FALSE),
#if P_TERA_FORMS
- [SPECIES_OGERPON_TEAL_TERA] = OGERPON_SPECIES_INFO(Teal, TealTera, TYPE_GRASS, ABILITY_EMBODY_ASPECT_TEAL_MASK, BODY_COLOR_GREEN, 1, TRUE),
- [SPECIES_OGERPON_WELLSPRING_TERA] = OGERPON_SPECIES_INFO(Wellspring, WellspringTera, TYPE_WATER, ABILITY_EMBODY_ASPECT_WELLSPRING_MASK, BODY_COLOR_BLUE, 0, TRUE),
- [SPECIES_OGERPON_HEARTHFLAME_TERA] = OGERPON_SPECIES_INFO(Hearthflame, HearthflameTera, TYPE_FIRE, ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK, BODY_COLOR_RED, 0, TRUE),
- [SPECIES_OGERPON_CORNERSTONE_TERA] = OGERPON_SPECIES_INFO(Cornerstone, CornerstoneTera, TYPE_ROCK, ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK, BODY_COLOR_GRAY, 0, TRUE),
+ [SPECIES_OGERPON_TEAL_TERA] = OGERPON_SPECIES_INFO(Teal, TealTera, TYPE_GRASS, ABILITY_EMBODY_ASPECT_TEAL_MASK, BODY_COLOR_GREEN, 0, 0, 1, TRUE),
+ [SPECIES_OGERPON_WELLSPRING_TERA] = OGERPON_SPECIES_INFO(Wellspring, WellspringTera, TYPE_WATER, ABILITY_EMBODY_ASPECT_WELLSPRING_MASK, BODY_COLOR_BLUE, 0, 0, 0, TRUE),
+ [SPECIES_OGERPON_HEARTHFLAME_TERA] = OGERPON_SPECIES_INFO(Hearthflame, HearthflameTera, TYPE_FIRE, ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK, BODY_COLOR_RED, 0, 0, 0, TRUE),
+ [SPECIES_OGERPON_CORNERSTONE_TERA] = OGERPON_SPECIES_INFO(Cornerstone, CornerstoneTera, TYPE_ROCK, ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK, BODY_COLOR_GRAY, 0, 0, 0, TRUE),
#endif //P_TERA_FORMS
#endif //P_FAMILY_OGERPON
diff --git a/src/data/pokemon_graphics/front_pic_anims.h b/src/data/pokemon_graphics/front_pic_anims.h
index deceeb0420..56ec319a57 100644
--- a/src/data/pokemon_graphics/front_pic_anims.h
+++ b/src/data/pokemon_graphics/front_pic_anims.h
@@ -9794,7 +9794,7 @@ PLACEHOLDER_ANIM_SINGLE_FRAME(Calyrex);
#endif //P_FAMILY_CALYREX
#if P_FAMILY_ENAMORUS
-PLACEHOLDER_ANIM_SINGLE_FRAME(EnamorusIncarnate);
+PLACEHOLDER_ANIM_TWO_FRAMES(EnamorusIncarnate);
PLACEHOLDER_ANIM_SINGLE_FRAME(EnamorusTherian);
#endif //P_FAMILY_ENAMORUS
diff --git a/src/debug.c b/src/debug.c
index 590e415b7e..3615ef1997 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -159,7 +159,7 @@ enum FlagsVarsDebugMenu
DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS,
DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL,
DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS,
- DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLISSION,
+ DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLLISION,
DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER,
DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE,
DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE,
@@ -788,7 +788,7 @@ static const struct ListMenuItem sDebugMenu_Items_FlagsVars[] =
[DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS] = {sDebugText_FlagsVars_ToggleFlyFlags, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS},
[DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL] = {sDebugText_FlagsVars_ToggleAllBadges, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL},
[DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS] = {sDebugText_FlagsVars_ToggleFrontierPass, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS},
- [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLISSION] = {sDebugText_FlagsVars_SwitchCollision, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLISSION},
+ [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLLISION] = {sDebugText_FlagsVars_SwitchCollision, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLLISION},
[DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER] = {sDebugText_FlagsVars_SwitchEncounter, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER},
[DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE] = {sDebugText_FlagsVars_SwitchTrainerSee, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE},
[DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE] = {sDebugText_FlagsVars_SwitchBagUse, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE},
@@ -959,7 +959,7 @@ static void (*const sDebugMenu_Actions_Flags[])(u8) =
[DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS] = DebugAction_FlagsVars_ToggleFlyFlags,
[DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL] = DebugAction_FlagsVars_ToggleBadgeFlags,
[DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS] = DebugAction_FlagsVars_ToggleFrontierPass,
- [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLISSION] = DebugAction_FlagsVars_CollisionOnOff,
+ [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLLISION] = DebugAction_FlagsVars_CollisionOnOff,
[DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER] = DebugAction_FlagsVars_EncounterOnOff,
[DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE] = DebugAction_FlagsVars_TrainerSeeOnOff,
[DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE] = DebugAction_FlagsVars_BagUseOnOff,
@@ -1312,7 +1312,7 @@ static u8 Debug_CheckToggleFlags(u8 id)
result = FlagGet(FLAG_SYS_FRONTIER_PASS);
break;
#if OW_FLAG_NO_COLLISION != 0
- case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLISSION:
+ case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLLISION:
result = FlagGet(OW_FLAG_NO_COLLISION);
break;
#endif
@@ -1927,7 +1927,7 @@ static void DebugAction_Util_Warp_Warp(u8 taskId)
StringExpandPlaceholders(gStringVar1, sDebugText_Util_WarpToMap_SelMax);
StringCopy(gStringVar3, gText_DigitIndicator[0]);
StringExpandPlaceholders(gStringVar4, sDebugText_Util_WarpToMap_SelectMapGroup);
- AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Util_Warp_SelectMapGroup;
gTasks[taskId].tSubWindowId = windowId;
@@ -1971,7 +1971,7 @@ static void DebugAction_Util_Warp_SelectMapGroup(u8 taskId)
StringExpandPlaceholders(gStringVar1, sDebugText_Util_WarpToMap_SelMax);
StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]);
StringExpandPlaceholders(gStringVar4, sDebugText_Util_WarpToMap_SelectMapGroup);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
if (JOY_NEW(A_BUTTON))
@@ -1986,7 +1986,7 @@ static void DebugAction_Util_Warp_SelectMapGroup(u8 taskId)
GetMapName(gStringVar2, Overworld_GetMapHeaderByGroupAndId(gTasks[taskId].tMapGroup, gTasks[taskId].tInput)->regionMapSectionId, 0);
StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]);
StringExpandPlaceholders(gStringVar4, sDebugText_Util_WarpToMap_SelectMap);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Util_Warp_SelectMap;
}
@@ -2033,7 +2033,7 @@ static void DebugAction_Util_Warp_SelectMap(u8 taskId)
GetMapName(gStringVar2, Overworld_GetMapHeaderByGroupAndId(gTasks[taskId].tMapGroup, gTasks[taskId].tInput)->regionMapSectionId, 0);
StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]);
StringExpandPlaceholders(gStringVar4, sDebugText_Util_WarpToMap_SelectMap);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
if (JOY_NEW(A_BUTTON))
@@ -2045,7 +2045,7 @@ static void DebugAction_Util_Warp_SelectMap(u8 taskId)
StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]);
ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3);
StringExpandPlaceholders(gStringVar4, sDebugText_Util_WarpToMap_SelectWarp);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Util_Warp_SelectWarp;
}
else if (JOY_NEW(B_BUTTON))
@@ -2076,7 +2076,7 @@ static void DebugAction_Util_Warp_SelectWarp(u8 taskId)
StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]);
ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3);
StringExpandPlaceholders(gStringVar4, sDebugText_Util_WarpToMap_SelectWarp);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
if (JOY_NEW(A_BUTTON))
@@ -2236,7 +2236,7 @@ static void DebugAction_Util_Weather(u8 taskId)
ConvertIntToDecimalStringN(gStringVar3, 1, STR_CONV_MODE_LEADING_ZEROS, 2);
StringCopyPadded(gStringVar1, sWeatherNames[0], CHAR_SPACE, 30);
StringExpandPlaceholders(gStringVar4, sDebugText_Util_Weather_ID);
- AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Util_Weather_SelectId;
gTasks[taskId].tSubWindowId = windowId;
@@ -2282,7 +2282,7 @@ static void DebugAction_Util_Weather_SelectId(u8 taskId)
StringCopyPadded(gStringVar1, sDebugText_WeatherNotDefined, CHAR_SPACE, 30);
StringExpandPlaceholders(gStringVar4, sDebugText_Util_Weather_ID);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
if (JOY_NEW(A_BUTTON))
@@ -2445,7 +2445,7 @@ static void DebugAction_FlagsVars_Flags(u8 taskId)
StringCopyPadded(gStringVar2, sDebugText_False, CHAR_SPACE, 15);
StringCopy(gStringVar3, gText_DigitIndicator[0]);
StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_Flag);
- AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_FlagsVars_FlagsSelect;
gTasks[taskId].tSubWindowId = windowId;
@@ -2506,7 +2506,7 @@ static void DebugAction_FlagsVars_FlagsSelect(u8 taskId)
StringCopyPadded(gStringVar2, sDebugText_False, CHAR_SPACE, 15);
StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]);
StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_Flag);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
}
@@ -2534,7 +2534,7 @@ static void DebugAction_FlagsVars_Vars(u8 taskId)
StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15);
StringCopy(gStringVar2, gText_DigitIndicator[0]);
StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_Variable);
- AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_FlagsVars_Select;
gTasks[taskId].tSubWindowId = windowId;
@@ -2586,7 +2586,7 @@ static void DebugAction_FlagsVars_Select(u8 taskId)
//Combine str's to full window string
StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_Variable);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
if (JOY_NEW(A_BUTTON))
@@ -2606,7 +2606,7 @@ static void DebugAction_FlagsVars_Select(u8 taskId)
StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15);
StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]);
StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_VariableValueSet);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].data[6] = gTasks[taskId].data[5]; //New value selector
gTasks[taskId].func = DebugAction_FlagsVars_SetValue;
@@ -2674,7 +2674,7 @@ static void DebugAction_FlagsVars_SetValue(u8 taskId)
StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15);
StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]);
StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_VariableValueSet);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
}
@@ -2960,10 +2960,11 @@ static void DebugAction_Give_Item(u8 taskId)
// Display initial item
StringCopy(gStringVar2, gText_DigitIndicator[0]);
ConvertIntToDecimalStringN(gStringVar3, 1, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS);
- CopyItemName(1, gStringVar1);
+ u8* end = CopyItemName(1, gStringVar1);
+ WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(windowId));
StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15);
StringExpandPlaceholders(gStringVar4, sDebugText_ItemID);
- AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Give_Item_SelectId;
gTasks[taskId].tSubWindowId = windowId;
@@ -3005,11 +3006,12 @@ static void DebugAction_Give_Item_SelectId(u8 taskId)
}
StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]);
- CopyItemName(gTasks[taskId].tInput, gStringVar1);
+ u8* end = CopyItemName(gTasks[taskId].tInput, gStringVar1);
+ WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(gTasks[taskId].tSubWindowId));
StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15);
ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS);
StringExpandPlaceholders(gStringVar4, sDebugText_ItemID);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
FreeSpriteTilesByTag(ITEM_TAG); //Destroy item icon
FreeSpritePaletteByTag(ITEM_TAG); //Destroy item icon
@@ -3031,7 +3033,7 @@ static void DebugAction_Give_Item_SelectId(u8 taskId)
ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEM_QUANTITY);
StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15);
StringExpandPlaceholders(gStringVar4, sDebugText_ItemQuantity);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Give_Item_SelectQuantity;
}
@@ -3082,7 +3084,7 @@ static void DebugAction_Give_Item_SelectQuantity(u8 taskId)
ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEM_QUANTITY);
StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15);
StringExpandPlaceholders(gStringVar4, sDebugText_ItemQuantity);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
if (JOY_NEW(A_BUTTON))
@@ -3158,11 +3160,12 @@ static void DebugAction_Give_PokemonSimple(u8 taskId)
// Display initial Pokémon
StringCopy(gStringVar2, gText_DigitIndicator[0]);
- ConvertIntToDecimalStringN(gStringVar3, sDebugMonData->species, STR_CONV_MODE_LEADING_ZEROS, 3);
- StringCopy(gStringVar1, GetSpeciesName(sDebugMonData->species));
+ ConvertIntToDecimalStringN(gStringVar3, sDebugMonData->species, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS);
+ u8 *end = StringCopy(gStringVar1, GetSpeciesName(sDebugMonData->species));
+ WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(windowId));
StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15);
StringExpandPlaceholders(gStringVar4, sDebugText_PokemonID);
- AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
//Set task data
gTasks[taskId].func = DebugAction_Give_Pokemon_SelectId;
@@ -3198,11 +3201,12 @@ static void DebugAction_Give_PokemonComplex(u8 taskId)
// Display initial Pokémon
StringCopy(gStringVar2, gText_DigitIndicator[0]);
- ConvertIntToDecimalStringN(gStringVar3, sDebugMonData->species, STR_CONV_MODE_LEADING_ZEROS, 4);
- StringCopy(gStringVar1, GetSpeciesName(sDebugMonData->species));
+ ConvertIntToDecimalStringN(gStringVar3, sDebugMonData->species, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS);
+ u8 *end = StringCopy(gStringVar1, GetSpeciesName(sDebugMonData->species));
+ WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(windowId));
StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15);
StringExpandPlaceholders(gStringVar4, sDebugText_PokemonID);
- AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Give_Pokemon_SelectId;
gTasks[taskId].tSubWindowId = windowId;
@@ -3247,11 +3251,12 @@ static void DebugAction_Give_Pokemon_SelectId(u8 taskId)
}
StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]);
- StringCopy(gStringVar1, GetSpeciesName(gTasks[taskId].tInput)); //CopyItemName(gTasks[taskId].tInput, gStringVar1);
+ u8 *end = StringCopy(gStringVar1, GetSpeciesName(gTasks[taskId].tInput)); //CopyItemName(gTasks[taskId].tInput, gStringVar1);
+ WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(gTasks[taskId].tSubWindowId));
StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15);
- ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 4);
+ ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS);
StringExpandPlaceholders(gStringVar4, sDebugText_PokemonID);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
FreeAndDestroyMonIconSprite(&gSprites[gTasks[taskId].tSpriteId]);
FreeMonIconPalettes();
@@ -3270,7 +3275,7 @@ static void DebugAction_Give_Pokemon_SelectId(u8 taskId)
ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3);
StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15);
StringExpandPlaceholders(gStringVar4, sDebugText_PokemonLevel);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Give_Pokemon_SelectLevel;
}
@@ -3317,7 +3322,7 @@ static void DebugAction_Give_Pokemon_SelectLevel(u8 taskId)
ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3);
StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15);
StringExpandPlaceholders(gStringVar4, sDebugText_PokemonLevel);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
if (JOY_NEW(A_BUTTON))
@@ -3343,7 +3348,7 @@ static void DebugAction_Give_Pokemon_SelectLevel(u8 taskId)
StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15);
StringCopyPadded(gStringVar2, sDebugText_False, CHAR_SPACE, 15);
StringExpandPlaceholders(gStringVar4, sDebugText_PokemonShiny);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Give_Pokemon_SelectShiny;
}
@@ -3371,7 +3376,7 @@ static void DebugAction_Give_Pokemon_SelectShiny(u8 taskId)
ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 0);
StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15);
StringExpandPlaceholders(gStringVar4, sDebugText_PokemonShiny);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
if (JOY_NEW(A_BUTTON))
@@ -3385,7 +3390,7 @@ static void DebugAction_Give_Pokemon_SelectShiny(u8 taskId)
StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15);
StringCopy(gStringVar1, gNaturesInfo[0].name);
StringExpandPlaceholders(gStringVar4, sDebugText_PokemonNature);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Give_Pokemon_SelectNature;
}
@@ -3421,7 +3426,7 @@ static void DebugAction_Give_Pokemon_SelectNature(u8 taskId)
StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15);
StringCopy(gStringVar1, gNaturesInfo[gTasks[taskId].tInput].name);
StringExpandPlaceholders(gStringVar4, sDebugText_PokemonNature);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
if (JOY_NEW(A_BUTTON))
@@ -3435,9 +3440,10 @@ static void DebugAction_Give_Pokemon_SelectNature(u8 taskId)
ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2);
StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15);
abilityId = GetAbilityBySpecies(sDebugMonData->species, 0);
- StringCopy(gStringVar1, gAbilitiesInfo[abilityId].name);
+ u8 *end = StringCopy(gStringVar1, gAbilitiesInfo[abilityId].name);
+ WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(gTasks[taskId].tSubWindowId));
StringExpandPlaceholders(gStringVar4, sDebugText_PokemonAbility);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Give_Pokemon_SelectAbility;
}
@@ -3480,9 +3486,10 @@ static void DebugAction_Give_Pokemon_SelectAbility(u8 taskId)
StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]);
ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2);
StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15);
- StringCopy(gStringVar1, gAbilitiesInfo[abilityId].name);
+ u8 *end = StringCopy(gStringVar1, gAbilitiesInfo[abilityId].name);
+ WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(gTasks[taskId].tSubWindowId));
StringExpandPlaceholders(gStringVar4, sDebugText_PokemonAbility);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
if (JOY_NEW(A_BUTTON))
@@ -3495,7 +3502,7 @@ static void DebugAction_Give_Pokemon_SelectAbility(u8 taskId)
ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2);
StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15);
StringExpandPlaceholders(gStringVar4, sDebugText_IV_HP);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Give_Pokemon_SelectIVs;
}
@@ -3560,7 +3567,7 @@ static void DebugAction_Give_Pokemon_SelectIVs(u8 taskId)
StringExpandPlaceholders(gStringVar4, sDebugText_IV_SpDefense);
break;
}
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
//If A or B button
@@ -3619,7 +3626,7 @@ static void DebugAction_Give_Pokemon_SelectIVs(u8 taskId)
StringExpandPlaceholders(gStringVar4, sDebugText_IV_SpDefense);
break;
}
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Give_Pokemon_SelectIVs;
}
@@ -3633,7 +3640,7 @@ static void DebugAction_Give_Pokemon_SelectIVs(u8 taskId)
ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3);
StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15);
StringExpandPlaceholders(gStringVar4, sDebugText_EV_HP);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Give_Pokemon_SelectEVs;
}
}
@@ -3710,7 +3717,7 @@ static void DebugAction_Give_Pokemon_SelectEVs(u8 taskId)
StringExpandPlaceholders(gStringVar4, sDebugText_EV_SpDefense);
break;
}
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
//If A or B button
@@ -3769,7 +3776,7 @@ static void DebugAction_Give_Pokemon_SelectEVs(u8 taskId)
StringExpandPlaceholders(gStringVar4, sDebugText_EV_SpDefense);
break;
}
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Give_Pokemon_SelectEVs;
}
@@ -3793,18 +3800,19 @@ static void DebugAction_Give_Pokemon_SelectEVs(u8 taskId)
ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3);
StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15);
StringExpandPlaceholders(gStringVar4, sDebugText_EV_HP);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Give_Pokemon_SelectEVs;
}
else
{
StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]);
- StringCopy(gStringVar1, GetMoveName(gTasks[taskId].tInput));
+ u8 *end = StringCopy(gStringVar1, GetMoveName(gTasks[taskId].tInput));
+ WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(gTasks[taskId].tSubWindowId));
StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15);
ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3);
StringExpandPlaceholders(gStringVar4, sDebugText_PokemonMove_0);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Give_Pokemon_Move;
}
@@ -3848,7 +3856,8 @@ static void DebugAction_Give_Pokemon_Move(u8 taskId)
}
StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]);
- StringCopy(gStringVar1, GetMoveName(gTasks[taskId].tInput));
+ u8 *end = StringCopy(gStringVar1, GetMoveName(gTasks[taskId].tInput));
+ WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(gTasks[taskId].tSubWindowId));
StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15);
ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3);
switch (gTasks[taskId].tIterator)
@@ -3866,7 +3875,7 @@ static void DebugAction_Give_Pokemon_Move(u8 taskId)
StringExpandPlaceholders(gStringVar4, sDebugText_PokemonMove_3);
break;
}
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
if (JOY_NEW(A_BUTTON))
@@ -3900,7 +3909,8 @@ static void DebugAction_Give_Pokemon_Move(u8 taskId)
gTasks[taskId].tDigit = 0;
StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]);
- StringCopy(gStringVar1, GetMoveName(gTasks[taskId].tInput));
+ u8 *end = StringCopy(gStringVar1, GetMoveName(gTasks[taskId].tInput));
+ WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(gTasks[taskId].tSubWindowId));
StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15);
ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3);
switch (gTasks[taskId].tIterator)
@@ -3918,7 +3928,7 @@ static void DebugAction_Give_Pokemon_Move(u8 taskId)
StringExpandPlaceholders(gStringVar4, sDebugText_PokemonMove_3);
break;
}
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
gTasks[taskId].func = DebugAction_Give_Pokemon_Move;
}
@@ -4271,7 +4281,7 @@ static void DebugAction_Sound_SE(u8 taskId)
ConvertIntToDecimalStringN(gStringVar3, 1, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS);
StringCopyPadded(gStringVar1, sSENames[0], CHAR_SPACE, 35);
StringExpandPlaceholders(gStringVar4, sDebugText_Sound_SFX_ID);
- AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
StopMapMusic(); //Stop map music to better hear sounds
@@ -4313,7 +4323,7 @@ static void DebugAction_Sound_SE_SelectId(u8 taskId)
StringCopyPadded(gStringVar1, sSENames[gTasks[taskId].tInput-1], CHAR_SPACE, 35);
ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS);
StringExpandPlaceholders(gStringVar4, sDebugText_Sound_SFX_ID);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
if (JOY_NEW(A_BUTTON))
@@ -4353,7 +4363,7 @@ static void DebugAction_Sound_MUS(u8 taskId)
ConvertIntToDecimalStringN(gStringVar3, START_MUS, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS);
StringCopyPadded(gStringVar1, sBGMNames[0], CHAR_SPACE, 35);
StringExpandPlaceholders(gStringVar4, sDebugText_Sound_Music_ID);
- AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
StopMapMusic(); //Stop map music to better hear new music
@@ -4395,7 +4405,7 @@ static void DebugAction_Sound_MUS_SelectId(u8 taskId)
StringCopyPadded(gStringVar1, sBGMNames[gTasks[taskId].tInput-START_MUS], CHAR_SPACE, 35);
ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS);
StringExpandPlaceholders(gStringVar4, sDebugText_Sound_Music_ID);
- AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
+ AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL);
}
if (JOY_NEW(A_BUTTON))
diff --git a/src/fonts.c b/src/fonts.c
index 2eb8ed062b..853f6fbde2 100644
--- a/src/fonts.c
+++ b/src/fonts.c
@@ -5,7 +5,7 @@ ALIGNED(4) const u8 gFontSmallNarrowLatinGlyphWidths[] = {
3, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 4, 4, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 3, 4, 5, 5, 5, 5, 4, 3,
4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 8, 5, 6, 3,
- 3, 3, 3, 3, 8, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 8, 0, 3, 3, 7, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5, 5, 3, 8, 8, 8, 8, 8, 8, 8, 4, 5, 4, 4, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 4,
@@ -41,7 +41,7 @@ ALIGNED(4) const u8 gFontSmallLatinGlyphWidths[] = {
3, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 4, 4, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 4, 3,
4, 4, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 8, 7, 8, 3,
- 3, 3, 3, 3, 8, 8, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 8, 8, 7, 3, 7, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5, 5, 5, 8, 8, 8, 8, 8, 8, 8, 4, 7, 5, 5, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 4,
@@ -77,7 +77,7 @@ ALIGNED(4) const u8 gFontNarrowLatinGlyphWidths[] = {
3, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 4, 4, 5, 5, 5,
8, 5, 5, 5, 5, 6, 5, 5, 3, 5, 5, 5, 5, 5, 4, 3,
4, 4, 5, 5, 5, 8, 5, 5, 5, 5, 5, 6, 9, 6, 6, 3,
- 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 8, 8, 3, 3, 7, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5, 5, 4, 8, 8, 8, 7, 8, 8, 4, 4, 6, 4, 4, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 4,
@@ -113,7 +113,7 @@ ALIGNED(4) const u8 gFontShortLatinGlyphWidths[] = {
3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 6, 6, 6, 6, 6,
8, 6, 6, 6, 6, 6, 6, 6, 3, 6, 6, 6, 6, 6, 6, 3,
6, 6, 6, 6, 6, 8, 6, 6, 6, 6, 6, 6, 9, 8, 8, 3,
- 3, 3, 3, 3, 10, 8, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 10, 8, 5, 3, 7, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
6, 6, 6, 8, 8, 8, 8, 8, 8, 4, 6, 8, 5, 5, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 6, 3, 3, 3, 3, 3, 3, 6,
@@ -185,19 +185,19 @@ ALIGNED(4) const u8 gFontNarrowerLatinGlyphWidths[] = {
3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4,
8, 4, 4, 4, 5, 5, 4, 4, 3, 4, 4, 4, 4, 4, 4, 3,
4, 4, 4, 4, 4, 6, 4, 4, 4, 5, 4, 5, 8, 6, 6, 3,
- 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 8, 8, 2, 3, 7, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 5, 5, 4, 8, 8, 8, 7, 8, 8, 4, 4, 6, 4, 4, 3, 3,
+ 5, 4, 2, 8, 8, 8, 7, 8, 8, 4, 4, 6, 4, 4, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4,
3, 3, 3, 3, 3, 3, 3, 5, 3, 7, 7, 7, 7, 0, 0, 3,
4, 5, 6, 7, 4, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 3, 5, 3,
- 5, 5, 5, 3, 3, 5, 5, 6, 3, 6, 6, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4,
- 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4,
+ 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 2, 4, 2,
+ 4, 4, 4, 2, 2, 4, 4, 6, 2, 5, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4,
2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8,
- 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 8, 3, 3, 3, 3,
+ 2, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 8, 3, 3, 3, 3,
10, 10, 10, 10, 8, 8, 10, 8, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
@@ -221,19 +221,19 @@ ALIGNED(4) const u8 gFontSmallNarrowerLatinGlyphWidths[] = {
3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4,
5, 4, 4, 4, 5, 4, 4, 4, 3, 4, 4, 4, 4, 4, 3, 3,
4, 4, 4, 4, 4, 6, 4, 4, 4, 5, 4, 4, 7, 5, 6, 3,
- 3, 3, 3, 3, 8, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 8, 0, 2, 3, 7, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 5, 4, 3, 7, 7, 7, 8, 8, 8, 8, 4, 5, 4, 4, 3, 3,
+ 5, 4, 2, 7, 7, 7, 8, 8, 8, 8, 4, 7, 5, 5, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4,
3, 3, 3, 3, 3, 3, 3, 5, 3, 8, 8, 8, 8, 0, 0, 3,
4, 5, 6, 7, 4, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 3, 4, 4,
- 5, 5, 5, 3, 3, 5, 5, 5, 4, 5, 5, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4,
+ 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 2, 4, 2,
+ 4, 4, 4, 2, 2, 4, 4, 8, 2, 8, 5, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 3, 4,
2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7,
- 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 8, 3, 3, 3, 3,
+ 2, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 8, 3, 3, 3, 3,
8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
@@ -257,7 +257,7 @@ ALIGNED(4) const u8 gFontShortNarrowLatinGlyphWidths[] = {
3, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 4, 4, 5, 5, 5,
8, 5, 5, 5, 5, 6, 5, 5, 3, 5, 5, 5, 5, 5, 4, 3,
4, 4, 5, 5, 5, 8, 5, 5, 5, 5, 6, 6, 9, 6, 6, 3,
- 3, 3, 3, 3, 10, 8, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 10, 8, 5, 3, 7, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
6, 6, 6, 8, 8, 8, 8, 8, 8, 4, 6, 8, 5, 5, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 6,
@@ -293,19 +293,19 @@ ALIGNED(4) const u8 gFontShortNarrowerLatinGlyphWidths[] = {
1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4,
8, 4, 4, 4, 5, 5, 4, 4, 3, 4, 4, 4, 4, 4, 4, 3,
4, 4, 4, 4, 4, 6, 4, 4, 4, 5, 4, 5, 8, 6, 6, 3,
- 3, 3, 3, 3, 8, 8, 3, 5, 5, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 5, 5, 4, 8, 8, 8, 7, 8, 8, 4, 4, 6, 4, 4, 3, 3,
+ 3, 3, 3, 3, 10, 8, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 3, 3, 3, 3, 3, 3,
+ 6, 6, 6, 8, 8, 8, 8, 8, 8, 4, 6, 8, 5, 5, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4,
3, 3, 3, 3, 3, 3, 3, 5, 3, 7, 7, 7, 7, 0, 0, 3,
4, 5, 6, 7, 4, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 3, 5, 3,
- 5, 5, 5, 3, 3, 5, 5, 6, 3, 6, 6, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4,
- 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4,
+ 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 5, 4, 5,
+ 6, 6, 6, 3, 3, 6, 6, 8, 3, 9, 6, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4,
2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8,
- 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3,
10, 10, 10, 10, 8, 8, 10, 8, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
diff --git a/src/item_menu.c b/src/item_menu.c
index 709dded46b..75751cae6f 100755
--- a/src/item_menu.c
+++ b/src/item_menu.c
@@ -280,8 +280,8 @@ static const struct MenuAction sItemMenuActions[] = {
[ACTION_BATTLE_USE] = {gMenuText_Use, {ItemMenu_UseInBattle}},
[ACTION_CHECK] = {COMPOUND_STRING("CHECK"), {ItemMenu_UseOutOfBattle}},
[ACTION_WALK] = {COMPOUND_STRING("WALK"), {ItemMenu_UseOutOfBattle}},
- [ACTION_DESELECT] = {COMPOUND_STRING("CHECK TAG"), {ItemMenu_Register}},
- [ACTION_CHECK_TAG] = {COMPOUND_STRING("DESELECT"), {ItemMenu_CheckTag}},
+ [ACTION_DESELECT] = {COMPOUND_STRING("DESELECT"), {ItemMenu_Register}},
+ [ACTION_CHECK_TAG] = {COMPOUND_STRING("CHECK TAG"), {ItemMenu_CheckTag}},
[ACTION_CONFIRM] = {gMenuText_Confirm, {Task_FadeAndCloseBagMenu}},
[ACTION_SHOW] = {COMPOUND_STRING("SHOW"), {ItemMenu_Show}},
[ACTION_GIVE_FAVOR_LADY] = {gMenuText_Give2, {ItemMenu_GiveFavorLady}},
@@ -916,7 +916,7 @@ static void GetItemName(u8 *dest, u16 itemId)
{
case TMHM_POCKET:
end = StringCopy(gStringVar2, GetMoveName(ItemIdToBattleMoveId(itemId)));
- PrependFontIdToFit(gStringVar2, end, FONT_NARROW, 73);
+ PrependFontIdToFit(gStringVar2, end, FONT_NARROW, 61);
if (itemId >= ITEM_HM01)
{
// Get HM number
@@ -933,7 +933,7 @@ static void GetItemName(u8 *dest, u16 itemId)
case BERRIES_POCKET:
ConvertIntToDecimalStringN(gStringVar1, itemId - FIRST_BERRY_INDEX + 1, STR_CONV_MODE_LEADING_ZEROS, 2);
end = CopyItemName(itemId, gStringVar2);
- PrependFontIdToFit(gStringVar2, end, FONT_NARROW, 73);
+ PrependFontIdToFit(gStringVar2, end, FONT_NARROW, 61);
StringExpandPlaceholders(dest, gText_NumberItem_TMBerry);
break;
default:
diff --git a/src/move_relearner.c b/src/move_relearner.c
index a4cc778a45..1e66702695 100644
--- a/src/move_relearner.c
+++ b/src/move_relearner.c
@@ -165,18 +165,18 @@ enum {
static EWRAM_DATA struct
{
u8 state;
- u8 heartSpriteIds[16]; /*0x001*/
- u16 movesToLearn[MAX_RELEARNER_MOVES]; /*0x01A*/
- u8 partyMon; /*0x044*/
- u8 moveSlot; /*0x045*/
- struct ListMenuItem menuItems[MAX_RELEARNER_MOVES]; /*0x0E8*/
- u8 numMenuChoices; /*0x110*/
- u8 numToShowAtOnce; /*0x111*/
- u8 moveListMenuTask; /*0x112*/
- u8 moveListScrollArrowTask; /*0x113*/
- u8 moveDisplayArrowTask; /*0x114*/
- u16 scrollOffset; /*0x116*/
- u8 categoryIconSpriteId; /*0x117*/
+ u8 heartSpriteIds[16]; /*0x001*/
+ u16 movesToLearn[MAX_RELEARNER_MOVES]; /*0x01A*/
+ u8 partyMon; /*0x044*/
+ u8 moveSlot; /*0x045*/
+ struct ListMenuItem menuItems[MAX_RELEARNER_MOVES + 1]; /*0x0E8*/
+ u8 numMenuChoices; /*0x110*/
+ u8 numToShowAtOnce; /*0x111*/
+ u8 moveListMenuTask; /*0x112*/
+ u8 moveListScrollArrowTask; /*0x113*/
+ u8 moveDisplayArrowTask; /*0x114*/
+ u16 scrollOffset; /*0x116*/
+ u8 categoryIconSpriteId; /*0x117*/
} *sMoveRelearnerStruct = {0};
static EWRAM_DATA struct {
diff --git a/src/pokemon.c b/src/pokemon.c
index 743f5b2771..d377af1c42 100644
--- a/src/pokemon.c
+++ b/src/pokemon.c
@@ -2074,6 +2074,13 @@ u8 CountAliveMonsInBattle(u8 caseId, u32 battler)
retVal++;
}
break;
+ case BATTLE_ALIVE_EXCEPT_BATTLER_SIDE:
+ for (i = 0; i < MAX_BATTLERS_COUNT; i++)
+ {
+ if (i != battler && i != BATTLE_PARTNER(battler) && !(gAbsentBattlerFlags & (1u << i)))
+ retVal++;
+ }
+ break;
case BATTLE_ALIVE_SIDE:
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
@@ -6661,7 +6668,8 @@ u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove)
}
while(learnset[sLearningMoveTableID].move != LEVEL_UP_MOVE_END)
{
- while (learnset[sLearningMoveTableID].level == 0 || learnset[sLearningMoveTableID].level == level)
+ while ((learnset[sLearningMoveTableID].level == 0 || learnset[sLearningMoveTableID].level == level)
+ && !(P_EVOLUTION_LEVEL_1_LEARN >= GEN_8 && learnset[sLearningMoveTableID].level == 1))
{
gMoveToLearn = learnset[sLearningMoveTableID].move;
sLearningMoveTableID++;
diff --git a/test/battle/ability/flower_gift.c b/test/battle/ability/flower_gift.c
index 68712641e0..5ceb26c5c1 100644
--- a/test/battle/ability/flower_gift.c
+++ b/test/battle/ability/flower_gift.c
@@ -63,7 +63,32 @@ SINGLE_BATTLE_TEST("Flower Gift transforms Cherrim back to normal when its abili
}
}
-TO_DO_BATTLE_TEST("Forecast transforms Castform back to normal under Cloud Nine/Air Lock");
+SINGLE_BATTLE_TEST("Flower Gift transforms Cherrim back to normal under Cloud Nine/Air Lock")
+{
+ u32 species = 0, ability = 0;
+ PARAMETRIZE { species = SPECIES_PSYDUCK; ability = ABILITY_CLOUD_NINE; }
+ PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; }
+ GIVEN {
+ PLAYER(SPECIES_CHERRIM_OVERCAST) { Ability(ABILITY_FLOWER_GIFT); }
+ OPPONENT(SPECIES_WOBBUFFET);
+ OPPONENT(species) { Ability(ability); }
+ } WHEN {
+ TURN { MOVE(player, MOVE_SUNNY_DAY); }
+ TURN { SWITCH(opponent, 1); }
+ } SCENE {
+ // transforms
+ ABILITY_POPUP(player, ABILITY_FLOWER_GIFT);
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player);
+ MESSAGE("Cherrim transformed!");
+ // back to normal
+ ABILITY_POPUP(opponent, ability);
+ ABILITY_POPUP(player, ABILITY_FLOWER_GIFT);
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player);
+ MESSAGE("Cherrim transformed!");
+ } THEN {
+ EXPECT_EQ(player->species, SPECIES_CHERRIM_OVERCAST);
+ }
+}
DOUBLE_BATTLE_TEST("Flower Gift increases the attack of Cherrim and its allies by 1.5x", s16 damageL, s16 damageR)
{
diff --git a/test/battle/ability/transistor.c b/test/battle/ability/transistor.c
index f02743ab8c..8dd1a1bdb3 100644
--- a/test/battle/ability/transistor.c
+++ b/test/battle/ability/transistor.c
@@ -4,7 +4,7 @@
#include "global.h"
#include "test/battle.h"
-SINGLE_BATTLE_TEST("Transistor increases Electric-type move damage", s16 damage)
+SINGLE_BATTLE_TEST("Transistor increases Electric-type attack / special attack", s16 damage)
{
u32 move;
u16 ability;
@@ -30,20 +30,13 @@ SINGLE_BATTLE_TEST("Transistor increases Electric-type move damage", s16 damage)
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_EQ(results[0].damage, results[1].damage); // Tackle should be unaffected
- if (B_TRANSISTOR_BOOST >= GEN_9)
- {
- EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.3), results[3].damage); // Wild Charge should be affected
- EXPECT_MUL_EQ(results[4].damage, Q_4_12(1.3), results[5].damage); // Thunder Shock should be affected
- }
- else
- {
- EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[3].damage); // Wild Charge should be affected
- EXPECT_MUL_EQ(results[4].damage, Q_4_12(1.5), results[5].damage); // Thunder Shock should be affected
- }
+
+ EXPECT_LT(results[2].damage, results[3].damage); // cannot test exact factor because ATK / SPATK introduces inaccuracies
+ EXPECT_LT(results[4].damage, results[5].damage);
}
}
-SINGLE_BATTLE_TEST("Transistor boosts Electric type moves by 1.5 in Gen8 and 1.3 in Gen9+", s16 damage)
+SINGLE_BATTLE_TEST("Transistor is blocked by neutralizing gas", s16 damage)
{
u16 ability;
PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; }
@@ -58,9 +51,6 @@ SINGLE_BATTLE_TEST("Transistor boosts Electric type moves by 1.5 in Gen8 and 1.3
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
- if (B_TRANSISTOR_BOOST >= GEN_9)
- EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.3), results[1].damage);
- else
- EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
+ EXPECT_LT(results[0].damage, results[1].damage); // cannot test exact factor because ATK / SPATK introduces inaccuracies
}
}
diff --git a/test/battle/damage_formula.c b/test/battle/damage_formula.c
index 473f631b11..049bbf4051 100644
--- a/test/battle/damage_formula.c
+++ b/test/battle/damage_formula.c
@@ -150,3 +150,134 @@ DOUBLE_BATTLE_TEST("A spread move will do correct damage to the second mon if th
EXPECT_EQ(damage[4], damage[5]);
}
}
+
+SINGLE_BATTLE_TEST("Punching Glove vs Muscle Band Damage calculation")
+{
+ s16 dmgPlayer, dmgOpponent;
+ s16 expectedDamagePlayer, expectedDamageOpponent;
+ PARAMETRIZE { expectedDamagePlayer = 204, expectedDamageOpponent = 201; }
+ PARAMETRIZE { expectedDamagePlayer = 201, expectedDamageOpponent = 198; }
+ PARAMETRIZE { expectedDamagePlayer = 199, expectedDamageOpponent = 196; }
+ PARAMETRIZE { expectedDamagePlayer = 196, expectedDamageOpponent = 193; }
+ PARAMETRIZE { expectedDamagePlayer = 195, expectedDamageOpponent = 192; }
+ PARAMETRIZE { expectedDamagePlayer = 193, expectedDamageOpponent = 190; }
+ PARAMETRIZE { expectedDamagePlayer = 190, expectedDamageOpponent = 187; }
+ PARAMETRIZE { expectedDamagePlayer = 189, expectedDamageOpponent = 186; }
+ PARAMETRIZE { expectedDamagePlayer = 187, expectedDamageOpponent = 184; }
+ PARAMETRIZE { expectedDamagePlayer = 184, expectedDamageOpponent = 181; }
+ PARAMETRIZE { expectedDamagePlayer = 183, expectedDamageOpponent = 180; }
+ PARAMETRIZE { expectedDamagePlayer = 181, expectedDamageOpponent = 178; }
+ PARAMETRIZE { expectedDamagePlayer = 178, expectedDamageOpponent = 175; }
+ PARAMETRIZE { expectedDamagePlayer = 177, expectedDamageOpponent = 174; }
+ PARAMETRIZE { expectedDamagePlayer = 174, expectedDamageOpponent = 172; }
+ PARAMETRIZE { expectedDamagePlayer = 172, expectedDamageOpponent = 169; }
+ GIVEN {
+ PLAYER(SPECIES_MAKUHITA) { Item(ITEM_PUNCHING_GLOVE); }
+ OPPONENT(SPECIES_MAKUHITA) { Item(ITEM_MUSCLE_BAND); }
+ } WHEN {
+ TURN {
+ MOVE(player, MOVE_DRAIN_PUNCH, WITH_RNG(RNG_DAMAGE_MODIFIER, i));
+ MOVE(opponent, MOVE_DRAIN_PUNCH, WITH_RNG(RNG_DAMAGE_MODIFIER, i));
+ }
+ }
+ SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAIN_PUNCH, player);
+ HP_BAR(opponent, captureDamage: &dmgPlayer);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAIN_PUNCH, opponent);
+ HP_BAR(player, captureDamage: &dmgOpponent);
+ }
+ THEN {
+ EXPECT_EQ(expectedDamagePlayer, dmgPlayer);
+ EXPECT_EQ(expectedDamageOpponent, dmgOpponent);
+ }
+}
+
+SINGLE_BATTLE_TEST("Gem boosted Damage calculation")
+{
+ s16 dmg;
+ s16 expectedDamage;
+ PARAMETRIZE { expectedDamage = 240; }
+ PARAMETRIZE { expectedDamage = 237; }
+ PARAMETRIZE { expectedDamage = 234; }
+ PARAMETRIZE { expectedDamage = 232; }
+ PARAMETRIZE { expectedDamage = 229; }
+ PARAMETRIZE { expectedDamage = 228; }
+ PARAMETRIZE { expectedDamage = 225; }
+ PARAMETRIZE { expectedDamage = 222; }
+ PARAMETRIZE { expectedDamage = 220; }
+ PARAMETRIZE { expectedDamage = 217; }
+ PARAMETRIZE { expectedDamage = 216; }
+ PARAMETRIZE { expectedDamage = 213; }
+ PARAMETRIZE { expectedDamage = 210; }
+ PARAMETRIZE { expectedDamage = 208; }
+ PARAMETRIZE { expectedDamage = 205; }
+ PARAMETRIZE { expectedDamage = 204; }
+ GIVEN {
+ PLAYER(SPECIES_MAKUHITA) { Item(ITEM_FIGHTING_GEM); }
+ OPPONENT(SPECIES_MAKUHITA);
+ } WHEN {
+ TURN {
+ MOVE(player, MOVE_DRAIN_PUNCH, WITH_RNG(RNG_DAMAGE_MODIFIER, i));
+ }
+ }
+ SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAIN_PUNCH, player);
+ HP_BAR(opponent, captureDamage: &dmg);
+ }
+ THEN {
+ EXPECT_EQ(expectedDamage, dmg);
+ }
+}
+
+#define NUM_DAMAGE_SPREADS (DMG_ROLL_PERCENT_HI - DMG_ROLL_PERCENT_LO) + 1
+
+static const s16 sThunderShockTransistorSpread[] = { 54, 55, 56, 57, 57, 58, 59, 60, 60, 60, 61, 62, 63, 63, 64, 65 };
+static const s16 sThunderShockRegularSpread[] = { 42, 42, 43, 43, 44, 45, 45, 45, 46, 46, 47, 48, 48, 48, 49, 50 };
+static const s16 sWildChargeTransistorSpread[] = { 123, 124, 126, 127, 129, 130, 132, 133, 135, 136, 138, 139, 141, 142, 144, 145 };
+static const s16 sWildChargeRegularSpread[] = { 94, 96, 96, 98, 99, 100, 101, 102, 103, 105, 105, 107, 108, 109, 110, 111 };
+
+DOUBLE_BATTLE_TEST("Transistor Damage calculation", s16 damage)
+{
+ s16 expectedDamageTransistorSpec = 0, expectedDamageRegularPhys = 0, expectedDamageRegularSpec = 0, expectedDamageTransistorPhys = 0;
+ s16 damagePlayerLeft, damagePlayerRight, damageOpponentLeft, damageOpponentRight;
+ for (u32 spread = 0; spread < 16; ++spread) {
+ PARAMETRIZE { expectedDamageTransistorSpec = sThunderShockTransistorSpread[spread],
+ expectedDamageRegularSpec = sThunderShockRegularSpread[spread],
+ expectedDamageTransistorPhys = sWildChargeTransistorSpread[spread],
+ expectedDamageRegularPhys = sWildChargeRegularSpread[spread];
+ }
+ }
+ GIVEN {
+ ASSUME(gMovesInfo[MOVE_WILD_CHARGE].type == TYPE_ELECTRIC);
+ ASSUME(gMovesInfo[MOVE_THUNDER_SHOCK].type == TYPE_ELECTRIC);
+ ASSUME(gMovesInfo[MOVE_WILD_CHARGE].category == DAMAGE_CATEGORY_PHYSICAL);
+ ASSUME(gMovesInfo[MOVE_THUNDER_SHOCK].category == DAMAGE_CATEGORY_SPECIAL);
+ ASSUME(NUM_DAMAGE_SPREADS == 16);
+
+ PLAYER(SPECIES_REGIELEKI) { Ability(ABILITY_KLUTZ); }
+ PLAYER(SPECIES_REGIELEKI) { Ability(ABILITY_TRANSISTOR); }
+ OPPONENT(SPECIES_REGIELEKI) { Ability(ABILITY_KLUTZ); }
+ OPPONENT(SPECIES_REGIELEKI) { Ability(ABILITY_TRANSISTOR); }
+ } WHEN {
+ TURN {
+ MOVE(playerLeft, MOVE_THUNDER_SHOCK, target: opponentLeft, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - i));
+ MOVE(playerRight, MOVE_THUNDER_SHOCK, target: opponentRight, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - i));
+ MOVE(opponentLeft, MOVE_WILD_CHARGE, target: playerLeft, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - i));
+ MOVE(opponentRight, MOVE_WILD_CHARGE, target: playerRight, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - i));
+ }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_SHOCK, playerLeft);
+ HP_BAR(opponentLeft, captureDamage: &damageOpponentLeft);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_SHOCK, playerRight);
+ HP_BAR(opponentRight, captureDamage: &damageOpponentRight);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_WILD_CHARGE, opponentLeft);
+ HP_BAR(playerLeft, captureDamage: &damagePlayerLeft);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_WILD_CHARGE, opponentRight);
+ HP_BAR(playerRight, captureDamage: &damagePlayerRight);
+ } THEN {
+ EXPECT_EQ(damageOpponentLeft, expectedDamageRegularSpec);
+ EXPECT_EQ(damageOpponentRight, expectedDamageTransistorSpec);
+ EXPECT_EQ(damagePlayerLeft, expectedDamageRegularPhys);
+ EXPECT_EQ(damagePlayerRight, expectedDamageTransistorPhys);
+ }
+}
diff --git a/test/battle/move_effect/coaching.c b/test/battle/move_effect/coaching.c
index 2f50aceab5..451ac80495 100644
--- a/test/battle/move_effect/coaching.c
+++ b/test/battle/move_effect/coaching.c
@@ -1,8 +1,120 @@
#include "global.h"
#include "test/battle.h"
-TO_DO_BATTLE_TEST("Coaching raises Attack and Defense of ally by 1 stage each");
-TO_DO_BATTLE_TEST("Coaching doesn't raise stats of the user");
-TO_DO_BATTLE_TEST("Coaching bypasses protection of allies");
-TO_DO_BATTLE_TEST("Coaching fails in single battles");
-TO_DO_BATTLE_TEST("Coaching fails if there's no ally");
+ASSUMPTIONS
+{
+ ASSUME(gMovesInfo[MOVE_COACHING].effect == EFFECT_COACHING);
+}
+
+DOUBLE_BATTLE_TEST("Coaching raises Attack and Defense of ally by 1 stage each")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { MOVE(playerLeft, MOVE_COACHING, target: playerRight); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_COACHING, playerLeft);
+ MESSAGE("Wynaut's Attack rose!");
+ MESSAGE("Wynaut's Defense rose!");
+ }
+}
+
+DOUBLE_BATTLE_TEST("Coaching bypasses Protect")
+{
+ GIVEN {
+ ASSUME(gMovesInfo[MOVE_PROTECT].effect == EFFECT_PROTECT);
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { MOVE(playerRight, MOVE_PROTECT); MOVE(playerLeft, MOVE_COACHING, target: playerRight); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_COACHING, playerLeft);
+ MESSAGE("Wynaut's Attack rose!");
+ MESSAGE("Wynaut's Defense rose!");
+ }
+}
+
+DOUBLE_BATTLE_TEST("Coaching bypasses Crafty Shield")
+{
+ GIVEN {
+ ASSUME(gMovesInfo[MOVE_CRAFTY_SHIELD].effect == EFFECT_PROTECT);
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { MOVE(playerRight, MOVE_CRAFTY_SHIELD); MOVE(playerLeft, MOVE_COACHING, target: playerRight); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_COACHING, playerLeft);
+ MESSAGE("Wynaut's Attack rose!");
+ MESSAGE("Wynaut's Defense rose!");
+ }
+}
+
+DOUBLE_BATTLE_TEST("Coaching fails if all allies are is semi-invulnerable")
+{
+ KNOWN_FAILING; // Coaching succeeds
+ GIVEN {
+ ASSUME(gMovesInfo[MOVE_FLY].effect == EFFECT_SEMI_INVULNERABLE);
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_HAWLUCHA);
+ OPPONENT(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { MOVE(playerRight, MOVE_FLY, target: opponentLeft); MOVE(playerLeft, MOVE_COACHING, target: playerRight); }
+ } SCENE {
+ MESSAGE("Hawlucha used Fly!");
+ MESSAGE("Wobbuffet used Coaching!");
+ NONE_OF {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_COACHING, playerLeft);
+ MESSAGE("Hawlucha's Attack rose!");
+ MESSAGE("Hawlucha's Defense rose!");
+ }
+ MESSAGE("But it failed!");
+ }
+}
+
+SINGLE_BATTLE_TEST("Coaching fails in single battles")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { MOVE(player, MOVE_COACHING); }
+ } SCENE {
+ MESSAGE("But it failed!");
+ NONE_OF {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_COACHING, player);
+ MESSAGE("Wynaut's Attack rose!");
+ MESSAGE("Wynaut's Defense rose!");
+ }
+ }
+}
+
+DOUBLE_BATTLE_TEST("Coaching fails if there's no ally")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_WYNAUT) { HP(1); };
+ OPPONENT(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { MOVE(playerLeft, MOVE_TACKLE, target: playerRight); }
+ TURN { MOVE(playerLeft, MOVE_COACHING, target: playerRight); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerLeft);
+ MESSAGE("Wynaut fainted!");
+ MESSAGE("Wobbuffet used Coaching!");
+ NONE_OF {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_COACHING, playerLeft);
+ MESSAGE("Wynaut's Attack rose!");
+ MESSAGE("Wynaut's Defense rose!");
+ }
+ MESSAGE("But it failed!");
+ }
+}
diff --git a/test/battle/move_effect/cosmic_power.c b/test/battle/move_effect/cosmic_power.c
index 8680e9f28e..3b52fbe046 100644
--- a/test/battle/move_effect/cosmic_power.c
+++ b/test/battle/move_effect/cosmic_power.c
@@ -1,4 +1,21 @@
#include "global.h"
#include "test/battle.h"
-TO_DO_BATTLE_TEST("Cosmic Power increases the user's Defense and Sp. Defense by 1 stage each");
+ASSUMPTIONS
+{
+ ASSUME(gMovesInfo[MOVE_COSMIC_POWER].effect == EFFECT_COSMIC_POWER);
+}
+
+SINGLE_BATTLE_TEST("Cosmic Power increases the user's Defense and Sp. Defense by 1 stage each")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { MOVE(player, MOVE_COSMIC_POWER); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_COSMIC_POWER, player);
+ MESSAGE("Wobbuffet's Defense rose!");
+ MESSAGE("Wobbuffet's Sp. Def rose!");
+ }
+}
diff --git a/test/battle/move_effect/destiny_bond.c b/test/battle/move_effect/destiny_bond.c
index ba49e0ec43..7291fe7fb3 100644
--- a/test/battle/move_effect/destiny_bond.c
+++ b/test/battle/move_effect/destiny_bond.c
@@ -1,6 +1,11 @@
#include "global.h"
#include "test/battle.h"
+ASSUMPTIONS
+{
+ ASSUME(gMovesInfo[MOVE_DESTINY_BOND].effect == EFFECT_DESTINY_BOND);
+}
+
SINGLE_BATTLE_TEST("Destiny Bond faints the opposing mon if it fainted from the attack")
{
GIVEN {
@@ -15,3 +20,60 @@ SINGLE_BATTLE_TEST("Destiny Bond faints the opposing mon if it fainted from the
MESSAGE("The opposing Wobbuffet fainted!");
}
}
+
+SINGLE_BATTLE_TEST("Destiny Bond fails if used sequentially in Gen 7+")
+{
+ GIVEN {
+ ASSUME(B_DESTINY_BOND_FAIL >= GEN_7);
+ PLAYER(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_ZIGZAGOON);
+ } WHEN {
+ TURN { MOVE(player, MOVE_DESTINY_BOND); }
+ TURN { MOVE(player, MOVE_DESTINY_BOND); SWITCH(opponent, 1); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player);
+ MESSAGE("2 sent out Zigzagoon!");
+ NOT { ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player); }
+ MESSAGE("But it failed!");
+ }
+}
+
+SINGLE_BATTLE_TEST("Destiny Bond does not fail if used repeatedly separated by other moves in Gen 7+")
+{
+ GIVEN {
+ ASSUME(B_DESTINY_BOND_FAIL >= GEN_7);
+ PLAYER(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_ZIGZAGOON);
+ } WHEN {
+ TURN { MOVE(player, MOVE_DESTINY_BOND); }
+ TURN { MOVE(player, MOVE_GROWL); SWITCH(opponent, 1); }
+ TURN { MOVE(player, MOVE_DESTINY_BOND); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player);
+ MESSAGE("2 sent out Zigzagoon!");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player);
+ NOT { MESSAGE("But it failed!"); }
+ }
+}
+
+SINGLE_BATTLE_TEST("Destiny Bond does not fail if used after failing in Gen 7+")
+{
+ GIVEN {
+ ASSUME(B_DESTINY_BOND_FAIL >= GEN_7);
+ PLAYER(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_ZIGZAGOON);
+ } WHEN {
+ TURN { MOVE(player, MOVE_DESTINY_BOND); }
+ TURN { MOVE(player, MOVE_DESTINY_BOND); SWITCH(opponent, 1); }
+ TURN { MOVE(player, MOVE_DESTINY_BOND); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player);
+ MESSAGE("2 sent out Zigzagoon!");
+ NOT { ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player); }
+ MESSAGE("But it failed!");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player);
+ }
+}
diff --git a/test/battle/move_effect/gravity.c b/test/battle/move_effect/gravity.c
new file mode 100644
index 0000000000..4ccad08b58
--- /dev/null
+++ b/test/battle/move_effect/gravity.c
@@ -0,0 +1,47 @@
+#include "global.h"
+#include "test/battle.h"
+
+ASSUMPTIONS
+{
+ ASSUME(gMovesInfo[MOVE_GRAVITY].effect == EFFECT_GRAVITY);
+}
+
+DOUBLE_BATTLE_TEST("Gravity cancels fly and sky drop if they are in the air")
+{
+ u8 visibility;
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET) { Speed(100); }
+ PLAYER(SPECIES_WYNAUT) { Speed(90); }
+ OPPONENT(SPECIES_PIDGEY) { Speed(50); }
+ OPPONENT(SPECIES_ROOKIDEE) { Speed(45); }
+ } WHEN {
+ TURN { MOVE(opponentLeft, MOVE_SKY_DROP, target: playerRight); MOVE(opponentRight, MOVE_FLY, target: playerLeft); }
+ TURN { MOVE(playerLeft, MOVE_GRAVITY); SKIP_TURN(opponentRight); SKIP_TURN(opponentLeft); }
+ } SCENE {
+ // turn 1
+ MESSAGE("The opposing Pidgey used Sky Drop!");
+ MESSAGE("The opposing Pidgey took Wynaut into the sky!");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_DROP, opponentLeft);
+ MESSAGE("The opposing Rookidee used Fly!");
+ MESSAGE("The opposing Rookidee flew up high!");
+ // turn 2
+ MESSAGE("Wobbuffet used Gravity!");
+ MESSAGE("Gravity intensified!");
+ MESSAGE("The opposing Pidgey fell from the sky due to the gravity!");
+ MESSAGE("The opposing Rookidee fell from the sky due to the gravity!");
+ MESSAGE("The opposing Pidgey can't use Sky Drop because of gravity!");
+ MESSAGE("The opposing Rookidee can't use Fly because of gravity!");
+ } THEN {
+ // all battlers should be visible. assign to var first because expect_eq not working with bitfield address
+ visibility = gBattleSpritesDataPtr->battlerData[0].invisible;
+ EXPECT_EQ(visibility, 0);
+ visibility = gBattleSpritesDataPtr->battlerData[1].invisible;
+ EXPECT_EQ(visibility, 0);
+ visibility = gBattleSpritesDataPtr->battlerData[2].invisible;
+ EXPECT_EQ(visibility, 0);
+ visibility = gBattleSpritesDataPtr->battlerData[3].invisible;
+ EXPECT_EQ(visibility, 0);
+ // ensure moveend properly recorded
+ EXPECT_EQ(gLastMoves[0], MOVE_GRAVITY);
+ }
+}
diff --git a/test/battle/move_effect/octolock.c b/test/battle/move_effect/octolock.c
index 1a04de7331..e93f6f29cb 100644
--- a/test/battle/move_effect/octolock.c
+++ b/test/battle/move_effect/octolock.c
@@ -131,3 +131,24 @@ SINGLE_BATTLE_TEST("Octolock will not decrease Defense and Sp. Def further then
}
}
}
+
+SINGLE_BATTLE_TEST("Octolock triggers Defiant for both stat reductions")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_BISHARP) { Ability(ABILITY_DEFIANT); }
+ } WHEN {
+ TURN { MOVE(player, MOVE_OCTOLOCK); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_OCTOLOCK, player);
+ MESSAGE("The opposing Bisharp can no longer escape because of Octolock!");
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
+ MESSAGE("The opposing Bisharp's Defense fell!");
+ ABILITY_POPUP(opponent, ABILITY_DEFIANT);
+ MESSAGE("The opposing Bisharp's Attack sharply rose!");
+ NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
+ MESSAGE("The opposing Bisharp's Sp. Def fell!");
+ ABILITY_POPUP(opponent, ABILITY_DEFIANT);
+ MESSAGE("The opposing Bisharp's Attack sharply rose!");
+ }
+}
diff --git a/test/battle/move_effect/ohko.c b/test/battle/move_effect/ohko.c
index 511d76a8ad..8a8015309b 100644
--- a/test/battle/move_effect/ohko.c
+++ b/test/battle/move_effect/ohko.c
@@ -20,6 +20,22 @@ SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon")
MESSAGE("It doesn't affect the opposing Glalie…");
}
}
+
+SINGLE_BATTLE_TEST("OHKO moves can hit semi-invulnerable mons when the user has No-Guard")
+{
+ GIVEN {
+ ASSUME(gMovesInfo[MOVE_SHEER_COLD].effect == EFFECT_OHKO);
+ PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_NO_GUARD); }
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { MOVE(opponent, MOVE_FLY); }
+ TURN { MOVE(player, MOVE_SHEER_COLD); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player);
+ HP_BAR(opponent, hp: 0);
+ }
+}
+
TO_DO_BATTLE_TEST("Fissure faints the target, skipping regular damage calculations")
TO_DO_BATTLE_TEST("Fissure always fails if the target has a higher level than the user")
TO_DO_BATTLE_TEST("Fissure's accuracy increases by 1% for every level the user has over the target")
diff --git a/test/battle/move_effect/pursuit.c b/test/battle/move_effect/pursuit.c
index 3a1db03d06..5dfa3f8e33 100644
--- a/test/battle/move_effect/pursuit.c
+++ b/test/battle/move_effect/pursuit.c
@@ -6,10 +6,462 @@ ASSUMPTIONS
ASSUME(gMovesInfo[MOVE_PURSUIT].effect == EFFECT_PURSUIT);
}
+SINGLE_BATTLE_TEST("Pursuit attacks a switching foe")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_WYNAUT);
+ } WHEN {
+ TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT); }
+ } SCENE {
+ SWITCH_OUT_MESSAGE("Wobbuffet");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent);
+ HP_BAR(player);
+ SEND_IN_MESSAGE("Zigzagoon");
+ }
+}
+
+SINGLE_BATTLE_TEST("Pursuit attacks a foe using Volt Switch / U-Turn / Parting Shot to switch out")
+{
+ u32 move;
+ PARAMETRIZE { move = MOVE_VOLT_SWITCH; }
+ PARAMETRIZE { move = MOVE_U_TURN; }
+ PARAMETRIZE { move = MOVE_PARTING_SHOT; }
+ GIVEN {
+ ASSUME(gMovesInfo[MOVE_VOLT_SWITCH].effect == EFFECT_HIT_ESCAPE);
+ ASSUME(gMovesInfo[MOVE_U_TURN].effect == EFFECT_HIT_ESCAPE);
+ ASSUME(gMovesInfo[MOVE_PARTING_SHOT].effect == EFFECT_PARTING_SHOT);
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_WYNAUT);
+ } WHEN {
+ TURN { MOVE(player, move); MOVE(opponent, MOVE_PURSUIT); SEND_OUT(player, 1); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, move, player);
+ MESSAGE("Wobbuffet went back to 1!");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent);
+ SEND_IN_MESSAGE("Zigzagoon");
+ }
+}
+
+DOUBLE_BATTLE_TEST("Pursuit doesn't attack a foe using Teleport / Baton Pass to switch out")
+{
+ u32 move;
+ PARAMETRIZE { move = MOVE_TELEPORT; }
+ PARAMETRIZE { move = MOVE_BATON_PASS; }
+ GIVEN {
+ ASSUME(gMovesInfo[MOVE_QUASH].effect == EFFECT_QUASH);
+ ASSUME(gMovesInfo[MOVE_TELEPORT].effect == EFFECT_TELEPORT);
+ ASSUME(gMovesInfo[MOVE_BATON_PASS].effect == EFFECT_BATON_PASS);
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_NIDOKING);
+ PLAYER(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_LINOONE);
+ } WHEN {
+ TURN { MOVE(playerRight, MOVE_QUASH, target: opponentLeft); MOVE(playerLeft, move); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); SEND_OUT(playerLeft, 2); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_QUASH, playerRight);
+ ANIMATION(ANIM_TYPE_MOVE, move, playerLeft);
+ NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft);
+ SEND_IN_MESSAGE("Zigzagoon");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft);
+ }
+}
+
+SINGLE_BATTLE_TEST("Pursuit doesn't attack switching foe if user already acted that turn")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_WYNAUT);
+ } WHEN {
+ TURN { MOVE(opponent, MOVE_PURSUIT); MOVE(player, MOVE_VOLT_SWITCH); SEND_OUT(player, 1); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_VOLT_SWITCH, player);
+ MESSAGE("Wobbuffet went back to 1!");
+ NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent);
+ SEND_IN_MESSAGE("Zigzagoon");
+ }
+}
+
+SINGLE_BATTLE_TEST("Pursuit doubles in power if attacking while target switches out", s16 damage)
+{
+ u32 speed;
+ PARAMETRIZE { speed = 5; }
+ PARAMETRIZE { speed = 3; }
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET) { Speed(4); }
+ PLAYER(SPECIES_ZIGZAGOON) { Speed(2); }
+ OPPONENT(SPECIES_WYNAUT) { Speed(speed); }
+ } WHEN {
+ TURN { MOVE(opponent, MOVE_PURSUIT); MOVE(player, MOVE_VOLT_SWITCH); SEND_OUT(player, 1); }
+ } SCENE {
+ if (speed == 3)
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_VOLT_SWITCH, player);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent);
+ HP_BAR(player, captureDamage: &results[i].damage);
+ if (speed == 5)
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_VOLT_SWITCH, player);
+ SEND_IN_MESSAGE("Zigzagoon");
+ } FINALLY {
+ EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
+ }
+}
+
+SINGLE_BATTLE_TEST("Pursuit ignores accuracy checks when attacking a switching target")
+{
+ PASSES_RANDOMLY(100, 100, RNG_ACCURACY);
+ GIVEN {
+ ASSUME(gMovesInfo[MOVE_SAND_ATTACK].effect == EFFECT_ACCURACY_DOWN);
+ ASSUME(gMovesInfo[MOVE_HAIL].effect == EFFECT_HAIL);
+ PLAYER(SPECIES_GLACEON) { Ability(ABILITY_SNOW_CLOAK); }
+ PLAYER(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { MOVE(player, MOVE_SAND_ATTACK); MOVE(opponent, MOVE_HAIL); }
+ TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_SAND_ATTACK, player);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_HAIL, opponent);
+ SWITCH_OUT_MESSAGE("Glaceon");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent);
+ SEND_IN_MESSAGE("Zigzagoon");
+ }
+}
+
+DOUBLE_BATTLE_TEST("Pursuit attacks switching foes even if not targetting them (Gen 4+)")
+{
+ GIVEN {
+ ASSUME(B_PURSUIT_TARGET >= GEN_4);
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_ZIGZAGOON);
+ PLAYER(SPECIES_GRIMER);
+ OPPONENT(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_LINOONE);
+ } WHEN {
+ TURN { SWITCH(playerLeft, 2); MOVE(opponentLeft, MOVE_PURSUIT, target: playerRight); MOVE(opponentRight, MOVE_PURSUIT, target: playerRight); }
+ } SCENE {
+ SWITCH_OUT_MESSAGE("Wobbuffet");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft);
+ HP_BAR(playerLeft);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight);
+ HP_BAR(playerLeft);
+ SEND_IN_MESSAGE("Grimer");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight);
+ }
+}
+
+DOUBLE_BATTLE_TEST("Pursuit attacks a switching foe from fastest to slowest")
+{
+ u32 speedLeft, speedRight;
+ PARAMETRIZE { speedLeft = 5; speedRight = 3; }
+ PARAMETRIZE { speedLeft = 3; speedRight = 5; }
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET) { Speed(1); }
+ PLAYER(SPECIES_ZIGZAGOON) { Speed(4); }
+ PLAYER(SPECIES_GRIMER) { Speed(2); }
+ OPPONENT(SPECIES_WYNAUT) { Speed(speedLeft); }
+ OPPONENT(SPECIES_LINOONE) { Speed(speedRight); }
+ } WHEN {
+ TURN { SWITCH(playerLeft, 2); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); MOVE(opponentRight, MOVE_PURSUIT, target: playerLeft); }
+ } SCENE {
+ SWITCH_OUT_MESSAGE("Wobbuffet");
+ if (speedLeft > speedRight) {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft);
+ HP_BAR(playerLeft);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight);
+ HP_BAR(playerLeft);
+ } else {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight);
+ HP_BAR(playerLeft);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft);
+ HP_BAR(playerLeft);
+ }
+ SEND_IN_MESSAGE("Grimer");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight);
+ }
+}
+
+DOUBLE_BATTLE_TEST("Pursuit attacks a switching foe but not switching allies")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_ZIGZAGOON);
+ PLAYER(SPECIES_GRIMER);
+ OPPONENT(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_LINOONE);
+ OPPONENT(SPECIES_ABRA);
+ } WHEN {
+ TURN { SWITCH(playerLeft, 2); SWITCH(opponentRight, 2); MOVE(playerRight, MOVE_PURSUIT, target: opponentRight); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); }
+ } SCENE {
+ SWITCH_OUT_MESSAGE("Wobbuffet");
+ NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, playerRight);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft);
+ SEND_IN_MESSAGE("Grimer");
+ MESSAGE("2 withdrew Linoone!");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, playerRight);
+ MESSAGE("2 sent out Abra!");
+ }
+}
+
+DOUBLE_BATTLE_TEST("Pursuit only attacks the first switching foe")
+{
+ // This test does not make sense for B_PURSUIT_TARGET < GEN_4
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_ZIGZAGOON);
+ PLAYER(SPECIES_GRIMER);
+ PLAYER(SPECIES_SUNKERN);
+ OPPONENT(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_LINOONE);
+ } WHEN {
+ TURN { SWITCH(playerLeft, 2); SWITCH(playerRight, 3); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); MOVE(opponentRight, MOVE_PURSUIT, target: playerLeft); }
+ } SCENE {
+ SWITCH_OUT_MESSAGE("Wobbuffet");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft);
+ HP_BAR(playerLeft);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight);
+ HP_BAR(playerLeft);
+ SEND_IN_MESSAGE("Grimer");
+ SWITCH_OUT_MESSAGE("Zigzagoon");
+ NONE_OF {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft);
+ HP_BAR(playerRight);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight);
+ HP_BAR(playerRight);
+ }
+ SEND_IN_MESSAGE("Sunkern");
+ }
+}
+
+DOUBLE_BATTLE_TEST("Pursuit only attacks a switching foe if foe is alive")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET) { HP(1); }
+ PLAYER(SPECIES_ZIGZAGOON);
+ PLAYER(SPECIES_GRIMER);
+ PLAYER(SPECIES_SUNKERN);
+ OPPONENT(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_LINOONE);
+ } WHEN {
+ TURN { SWITCH(playerLeft, 2); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); MOVE(opponentRight, MOVE_PURSUIT, target: playerLeft); SEND_OUT(playerLeft, 2); }
+ } SCENE {
+ SWITCH_OUT_MESSAGE("Wobbuffet");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft);
+ HP_BAR(playerLeft);
+ NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight);
+ MESSAGE("Wobbuffet fainted!");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight);
+ SEND_IN_MESSAGE("Grimer");
+ }
+}
+
+DOUBLE_BATTLE_TEST("Pursuit attacks the second switching foe if the first faints from pursuit")
+{
+ // This test does not make sense for B_PURSUIT_TARGET < GEN_4
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET) { HP(1); }
+ PLAYER(SPECIES_ZIGZAGOON);
+ PLAYER(SPECIES_GRIMER);
+ PLAYER(SPECIES_SUNKERN);
+ OPPONENT(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_LINOONE);
+ } WHEN {
+ TURN { SWITCH(playerLeft, 2); SWITCH(playerRight, 3); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); MOVE(opponentRight, MOVE_PURSUIT, target: playerRight); SEND_OUT(playerLeft, 2); }
+ } SCENE {
+ SWITCH_OUT_MESSAGE("Wobbuffet");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft);
+ HP_BAR(playerLeft);
+ MESSAGE("Wobbuffet fainted!");
+ NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight);
+ SWITCH_OUT_MESSAGE("Zigzagoon");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight);
+ HP_BAR(playerRight);
+ SEND_IN_MESSAGE("Sunkern");
+ SEND_IN_MESSAGE("Grimer");
+ }
+}
+
+DOUBLE_BATTLE_TEST("Pursuit only attacks a switching foe if user is alive")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_ZIGZAGOON);
+ PLAYER(SPECIES_GRIMER);
+ OPPONENT(SPECIES_WYNAUT) { HP(1); }
+ OPPONENT(SPECIES_LINOONE);
+ OPPONENT(SPECIES_SUNKERN);
+ } WHEN {
+ TURN { MOVE(playerLeft, MOVE_VOLT_SWITCH, target: opponentLeft); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); SEND_OUT(playerLeft, 2); SEND_OUT(opponentLeft, 2); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_VOLT_SWITCH, playerLeft);
+ MESSAGE("The opposing Wynaut fainted!");
+ NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft);
+ SEND_IN_MESSAGE("Grimer");
+ }
+}
+
+SINGLE_BATTLE_TEST("Pursuit attacks a switching foe but fails if user is asleep")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_WYNAUT) { Status1(STATUS1_SLEEP_TURN(2)); }
+ } WHEN {
+ TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT); }
+ } SCENE {
+ SWITCH_OUT_MESSAGE("Wobbuffet");
+ MESSAGE("The opposing Wynaut is fast asleep.");
+ NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent);
+ SEND_IN_MESSAGE("Zigzagoon");
+ }
+}
+
+SINGLE_BATTLE_TEST("Pursuit attacks a switching foe and takes Life Orb damage")
+{
+ GIVEN {
+ ASSUME(gItemsInfo[ITEM_LIFE_ORB].holdEffect == HOLD_EFFECT_LIFE_ORB);
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_WYNAUT) { Item(ITEM_LIFE_ORB); }
+ } WHEN {
+ TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT); }
+ } SCENE {
+ SWITCH_OUT_MESSAGE("Wobbuffet");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent);
+ HP_BAR(opponent);
+ SEND_IN_MESSAGE("Zigzagoon");
+ }
+}
+
+DOUBLE_BATTLE_TEST("Pursuit attacks a switching foe but isn't affected by Follow Me")
+{
+ GIVEN {
+ ASSUME(gMovesInfo[MOVE_FOLLOW_ME].effect == EFFECT_FOLLOW_ME);
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_CLEFABLE);
+ PLAYER(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_LINOONE);
+ } WHEN {
+ TURN { MOVE(playerRight, MOVE_FOLLOW_ME); MOVE(playerLeft, MOVE_VOLT_SWITCH, target: opponentLeft); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); SEND_OUT(playerLeft, 2); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_FOLLOW_ME, playerRight);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_VOLT_SWITCH, playerLeft);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft);
+ SEND_IN_MESSAGE("Zigzagoon");
+ }
+}
+
+SINGLE_BATTLE_TEST("Pursuit user mega evolves before attacking a switching foe and hits twice if user has Parental Bond")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); }
+ } WHEN {
+ TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT, gimmick: GIMMICK_MEGA); }
+ } SCENE {
+ SWITCH_OUT_MESSAGE("Wobbuffet");
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_MEGA_EVOLUTION, opponent);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent);
+ HP_BAR(player);
+ HP_BAR(player);
+ SEND_IN_MESSAGE("Zigzagoon");
+ }
+}
+
+DOUBLE_BATTLE_TEST("Pursuit user mega evolves before attacking a switching foe and others mega evolve after switch")
+{
+ GIVEN {
+ PLAYER(SPECIES_CHARIZARD) { Item(ITEM_CHARIZARDITE_X); }
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); }
+ } WHEN {
+ TURN { SWITCH(playerRight, 2); MOVE(opponentRight, MOVE_PURSUIT, gimmick: GIMMICK_MEGA, target: playerRight); MOVE(playerLeft, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
+ } SCENE {
+ SWITCH_OUT_MESSAGE("Wobbuffet");
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_MEGA_EVOLUTION, opponentRight);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight);
+ HP_BAR(playerRight);
+ HP_BAR(playerRight);
+ SEND_IN_MESSAGE("Zigzagoon");
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_MEGA_EVOLUTION, playerLeft);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerLeft);
+ }
+}
+
+SINGLE_BATTLE_TEST("Pursuit user terastalizes before attacking a switching foe and gets the damage boost from the tera type", s16 damage)
+{
+ u32 tera;
+ PARAMETRIZE { tera = GIMMICK_NONE; }
+ PARAMETRIZE { tera = GIMMICK_TERA; }
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_KANGASKHAN) { TeraType(TYPE_DARK); }
+ } WHEN {
+ TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT, gimmick: tera); }
+ } SCENE {
+ SWITCH_OUT_MESSAGE("Wobbuffet");
+ if (tera == GIMMICK_TERA)
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_ACTIVATE, opponent);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent);
+ HP_BAR(player, captureDamage: &results[i].damage);
+ SEND_IN_MESSAGE("Zigzagoon");
+ } FINALLY {
+ EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
+ }
+}
+
+DOUBLE_BATTLE_TEST("Pursuit affected by Electrify fails against immune target")
+{
+ GIVEN {
+ ASSUME(gMovesInfo[MOVE_ELECTRIFY].effect == EFFECT_ELECTRIFY);
+ PLAYER(SPECIES_DONPHAN);
+ PLAYER(SPECIES_HELIOLISK);
+ PLAYER(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_LINOONE);
+ } WHEN {
+ TURN { MOVE(playerRight, MOVE_ELECTRIFY, target: opponentLeft); MOVE(playerLeft, MOVE_VOLT_SWITCH, target: opponentLeft); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); SEND_OUT(playerLeft, 2); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIFY, playerRight);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_VOLT_SWITCH, playerLeft);
+ NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft);
+ SEND_IN_MESSAGE("Zigzagoon");
+ }
+}
+
+DOUBLE_BATTLE_TEST("Pursuit affected by Electrify fails against target with Volt Absorb")
+{
+ GIVEN {
+ ASSUME(gMovesInfo[MOVE_ELECTRIFY].effect == EFFECT_ELECTRIFY);
+ PLAYER(SPECIES_LANTURN) { Ability(ABILITY_VOLT_ABSORB); }
+ PLAYER(SPECIES_HELIOLISK);
+ PLAYER(SPECIES_ZIGZAGOON);
+ OPPONENT(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_LINOONE);
+ } WHEN {
+ TURN { MOVE(playerRight, MOVE_ELECTRIFY, target: opponentLeft); MOVE(playerLeft, MOVE_VOLT_SWITCH, target: opponentLeft); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); SEND_OUT(playerLeft, 2); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIFY, playerRight);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_VOLT_SWITCH, playerLeft);
+ NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft);
+ ABILITY_POPUP(playerLeft, ABILITY_VOLT_ABSORB);
+ SEND_IN_MESSAGE("Zigzagoon");
+ }
+}
+
SINGLE_BATTLE_TEST("Pursuited mon correctly switches out after it got hit and activated ability Tangling Hair")
{
GIVEN {
- PLAYER(SPECIES_DUGTRIO) { Ability(ABILITY_TANGLING_HAIR); }
+ PLAYER(SPECIES_DUGTRIO_ALOLA) { Ability(ABILITY_TANGLING_HAIR); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET);
@@ -25,6 +477,80 @@ SINGLE_BATTLE_TEST("Pursuited mon correctly switches out after it got hit and ac
}
}
+DOUBLE_BATTLE_TEST("Pursuited mon correctly switches out after it got hit and activated ability Tangling Hair - Doubles")
+{
+ GIVEN {
+ PLAYER(SPECIES_DUGTRIO_ALOLA) { Ability(ABILITY_TANGLING_HAIR); }
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { SWITCH(playerLeft, 2); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); MOVE(opponentRight, MOVE_PURSUIT, target: playerLeft); }
+ } SCENE {
+ SWITCH_OUT_MESSAGE("Dugtrio");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft);
+ ABILITY_POPUP(playerLeft, ABILITY_TANGLING_HAIR);
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
+ MESSAGE("The opposing Wynaut's Speed fell!");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight);
+ ABILITY_POPUP(playerLeft, ABILITY_TANGLING_HAIR);
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
+ MESSAGE("The opposing Wobbuffet's Speed fell!");
+ SEND_IN_MESSAGE("Wobbuffet");
+ }
+}
+
+SINGLE_BATTLE_TEST("Pursuited mon correctly switches out after it got hit and activated ability Tangling Hair - Mirror Armor")
+{
+ GIVEN {
+ PLAYER(SPECIES_DUGTRIO_ALOLA) { Ability(ABILITY_TANGLING_HAIR); }
+ PLAYER(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); }
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT); }
+ } SCENE {
+ SWITCH_OUT_MESSAGE("Dugtrio");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent);
+ ABILITY_POPUP(player, ABILITY_TANGLING_HAIR);
+ ABILITY_POPUP(opponent, ABILITY_MIRROR_ARMOR);
+ SEND_IN_MESSAGE("Wobbuffet");
+ }
+}
+
+DOUBLE_BATTLE_TEST("Pursuited mon correctly switches out after it got hit and activated ability Cotton Down")
+{
+ GIVEN {
+ PLAYER(SPECIES_ELDEGOSS) { Ability(ABILITY_COTTON_DOWN); }
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { SWITCH(playerLeft, 2); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); MOVE(opponentRight, MOVE_PURSUIT, target: playerLeft); }
+ } SCENE {
+ SWITCH_OUT_MESSAGE("Eldegoss");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft);
+ ABILITY_POPUP(playerLeft, ABILITY_COTTON_DOWN);
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
+ MESSAGE("The opposing Wynaut's Speed fell!");
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
+ MESSAGE("Wobbuffet's Speed fell!");
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
+ MESSAGE("The opposing Wobbuffet's Speed fell!");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight);
+ ABILITY_POPUP(playerLeft, ABILITY_COTTON_DOWN);
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
+ MESSAGE("The opposing Wynaut's Speed fell!");
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
+ MESSAGE("Wobbuffet's Speed fell!");
+ ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
+ MESSAGE("The opposing Wobbuffet's Speed fell!");
+ SEND_IN_MESSAGE("Wobbuffet");
+ }
+}
+
// Checked so that Pursuit has only 1 PP and it forces the player to use Struggle.
SINGLE_BATTLE_TEST("Pursuit becomes a locked move after being used on switch-out while holding a Choice Item")
{
@@ -46,4 +572,42 @@ SINGLE_BATTLE_TEST("Pursuit becomes a locked move after being used on switch-out
}
}
+SINGLE_BATTLE_TEST("Pursuit attacks a switching foe and switchin is correctly stored")
+{
+ u32 switchin;
+ PARAMETRIZE { switchin = 1; }
+ PARAMETRIZE { switchin = 2; }
+ PARAMETRIZE { switchin = 3; }
+ PARAMETRIZE { switchin = 4; }
+
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_ZIGZAGOON);
+ PLAYER(SPECIES_AIPOM);
+ PLAYER(SPECIES_ABRA);
+ PLAYER(SPECIES_VENIPEDE);
+ OPPONENT(SPECIES_WYNAUT);
+ } WHEN {
+ TURN { SWITCH(player, switchin); MOVE(opponent, MOVE_PURSUIT); }
+ } SCENE {
+ SWITCH_OUT_MESSAGE("Wobbuffet");
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent);
+ switch (switchin)
+ {
+ case 1:
+ SEND_IN_MESSAGE("Zigzagoon");
+ break;
+ case 2:
+ SEND_IN_MESSAGE("Aipom");
+ break;
+ case 3:
+ SEND_IN_MESSAGE("Abra");
+ break;
+ case 4:
+ SEND_IN_MESSAGE("Venipede");
+ break;
+ }
+ }
+}
+
TO_DO_BATTLE_TEST("Baton Pass doesn't cause Pursuit to increase its power or priority");
diff --git a/test/battle/spread_moves.c b/test/battle/spread_moves.c
index 7b395a1cc2..5228e3041f 100644
--- a/test/battle/spread_moves.c
+++ b/test/battle/spread_moves.c
@@ -411,3 +411,25 @@ DOUBLE_BATTLE_TEST("Spread Moves: Doesn't affect message on both opposing mons")
MESSAGE("It doesn't affect the opposing Pidgey and Hoothoot…");
}
}
+
+DOUBLE_BATTLE_TEST("Spread Moves: Unless move hits every target user will not include partner in the target count")
+{
+ GIVEN {
+ PLAYER(SPECIES_SANDSLASH);
+ PLAYER(SPECIES_WYNAUT) { HP(1); }
+ PLAYER(SPECIES_RALTS);
+ OPPONENT(SPECIES_TORKOAL);
+ OPPONENT(SPECIES_TORKOAL);
+ } WHEN {
+ TURN { MOVE(opponentRight, MOVE_ICY_WIND); MOVE(playerLeft, MOVE_ROCK_SLIDE); SEND_OUT(playerRight, 2); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_ICY_WIND, opponentRight);
+ HP_BAR(playerLeft);
+ HP_BAR(playerRight);
+
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft);
+ HP_BAR(opponentLeft);
+ HP_BAR(opponentRight);
+ MESSAGE("It's super effective on the opposing Torkoal and Torkoal!");
+ }
+}
diff --git a/test/test_runner.c b/test/test_runner.c
index f7c4cf780e..d3196a20e1 100644
--- a/test/test_runner.c
+++ b/test/test_runner.c
@@ -356,9 +356,14 @@ top:
if (gTestRunnerState.result == TEST_RESULT_PASS)
{
if (gTestRunnerState.result != gTestRunnerState.expectedResult)
+ {
+ Test_MgbaPrintf(":L%s:%d", gTestRunnerState.test->filename, SourceLine(0));
Test_MgbaPrintf(":U%s%s\e[0m", color, result);
+ }
else
+ {
Test_MgbaPrintf(":P%s%s\e[0m", color, result);
+ }
}
else if (gTestRunnerState.result == TEST_RESULT_ASSUMPTION_FAIL)
Test_MgbaPrintf(":A%s%s\e[0m", color, result);
@@ -490,6 +495,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));
ReinitCallbacks();
IRQ_LR = ((uintptr_t)JumpToAgbMainLoop & ~1) + 4;
}
diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c
index 6faf6a4715..50d389c545 100644
--- a/test/test_runner_battle.c
+++ b/test/test_runner_battle.c
@@ -1160,6 +1160,7 @@ static s32 TryMessage(s32 i, s32 n, const u8 *string)
switch (string[j])
{
case CHAR_SPACE:
+ case CHAR_NBSP:
case CHAR_PROMPT_SCROLL:
case CHAR_PROMPT_CLEAR:
case CHAR_NEWLINE:
diff --git a/test/text.c b/test/text.c
index 17d9ab0ee9..ed343d1039 100644
--- a/test/text.c
+++ b/test/text.c
@@ -44,7 +44,7 @@ TEST("Move names fit on Battle Screen")
TEST("Move names fit on Contest Screen")
{
u32 i;
- const u32 fontId = FONT_NARROWER, widthPx = 61;
+ const u32 fontId = FONT_NARROWER, widthPx = 59;
u32 move = MOVE_NONE;
for (i = 1; i < MOVES_COUNT; i++)
{
@@ -53,7 +53,9 @@ TEST("Move names fit on Contest Screen")
// All moves explicitly listed here are too big to fit.
switch (move)
{
+ case MOVE_STOMPING_TANTRUM:
case MOVE_NATURES_MADNESS:
+ case MOVE_DOUBLE_IRON_BASH:
EXPECT_GT(GetStringWidth(fontId, gMovesInfo[move].name, 0), widthPx);
break;
default:
@@ -65,14 +67,11 @@ TEST("Move names fit on Contest Screen")
TEST("Move names fit on TMs & HMs Bag Screen")
{
u32 i;
- const u32 fontId = FONT_NARROWER, widthPx = 63;
+ const u32 fontId = FONT_NARROWER, widthPx = 61;
u32 move = MOVE_NONE;
- for (i = 1; i < ITEMS_COUNT; i++)
+ for (i = 1; i < MOVES_COUNT; i++)
{
- if (gItemsInfo[i].pocket == POCKET_TM_HM)
- {
- PARAMETRIZE_LABEL("%S", gMovesInfo[gItemsInfo[i].secondaryId].name) { move = gItemsInfo[i].secondaryId; }
- }
+ PARAMETRIZE_LABEL("%S", gMovesInfo[i].name) { move = i; }
}
EXPECT_LE(GetStringWidth(fontId, gMovesInfo[move].name, 0), widthPx);
}
@@ -105,7 +104,7 @@ TEST("Item names fit on Bag Screen (list)")
{
u32 i;
const u32 fontId = FONT_NARROWER;
- const u32 tmHmBerryWidthPx = 71, restWidthPx = 88;
+ const u32 tmHmBerryWidthPx = 61, restWidthPx = 88;
u32 item = ITEM_NONE;
for (i = 1; i < ITEMS_COUNT; i++)
{
@@ -122,7 +121,7 @@ TEST("Item plural names fit on Bag Screen (left box)")
{
u32 i;
// -6 for the question mark in FONT_NORMAL.
- const u32 fontId = FONT_NARROWER, widthPx = 102 - 6;
+ const u32 fontId = FONT_NARROWER, widthPx = 101 - 6;
u32 item = ITEM_NONE;
u8 pluralName[ITEM_NAME_PLURAL_LENGTH + 1];
for (i = 1; i < ITEMS_COUNT; i++)
@@ -133,6 +132,18 @@ TEST("Item plural names fit on Bag Screen (left box)")
EXPECT_LE(GetStringWidth(fontId, pluralName, 0), widthPx);
}
+TEST("Item names fit on PC Storage (list)")
+{
+ u32 i;
+ const u32 fontId = FONT_NARROWER, widthPx = 73;
+ u32 item = ITEM_NONE;
+ for (i = 1; i < ITEMS_COUNT; i++)
+ {
+ PARAMETRIZE_LABEL("%S", gItemsInfo[i].name) { item = i; }
+ }
+ EXPECT_LE(GetStringWidth(fontId, gItemsInfo[item].name, 0), widthPx);
+}
+
TEST("Item plural names fit on PC storage (left box)")
{
u32 i;
@@ -151,108 +162,22 @@ TEST("Item plural names fit on PC storage (left box)")
TEST("Item names fit on Pokemon Storage System")
{
u32 i;
- const u32 fontId = FONT_SMALL_NARROWER, widthPx = 50;
+ const u32 fontId = FONT_SMALL_NARROWER, widthPx = 66;
u32 item = ITEM_NONE;
for (i = 1; i < ITEMS_COUNT; i++)
{
if (gItemsInfo[i].importance) continue;
PARAMETRIZE_LABEL("%S", gItemsInfo[i].name) { item = i; }
}
- // All items explicitly listed here are too big to fit. The ones
- // with a hold effect are listed at the bottom in case you want to
- // focus on making them fit (they are the most likely to appear on
- // the storage system UI, along with anything that could be held
- // in the wild).
+ // All items explicitly listed here are too big to fit.
switch (item)
{
- case ITEM_ENERGY_POWDER:
- case ITEM_PEWTER_CRUNCHIES:
- case ITEM_RAGE_CANDY_BAR:
- case ITEM_LUMIOSE_GALETTE:
- case ITEM_HEALTH_FEATHER:
- case ITEM_MUSCLE_FEATHER:
- case ITEM_RESIST_FEATHER:
- case ITEM_GENIUS_FEATHER:
- case ITEM_CLEVER_FEATHER:
- case ITEM_ABILITY_CAPSULE:
- case ITEM_DYNAMAX_CANDY:
- case ITEM_MAX_MUSHROOMS:
- case ITEM_GOLD_BOTTLE_CAP:
- case ITEM_PRETTY_FEATHER:
- case ITEM_STRANGE_SOUVENIR:
- case ITEM_FOSSILIZED_BIRD:
- case ITEM_FOSSILIZED_FISH:
- case ITEM_FOSSILIZED_DRAKE:
- case ITEM_FOSSILIZED_DINO:
- case ITEM_SURPRISE_MULCH:
- case ITEM_YELLOW_APRICORN:
- case ITEM_GREEN_APRICORN:
- case ITEM_WHITE_APRICORN:
- case ITEM_BLACK_APRICORN:
- case ITEM_THUNDER_STONE:
- case ITEM_GALARICA_WREATH:
- case ITEM_STRAWBERRY_SWEET:
- case ITEM_AUSPICIOUS_ARMOR:
- case ITEM_BIG_BAMBOO_SHOOT:
- case ITEM_GIMMIGHOUL_COIN:
- case ITEM_LEADERS_CREST:
- case ITEM_MALICIOUS_ARMOR:
- case ITEM_TINY_BAMBOO_SHOOT:
- case ITEM_BUG_TERA_SHARD:
- case ITEM_DARK_TERA_SHARD:
- case ITEM_DRAGON_TERA_SHARD:
case ITEM_ELECTRIC_TERA_SHARD:
- case ITEM_FAIRY_TERA_SHARD:
case ITEM_FIGHTING_TERA_SHARD:
- case ITEM_FIRE_TERA_SHARD:
- case ITEM_FLYING_TERA_SHARD:
- case ITEM_GHOST_TERA_SHARD:
- case ITEM_GRASS_TERA_SHARD:
- case ITEM_GROUND_TERA_SHARD:
- case ITEM_ICE_TERA_SHARD:
- case ITEM_NORMAL_TERA_SHARD:
- case ITEM_POISON_TERA_SHARD:
case ITEM_PSYCHIC_TERA_SHARD:
- case ITEM_ROCK_TERA_SHARD:
- case ITEM_STEEL_TERA_SHARD:
- case ITEM_WATER_TERA_SHARD:
- case ITEM_BLACK_AUGURITE:
case ITEM_UNREMARKABLE_TEACUP:
case ITEM_MASTERPIECE_TEACUP:
- case ITEM_FRESH_START_MOCHI:
- case ITEM_STELLAR_TERA_SHARD:
- case ITEM_JUBILIFE_MUFFIN:
- case ITEM_SUPERB_REMEDY:
- case ITEM_AUX_POWERGUARD:
- case ITEM_CHOICE_DUMPLING:
case ITEM_TWICE_SPICED_RADISH:
- // Items with hold effects:
- case ITEM_ELECTRIC_MEMORY:
- case ITEM_FIGHTING_MEMORY:
- case ITEM_GROUND_MEMORY:
- case ITEM_PSYCHIC_MEMORY:
- case ITEM_DRAGON_MEMORY:
- case ITEM_CHARIZARDITE_X:
- case ITEM_CHARIZARDITE_Y:
- case ITEM_ULTRANECROZIUM_Z:
- case ITEM_DEEP_SEA_SCALE:
- case ITEM_DEEP_SEA_TOOTH:
- case ITEM_NEVER_MELT_ICE:
- case ITEM_WEAKNESS_POLICY:
- case ITEM_SAFETY_GOGGLES:
- case ITEM_ADRENALINE_ORB:
- case ITEM_TERRAIN_EXTENDER:
- case ITEM_PROTECTIVE_PADS:
- case ITEM_HEAVY_DUTY_BOOTS:
- case ITEM_UTILITY_UMBRELLA:
- case ITEM_MARANGA_BERRY:
- case ITEM_PUNCHING_GLOVE:
- case ITEM_BOOSTER_ENERGY:
- case ITEM_ADAMANT_CRYSTAL:
- case ITEM_LUSTROUS_GLOBE:
- case ITEM_CORNERSTONE_MASK:
- case ITEM_WELLSPRING_MASK:
- case ITEM_HEARTHFLAME_MASK:
EXPECT_GT(GetStringWidth(fontId, gItemsInfo[item].name, 0), widthPx);
break;
default:
@@ -398,7 +323,7 @@ TEST("Species names fit on Pokemon Storage System")
}
}
EXPECT_LE(GetStringWidth(FONT_NARROWER, gSpeciesInfo[species].speciesName, 0), 66);
- EXPECT_LE(GetStringWidth(FONT_SHORT_NARROW, gSpeciesInfo[species].speciesName, 0), 60);
+ EXPECT_LE(GetStringWidth(FONT_SHORT_NARROWER, gSpeciesInfo[species].speciesName, 0), 60);
}
TEST("Species names fit on Contest Screen")
@@ -434,7 +359,7 @@ TEST("Species names fit on Contest Screen - Rankings")
TEST("Species names fit on Battle Dome Screen")
{
u32 i;
- const u32 fontId = FONT_SHORT_NARROW, widthPx = 60;
+ const u32 fontId = FONT_SHORT_NARROWER, widthPx = 60;
u32 species = SPECIES_NONE;
for (i = 1; i < NUM_SPECIES; i++)
{
diff --git a/tools/learnset_helpers/porymoves_files/b2w2.json b/tools/learnset_helpers/porymoves_files/b2w2.json
index 976b125c6c..bd1762990e 100644
--- a/tools/learnset_helpers/porymoves_files/b2w2.json
+++ b/tools/learnset_helpers/porymoves_files/b2w2.json
@@ -50290,7 +50290,7 @@
"MOVE_SNORE"
]
},
- "WORMADAM_PLANT_CLOAK": {
+ "WORMADAM_PLANT": {
"LevelMoves": [
{
"Level": 1,
diff --git a/tools/learnset_helpers/porymoves_files/bdsp.json b/tools/learnset_helpers/porymoves_files/bdsp.json
index 8e4ac589d3..af2e75a3ae 100644
--- a/tools/learnset_helpers/porymoves_files/bdsp.json
+++ b/tools/learnset_helpers/porymoves_files/bdsp.json
@@ -46223,7 +46223,7 @@
"EggMoves": [],
"TutorMoves": []
},
- "WORMADAM_PLANT_CLOAK": {
+ "WORMADAM_PLANT": {
"LevelMoves": [
{
"Level": 0,
diff --git a/tools/learnset_helpers/porymoves_files/bw.json b/tools/learnset_helpers/porymoves_files/bw.json
index 7728235c5f..4a93b57602 100644
--- a/tools/learnset_helpers/porymoves_files/bw.json
+++ b/tools/learnset_helpers/porymoves_files/bw.json
@@ -45087,7 +45087,7 @@
"EggMoves": [],
"TutorMoves": []
},
- "WORMADAM_PLANT_CLOAK": {
+ "WORMADAM_PLANT": {
"LevelMoves": [
{
"Level": 1,
diff --git a/tools/learnset_helpers/porymoves_files/dp.json b/tools/learnset_helpers/porymoves_files/dp.json
index 666a6dda58..fdae45c2a6 100644
--- a/tools/learnset_helpers/porymoves_files/dp.json
+++ b/tools/learnset_helpers/porymoves_files/dp.json
@@ -44067,7 +44067,7 @@
"EggMoves": [],
"TutorMoves": []
},
- "WORMADAM_PLANT_CLOAK": {
+ "WORMADAM_PLANT": {
"LevelMoves": [
{
"Level": 1,
diff --git a/tools/learnset_helpers/porymoves_files/hgss.json b/tools/learnset_helpers/porymoves_files/hgss.json
index b0241c96f4..8aaf2714b3 100644
--- a/tools/learnset_helpers/porymoves_files/hgss.json
+++ b/tools/learnset_helpers/porymoves_files/hgss.json
@@ -49305,7 +49305,7 @@
"MOVE_STRING_SHOT"
]
},
- "WORMADAM_PLANT_CLOAK": {
+ "WORMADAM_PLANT": {
"LevelMoves": [
{
"Level": 1,
diff --git a/tools/learnset_helpers/porymoves_files/la.json b/tools/learnset_helpers/porymoves_files/la.json
index 599596a902..4492a37c69 100644
--- a/tools/learnset_helpers/porymoves_files/la.json
+++ b/tools/learnset_helpers/porymoves_files/la.json
@@ -8433,7 +8433,7 @@
"EggMoves": [],
"TutorMoves": []
},
- "WORMADAM_PLANT_CLOAK": {
+ "WORMADAM_PLANT": {
"LevelMoves": [
{
"Level": 1,
diff --git a/tools/learnset_helpers/porymoves_files/oras.json b/tools/learnset_helpers/porymoves_files/oras.json
index 11a737628e..da1a3bf21f 100644
--- a/tools/learnset_helpers/porymoves_files/oras.json
+++ b/tools/learnset_helpers/porymoves_files/oras.json
@@ -53725,7 +53725,7 @@
"MOVE_SNORE"
]
},
- "WORMADAM_PLANT_CLOAK": {
+ "WORMADAM_PLANT": {
"LevelMoves": [
{
"Level": 1,
diff --git a/tools/learnset_helpers/porymoves_files/pt.json b/tools/learnset_helpers/porymoves_files/pt.json
index e969777fa6..bf2ace3c59 100644
--- a/tools/learnset_helpers/porymoves_files/pt.json
+++ b/tools/learnset_helpers/porymoves_files/pt.json
@@ -48085,7 +48085,7 @@
"MOVE_SNORE"
]
},
- "WORMADAM_PLANT_CLOAK": {
+ "WORMADAM_PLANT": {
"LevelMoves": [
{
"Level": 1,
diff --git a/tools/learnset_helpers/porymoves_files/sm.json b/tools/learnset_helpers/porymoves_files/sm.json
index 65255a69fa..d79ab5c4e9 100644
--- a/tools/learnset_helpers/porymoves_files/sm.json
+++ b/tools/learnset_helpers/porymoves_files/sm.json
@@ -48246,7 +48246,7 @@
"EggMoves": [],
"TutorMoves": []
},
- "WORMADAM_PLANT_CLOAK": {
+ "WORMADAM_PLANT": {
"LevelMoves": [
{
"Level": 0,
diff --git a/tools/learnset_helpers/porymoves_files/sv.json b/tools/learnset_helpers/porymoves_files/sv.json
index 04bc72f9e6..190b084611 100644
--- a/tools/learnset_helpers/porymoves_files/sv.json
+++ b/tools/learnset_helpers/porymoves_files/sv.json
@@ -36838,7 +36838,7 @@
"EggMoves": [],
"TutorMoves": []
},
- "WORMADAM_PLANT_CLOAK": {
+ "WORMADAM_PLANT": {
"LevelMoves": [],
"PreEvoMoves": [],
"TMMoves": [],
diff --git a/tools/learnset_helpers/porymoves_files/usum.json b/tools/learnset_helpers/porymoves_files/usum.json
index ed4cfb69e0..2587a7de81 100644
--- a/tools/learnset_helpers/porymoves_files/usum.json
+++ b/tools/learnset_helpers/porymoves_files/usum.json
@@ -53477,7 +53477,7 @@
"MOVE_SNORE"
]
},
- "WORMADAM_PLANT_CLOAK": {
+ "WORMADAM_PLANT": {
"LevelMoves": [
{
"Level": 0,
diff --git a/tools/learnset_helpers/porymoves_files/xy.json b/tools/learnset_helpers/porymoves_files/xy.json
index 8be594e6d7..1cb68d527b 100644
--- a/tools/learnset_helpers/porymoves_files/xy.json
+++ b/tools/learnset_helpers/porymoves_files/xy.json
@@ -47960,7 +47960,7 @@
"EggMoves": [],
"TutorMoves": []
},
- "WORMADAM_PLANT_CLOAK": {
+ "WORMADAM_PLANT": {
"LevelMoves": [
{
"Level": 1,