diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml index 310f92c118..edebc1bbf0 100644 --- a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml +++ b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml @@ -23,9 +23,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.9.0 (Latest release) + - 1.9.1 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.9.0 - 1.8.6 - 1.8.5 - 1.8.4 diff --git a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml index 9fcb1595a2..dd3024230b 100644 --- a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml +++ b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml @@ -23,9 +23,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.9.0 (Latest release) + - 1.9.1 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.9.0 - 1.8.6 - 1.8.5 - 1.8.4 diff --git a/.github/ISSUE_TEMPLATE/04_other_errors.yaml b/.github/ISSUE_TEMPLATE/04_other_errors.yaml index 73d9fd11d3..29960c267b 100644 --- a/.github/ISSUE_TEMPLATE/04_other_errors.yaml +++ b/.github/ISSUE_TEMPLATE/04_other_errors.yaml @@ -23,9 +23,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.9.0 (Latest release) + - 1.9.1 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.9.0 - 1.8.6 - 1.8.5 - 1.8.4 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0322cbe11f..c84110d7dd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,19 +15,12 @@ jobs: GAME_VERSION: EMERALD GAME_REVISION: 0 GAME_LANGUAGE: ENGLISH - MODERN: 0 COMPARE: 0 UNUSED_ERROR: 1 steps: - name: Checkout uses: actions/checkout@v2 - - name: Checkout agbcc - uses: actions/checkout@v2 - with: - path: agbcc - repository: pret/agbcc - - name: Install binutils run: | sudo apt update @@ -36,27 +29,13 @@ jobs: # gcc-arm-none-eabi is only needed for the modern build # as an alternative to dkP - - name: Install agbcc - run: | - ./build.sh - ./install.sh ../ - working-directory: agbcc - - - name: Agbcc + - name: ROM env: - MODERN: 0 - COMPARE: 0 - run: make -j${nproc} -O all - - - name: Modern - env: - MODERN: 1 COMPARE: 0 run: make -j${nproc} -O all - name: Test env: - MODERN: 1 TEST: 1 run: | make -j${nproc} -O pokeemerald-test.elf diff --git a/CHANGELOG.md b/CHANGELOG.md index 0999ae5f7e..fb2f38af1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Pokeemerald-Expansion Changelogs ## 1.9.x +- **[Version 1.9.1](docs/changelogs/1.9.x/1.9.1.md) - 🧹 Bugfix Release** - **[Version 1.9.0](docs/changelogs/1.9.x/1.9.0.md) - ✨ Feature Release** ## 1.8.x diff --git a/INSTALL.md b/INSTALL.md index 6349d24fbb..094f7b246a 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -327,7 +327,7 @@ If this works, then proceed to [Installation](#installation). Otherwise, ask for 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) @@ -541,7 +541,7 @@ If this works, then proceed to [Installation](#installation). Otherwise, ask for > ``` > 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. - + Now you're ready to build pokeemerald Expansion. ## Build pokeemerald Expansion @@ -596,58 +596,6 @@ To build **pokeemerald.elf** with debug symbols under a modern toolchain: ```bash make DINFO=1 ``` -Note that this is not necessary for a non-modern (agbcc) build since those are built with debug symbols by default. - -### agbcc - -
- Deprecated; installing agbcc is optional since 1.7.0. - -1. Install agbcc into pokeemerald-expansion. The commands to run depend on certain conditions. **You should only follow one of the listed instructions**: -- If agbcc has **not been built before** in the folder where you chose to store pokeemerald Expansion, run the following commands to build and install it into pokeemerald-expansion: - - ```bash - git clone https://github.com/pret/agbcc - cd agbcc - ./build.sh - ./install.sh ../pokeemerald-expansion - ``` - -- **Otherwise**, if agbcc has been built before (e.g. if the git clone above fails), but was **last built on a different terminal** than the one currently used (only relevant to Windows, e.g. switching from msys2 to WSL1), then run the following commands to build and install it into pokeemerald-expansion: - - ```bash - cd agbcc - git clean -fX - ./build.sh - ./install.sh ../pokeemerald-expansion - ``` - -- **Otherwise**, if agbcc has been built before on the same terminal, run the following commands to install agbcc into pokeemerald-expansion: - - ```bash - cd agbcc - ./install.sh ../pokeemerald-expansion - ``` - -
- Note... - - > If building agbcc or pokeemerald results in an error, try deleting the agbcc folder and re-installing agbcc as if it has not been built before. -
- -2. Once agbcc is installed, change directory back to the base directory where pokeemerald-expansion and agbcc are stored: - - ```bash - cd .. - ``` - -3. To compile with agbcc: - - ```bash - make agbcc - ``` - -
# Useful additional tools diff --git a/Makefile b/Makefile index 6dacf8b1d3..6f8951d378 100644 --- a/Makefile +++ b/Makefile @@ -25,10 +25,8 @@ AS := $(PREFIX)as LD := $(PREFIX)ld -# note: the makefile must be set up so MODERNCC is never called -# if MODERN=0 -MODERNCC := $(PREFIX)gcc -PATH_MODERNCC := PATH="$(PATH)" $(MODERNCC) +ARMCC := $(PREFIX)gcc +PATH_ARMCC := PATH="$(PATH)" $(ARMCC) ifeq ($(OS),Windows_NT) EXE := .exe @@ -40,45 +38,20 @@ TITLE := POKEMON EMER GAME_CODE := BPEE MAKER_CODE := 01 REVISION := 0 -MODERN ?= 1 TEST ?= 0 ANALYZE ?= 0 UNUSED_ERROR ?= 0 -ifeq (agbcc,$(MAKECMDGOALS)) - MODERN := 0 -endif - ifeq (check,$(MAKECMDGOALS)) TEST := 1 endif -# use arm-none-eabi-cpp for macOS -# as macOS's default compiler is clang -# and clang's preprocessor will warn on \u -# when preprocessing asm files, expecting a unicode literal -# we can't unconditionally use arm-none-eabi-cpp -# as installations which install binutils-arm-none-eabi -# don't come with it -ifneq ($(MODERN),1) - ifeq ($(shell uname -s),Darwin) - CPP := $(PREFIX)cpp - else - CPP := $(CC) -E - endif -else - CPP := $(PREFIX)cpp -endif +CPP := $(PREFIX)cpp -ROM_NAME := pokeemerald_agbcc.gba +ROM_NAME := pokeemerald.gba ELF_NAME := $(ROM_NAME:.gba=.elf) MAP_NAME := $(ROM_NAME:.gba=.map) -OBJ_DIR_NAME := build/emerald - -MODERN_ROM_NAME := pokeemerald.gba -MODERN_ELF_NAME := $(MODERN_ROM_NAME:.gba=.elf) -MODERN_MAP_NAME := $(MODERN_ROM_NAME:.gba=.map) -MODERN_OBJ_DIR_NAME := build/modern +OBJ_DIR_NAME := build/modern SHELL := bash -o pipefail @@ -86,14 +59,8 @@ ELF = $(ROM:.gba=.elf) MAP = $(ROM:.gba=.map) SYM = $(ROM:.gba=.sym) -TEST_OBJ_DIR_NAME_MODERN := build/modern-test -TEST_OBJ_DIR_NAME_AGBCC := build/test +TEST_OBJ_DIR_NAME := build/modern-test -ifeq ($(MODERN),0) -TEST_OBJ_DIR_NAME := $(TEST_OBJ_DIR_NAME_AGBCC) -else -TEST_OBJ_DIR_NAME := $(TEST_OBJ_DIR_NAME_MODERN) -endif TESTELF = $(ROM:.gba=-test.elf) HEADLESSELF = $(ROM:.gba=-test-headless.elf) @@ -116,17 +83,9 @@ SONG_BUILDDIR = $(OBJ_DIR)/$(SONG_SUBDIR) MID_BUILDDIR = $(OBJ_DIR)/$(MID_SUBDIR) TEST_BUILDDIR = $(OBJ_DIR)/$(TEST_SUBDIR) -ASFLAGS := -mcpu=arm7tdmi --defsym MODERN=$(MODERN) +ASFLAGS := -mcpu=arm7tdmi --defsym MODERN=1 -ifeq ($(MODERN),0) -CC1 := tools/agbcc/bin/agbcc$(EXE) -override CFLAGS += -mthumb-interwork -Wimplicit -Wparentheses -Werror -O2 -fhex-asm -g -ROM := $(ROM_NAME) -OBJ_DIR := $(OBJ_DIR_NAME) -LIBPATH := -L ../../tools/agbcc/lib -LIB := $(LIBPATH) -lgcc -lc -L../../libagbsyscall -lagbsyscall -else -CC1 = $(shell $(PATH_MODERNCC) --print-prog-name=cc1) -quiet +CC1 = $(shell $(PATH_ARMCC) --print-prog-name=cc1) -quiet override CFLAGS += -mthumb -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast -std=gnu17 -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias -Woverride-init ifeq ($(ANALYZE),1) override CFLAGS += -fanalyzer @@ -137,11 +96,10 @@ ifneq ($(GITHUB_REPOSITORY_OWNER),rh-hideout) override CFLAGS += -Wno-error=unused-variable -Wno-error=unused-const-variable -Wno-error=unused-parameter -Wno-error=unused-function -Wno-error=unused-but-set-parameter -Wno-error=unused-but-set-variable -Wno-error=unused-value -Wno-error=unused-local-typedefs endif endif -ROM := $(MODERN_ROM_NAME) -OBJ_DIR := $(MODERN_OBJ_DIR_NAME) -LIBPATH := -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libgcc.a))" -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libnosys.a))" -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libc.a))" +ROM := $(ROM_NAME) +OBJ_DIR := $(OBJ_DIR_NAME) +LIBPATH := -L "$(dir $(shell $(PATH_ARMCC) -mthumb -print-file-name=libgcc.a))" -L "$(dir $(shell $(PATH_ARMCC) -mthumb -print-file-name=libnosys.a))" -L "$(dir $(shell $(PATH_ARMCC) -mthumb -print-file-name=libc.a))" LIB := $(LIBPATH) -lc -lnosys -lgcc -L../../libagbsyscall -lagbsyscall -endif ifeq ($(TESTELF),$(MAKECMDGOALS)) TEST := 1 @@ -151,10 +109,7 @@ ifeq ($(TEST),1) OBJ_DIR := $(TEST_OBJ_DIR_NAME) endif -CPPFLAGS := -iquote include -iquote $(GFLIB_SUBDIR) -Wno-trigraphs -DMODERN=$(MODERN) -DTESTING=$(TEST) -ifneq ($(MODERN),1) -CPPFLAGS += -I tools/agbcc/include -I tools/agbcc -nostdinc -undef -endif +CPPFLAGS := -iquote include -iquote $(GFLIB_SUBDIR) -Wno-trigraphs -DMODERN=1 -DTESTING=$(TEST) SHA1 := $(shell { command -v sha1sum || command -v shasum; } 2>/dev/null) -c GFX := tools/gbagfx/gbagfx$(EXE) @@ -301,26 +256,17 @@ mostlyclean: tidynonmodern tidymodern tidycheck rm -f $(AUTO_GEN_TARGETS) @$(MAKE) clean -C libagbsyscall -tidy: tidynonmodern tidymodern tidycheck +tidy: tidymodern tidycheck -tidynonmodern: +tidymodern: rm -f $(ROM_NAME) $(ELF_NAME) $(MAP_NAME) rm -rf $(OBJ_DIR_NAME) -tidymodern: - rm -f $(MODERN_ROM_NAME) $(MODERN_ELF_NAME) $(MODERN_MAP_NAME) - rm -rf $(MODERN_OBJ_DIR_NAME) - tidycheck: rm -f $(TESTELF) $(HEADLESSELF) - rm -rf $(TEST_OBJ_DIR_NAME_MODERN) - rm -rf $(TEST_OBJ_DIR_NAME_AGBCC) + rm -rf $(TEST_OBJ_DIR_NAME) -ifneq ($(MODERN),0) -$(C_BUILDDIR)/berry_crush.o: override CFLAGS += -Wno-address-of-packed-member -endif - include graphics_file_rules.mk include map_data_rules.mk include spritesheet_rules.mk @@ -349,27 +295,11 @@ ifeq ($(COMPETITIVE_PARTY_SYNTAX),1) %.h: %.party tools ; $(CPP) $(CPPFLAGS) -traditional-cpp - < $< | $(TRAINERPROC) -o $@ -i $< - endif -ifeq ($(MODERN),0) -$(C_BUILDDIR)/libc.o: CC1 := tools/agbcc/bin/old_agbcc$(EXE) -$(C_BUILDDIR)/libc.o: CFLAGS := -O2 - -$(C_BUILDDIR)/siirtc.o: CFLAGS := -mthumb-interwork - -$(C_BUILDDIR)/agb_flash.o: CFLAGS := -O -mthumb-interwork -$(C_BUILDDIR)/agb_flash_1m.o: CFLAGS := -O -mthumb-interwork -$(C_BUILDDIR)/agb_flash_mx.o: CFLAGS := -O -mthumb-interwork - -$(C_BUILDDIR)/m4a.o: CC1 := tools/agbcc/bin/old_agbcc$(EXE) - -$(C_BUILDDIR)/record_mixing.o: CFLAGS += -ffreestanding -$(C_BUILDDIR)/librfu_intr.o: CC1 := tools/agbcc/bin/agbcc_arm$(EXE) -$(C_BUILDDIR)/librfu_intr.o: CFLAGS := -O2 -mthumb-interwork -quiet -else +$(C_BUILDDIR)/berry_crush.o: override CFLAGS += -Wno-address-of-packed-member $(C_BUILDDIR)/librfu_intr.o: CFLAGS := -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast $(C_BUILDDIR)/pokedex_plus_hgss.o: CFLAGS := -mthumb -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -Wno-pointer-to-int-cast -std=gnu17 -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias -Woverride-init # Annoyingly we can't turn this on just for src/data/trainers.h $(C_BUILDDIR)/data.o: CFLAGS += -fno-show-column -fno-diagnostics-show-caret -endif ifeq ($(DINFO),1) override CFLAGS += -g @@ -488,13 +418,8 @@ $1: $2 $$(shell $(SCANINC) -I include -I tools/agbcc/include -I gflib $2) endef $(foreach src, $(TEST_SRCS), $(eval $(call TEST_DEP,$(patsubst $(TEST_SUBDIR)/%.c,$(TEST_BUILDDIR)/%.o,$(src)),$(src),$(patsubst $(TEST_SUBDIR)/%.c,%,$(src))))) -ifeq ($(MODERN),0) -LD_SCRIPT := ld_script.ld -LD_SCRIPT_DEPS := $(OBJ_DIR)/sym_bss.ld $(OBJ_DIR)/sym_common.ld $(OBJ_DIR)/sym_ewram.ld -else LD_SCRIPT := ld_script_modern.ld LD_SCRIPT_DEPS := -endif $(OBJ_DIR)/ld_script.ld: $(LD_SCRIPT) $(LD_SCRIPT_DEPS) cd $(OBJ_DIR) && sed "s#tools/#../../tools/#g" ../../$(LD_SCRIPT) > ld_script.ld @@ -541,7 +466,7 @@ check: $(TESTELF) $(ROMTESTHYDRA) $(ROMTEST) $(OBJCOPY) $(HEADLESSELF) libagbsyscall: - @$(MAKE) -C libagbsyscall TOOLCHAIN=$(TOOLCHAIN) MODERN=$(MODERN) + @$(MAKE) -C libagbsyscall TOOLCHAIN=$(TOOLCHAIN) MODERN=1 ################### ### Symbol file ### diff --git a/README.md b/README.md index 3a87ac27f6..f09f5a7d90 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ pokeemerald-expansion is a decomp hack base project based off pret's [pokeemeral If you use pokeemerald-expansion in your hack, please add RHH (Rom Hacking Hideout) to your credits list. Optionally, you can list the version used, so it can help players know what features to expect. You can phrase it as the following: ``` -Based off RHH's pokeemerald-expansion 1.9.0 https://github.com/rh-hideout/pokeemerald-expansion/ +Based off RHH's pokeemerald-expansion 1.9.1 https://github.com/rh-hideout/pokeemerald-expansion/ ``` ## What features are included? diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 12439efc4a..9d61889b40 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1670,6 +1670,10 @@ callnative BS_DamageToQuarterTargetHP .endm + .macro ficklebeamdamagecalculation + callnative BS_FickleBeamDamageCalculation + .endm + @ various command changed to more readable macros .macro cancelmultiturnmoves battler:req various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES diff --git a/common_syms/AgbRfu_LinkManager.txt b/common_syms/AgbRfu_LinkManager.txt deleted file mode 100644 index 7ff8cd53dd..0000000000 --- a/common_syms/AgbRfu_LinkManager.txt +++ /dev/null @@ -1 +0,0 @@ -lman diff --git a/common_syms/agb_flash.txt b/common_syms/agb_flash.txt deleted file mode 100644 index cb421ec80d..0000000000 --- a/common_syms/agb_flash.txt +++ /dev/null @@ -1,10 +0,0 @@ -gFlashTimeoutFlag -PollFlashStatus -WaitForFlashWrite -ProgramFlashSector -gFlash -ProgramFlashByte -gFlashNumRemainingBytes -EraseFlashChip -EraseFlashSector -gFlashMaxTime diff --git a/common_syms/apprentice.txt b/common_syms/apprentice.txt deleted file mode 100644 index 0d3569dcbb..0000000000 --- a/common_syms/apprentice.txt +++ /dev/null @@ -1,3 +0,0 @@ -gApprenticePartyMovesData -gApprenticeQuestionData -gApprenticeFunc diff --git a/common_syms/battle_anim_throw.txt b/common_syms/battle_anim_throw.txt deleted file mode 100755 index 5e2e8b3ff3..0000000000 --- a/common_syms/battle_anim_throw.txt +++ /dev/null @@ -1,3 +0,0 @@ -gMonShrinkDuration -gMonShrinkDelta -gMonShrinkDistance diff --git a/common_syms/battle_controllers.txt b/common_syms/battle_controllers.txt deleted file mode 100644 index 0b3c25266a..0000000000 --- a/common_syms/battle_controllers.txt +++ /dev/null @@ -1,3 +0,0 @@ -gBattlerControllerFuncs -gBattleControllerData -gBattlerControllerEndFuncs diff --git a/common_syms/battle_factory_screen.txt b/common_syms/battle_factory_screen.txt deleted file mode 100644 index 3ddeb6d3b1..0000000000 --- a/common_syms/battle_factory_screen.txt +++ /dev/null @@ -1 +0,0 @@ -gFactorySelect_CurrentOptionFunc diff --git a/common_syms/battle_main.txt b/common_syms/battle_main.txt deleted file mode 100644 index 7a9faa5a13..0000000000 --- a/common_syms/battle_main.txt +++ /dev/null @@ -1,7 +0,0 @@ -gPreBattleCallback1 -gBattleMainFunc -gBattleResults -gLeveledUpInBattle -gHealthboxSpriteIds -gMultiUsePlayerCursor -gNumberOfMovesToChoose diff --git a/common_syms/battle_tower.txt b/common_syms/battle_tower.txt deleted file mode 100644 index 7371109d51..0000000000 --- a/common_syms/battle_tower.txt +++ /dev/null @@ -1 +0,0 @@ -gFrontierTempParty diff --git a/common_syms/berry_blender.txt b/common_syms/berry_blender.txt deleted file mode 100644 index 1b15a33d61..0000000000 --- a/common_syms/berry_blender.txt +++ /dev/null @@ -1 +0,0 @@ -gInGameOpponentsNo diff --git a/common_syms/bg.txt b/common_syms/bg.txt deleted file mode 100644 index 0a3c3aecca..0000000000 --- a/common_syms/bg.txt +++ /dev/null @@ -1 +0,0 @@ -gWindowTileAutoAllocEnabled diff --git a/common_syms/contest.txt b/common_syms/contest.txt deleted file mode 100644 index 6a519fb463..0000000000 --- a/common_syms/contest.txt +++ /dev/null @@ -1 +0,0 @@ -gContestRngValue diff --git a/common_syms/contest_painting.txt b/common_syms/contest_painting.txt deleted file mode 100644 index 32bb8be161..0000000000 --- a/common_syms/contest_painting.txt +++ /dev/null @@ -1,4 +0,0 @@ -gContestMonPixels -gImageProcessingContext -gContestPaintingWinner -gContestPaintingMonPalette diff --git a/common_syms/ereader_screen.txt b/common_syms/ereader_screen.txt deleted file mode 100644 index 2189eedbc9..0000000000 --- a/common_syms/ereader_screen.txt +++ /dev/null @@ -1 +0,0 @@ -gEReaderData diff --git a/common_syms/evolution_scene.txt b/common_syms/evolution_scene.txt deleted file mode 100644 index 137cd3e05d..0000000000 --- a/common_syms/evolution_scene.txt +++ /dev/null @@ -1 +0,0 @@ -gCB2_AfterEvolution diff --git a/common_syms/faraway_island.txt b/common_syms/faraway_island.txt deleted file mode 100755 index e02ca2ec25..0000000000 --- a/common_syms/faraway_island.txt +++ /dev/null @@ -1,3 +0,0 @@ -sPlayerToMewDeltaX -sPlayerToMewDeltaY -sMewDirectionCandidates diff --git a/common_syms/field_camera.txt b/common_syms/field_camera.txt deleted file mode 100644 index 02301ce23c..0000000000 --- a/common_syms/field_camera.txt +++ /dev/null @@ -1,3 +0,0 @@ -gFieldCamera -gTotalCameraPixelOffsetY -gTotalCameraPixelOffsetX diff --git a/common_syms/field_control_avatar.txt b/common_syms/field_control_avatar.txt deleted file mode 100644 index 268f60c641..0000000000 --- a/common_syms/field_control_avatar.txt +++ /dev/null @@ -1 +0,0 @@ -gSelectedObjectEvent diff --git a/common_syms/field_specials.txt b/common_syms/field_specials.txt deleted file mode 100644 index 7adb3f6692..0000000000 --- a/common_syms/field_specials.txt +++ /dev/null @@ -1 +0,0 @@ -gScrollableMultichoice_ListMenuTemplate diff --git a/common_syms/fieldmap.txt b/common_syms/fieldmap.txt deleted file mode 100644 index 0ead758462..0000000000 --- a/common_syms/fieldmap.txt +++ /dev/null @@ -1 +0,0 @@ -gBackupMapLayout diff --git a/common_syms/image_processing_effects.txt b/common_syms/image_processing_effects.txt deleted file mode 100644 index 134f7e88b2..0000000000 --- a/common_syms/image_processing_effects.txt +++ /dev/null @@ -1,10 +0,0 @@ -gCanvasColumnStart -gCanvasPixels -gCanvasRowEnd -gCanvasHeight -gCanvasColumnEnd -gCanvasRowStart -gCanvasMonPersonality -gCanvasWidth -gCanvasPalette -gCanvasPaletteStart diff --git a/common_syms/intro.txt b/common_syms/intro.txt deleted file mode 100644 index d069b1014f..0000000000 --- a/common_syms/intro.txt +++ /dev/null @@ -1,2 +0,0 @@ -gIntroFrameCounter -gMultibootProgramStruct diff --git a/common_syms/librfu_rfu.txt b/common_syms/librfu_rfu.txt deleted file mode 100644 index 4b742dcd25..0000000000 --- a/common_syms/librfu_rfu.txt +++ /dev/null @@ -1,5 +0,0 @@ -gRfuSlotStatusUNI -gRfuSlotStatusNI -gRfuLinkStatus -gRfuStatic -gRfuFixed diff --git a/common_syms/librfu_sio32id.txt b/common_syms/librfu_sio32id.txt deleted file mode 100644 index 97395e84b3..0000000000 --- a/common_syms/librfu_sio32id.txt +++ /dev/null @@ -1 +0,0 @@ -gRfuSIO32Id diff --git a/common_syms/librfu_stwi.txt b/common_syms/librfu_stwi.txt deleted file mode 100644 index a1f7735535..0000000000 --- a/common_syms/librfu_stwi.txt +++ /dev/null @@ -1 +0,0 @@ -gSTWIStatus diff --git a/common_syms/link.txt b/common_syms/link.txt deleted file mode 100644 index 4118d1eb4b..0000000000 --- a/common_syms/link.txt +++ /dev/null @@ -1,35 +0,0 @@ -gLinkPartnersHeldKeys -gLinkDebugSeed -gLocalLinkPlayerBlock -gLinkErrorOccurred -gLinkDebugFlags -gLinkFiller1 -gRemoteLinkPlayersNotReceived -gBlockReceivedStatus -gLinkFiller2 -gLinkHeldKeys -gRecvCmds -gLinkStatus -gLinkDummy1 -gLinkDummy2 -gReadyToExitStandby -gReadyToCloseLink -gReadyCloseLinkType -gSuppressLinkErrorMessage -gWirelessCommType -gSavedLinkPlayerCount -gSendCmd -gSavedMultiplayerId -gReceivedRemoteLinkPlayers -gLinkTestBGInfo -gLinkCallback -gShouldAdvanceLinkState -gLinkTestBlockChecksums -gBlockRequestType -gLinkFiller3 -gLinkFiller4 -gLinkFiller5 -gLastSendQueueCount -gLink -gLastRecvQueueCount -gLinkSavedIme diff --git a/common_syms/link_rfu_2.txt b/common_syms/link_rfu_2.txt deleted file mode 100644 index 4b8f02bad8..0000000000 --- a/common_syms/link_rfu_2.txt +++ /dev/null @@ -1,2 +0,0 @@ -gRfuAPIBuffer -gRfu diff --git a/common_syms/list_menu.txt b/common_syms/list_menu.txt deleted file mode 100644 index ed5343618c..0000000000 --- a/common_syms/list_menu.txt +++ /dev/null @@ -1,2 +0,0 @@ -gListMenuOverride -gMultiuseListMenuTemplate diff --git a/common_syms/load_save.txt b/common_syms/load_save.txt deleted file mode 100644 index 2d3d9b802f..0000000000 --- a/common_syms/load_save.txt +++ /dev/null @@ -1,4 +0,0 @@ -gFlashMemoryPresent -gSaveBlock1Ptr -gSaveBlock2Ptr -gPokemonStoragePtr diff --git a/common_syms/m4a.txt b/common_syms/m4a.txt deleted file mode 100644 index 0d6b13a79b..0000000000 --- a/common_syms/m4a.txt +++ /dev/null @@ -1,12 +0,0 @@ -gSoundInfo -gPokemonCrySongs -gPokemonCryMusicPlayers -gMPlayInfo_BGM -gMPlayJumpTable -gCgbChans -gMPlayInfo_SE1 -gMPlayInfo_SE2 -gPokemonCryTracks -gPokemonCrySong -gMPlayMemAccArea -gMPlayInfo_SE3 diff --git a/common_syms/main.txt b/common_syms/main.txt deleted file mode 100644 index f1f8076adf..0000000000 --- a/common_syms/main.txt +++ /dev/null @@ -1,10 +0,0 @@ -gKeyRepeatStartDelay -gLinkTransferringData -gMain -gKeyRepeatContinueDelay -gSoftResetDisabled -gIntrTable -gLinkVSyncDisabled -IntrMain_Buffer -gPcmDmaCounter -gAgbMainLoop_sp diff --git a/common_syms/mauville_old_man.txt b/common_syms/mauville_old_man.txt deleted file mode 100644 index 9d77b8692b..0000000000 --- a/common_syms/mauville_old_man.txt +++ /dev/null @@ -1 +0,0 @@ -gBardSong diff --git a/common_syms/overworld.txt b/common_syms/overworld.txt deleted file mode 100644 index dcada0bbef..0000000000 --- a/common_syms/overworld.txt +++ /dev/null @@ -1,8 +0,0 @@ -gOverworldTilemapBuffer_Bg2 -gOverworldTilemapBuffer_Bg1 -gOverworldTilemapBuffer_Bg3 -gHeldKeyCodeToSend -gFieldCallback -gFieldCallback2 -gLocalLinkPlayerId -gFieldLinkPlayerCount diff --git a/common_syms/party_menu.txt b/common_syms/party_menu.txt deleted file mode 100644 index 6ed37392c2..0000000000 --- a/common_syms/party_menu.txt +++ /dev/null @@ -1 +0,0 @@ -gItemUseCB diff --git a/common_syms/pokedex.txt b/common_syms/pokedex.txt deleted file mode 100644 index c7a297b2af..0000000000 --- a/common_syms/pokedex.txt +++ /dev/null @@ -1,2 +0,0 @@ -gUnusedPokedexU8 -gPokedexVBlankCB diff --git a/common_syms/pokedex_cry_screen.txt b/common_syms/pokedex_cry_screen.txt deleted file mode 100644 index d16ec36d64..0000000000 --- a/common_syms/pokedex_cry_screen.txt +++ /dev/null @@ -1 +0,0 @@ -gDexCryScreenState diff --git a/common_syms/random.txt b/common_syms/random.txt deleted file mode 100644 index 8037c69586..0000000000 --- a/common_syms/random.txt +++ /dev/null @@ -1,2 +0,0 @@ -gRngValue -gRng2Value diff --git a/common_syms/rtc.txt b/common_syms/rtc.txt deleted file mode 100644 index fa00a34d51..0000000000 --- a/common_syms/rtc.txt +++ /dev/null @@ -1 +0,0 @@ -gLocalTime diff --git a/common_syms/save.txt b/common_syms/save.txt deleted file mode 100644 index 131031d506..0000000000 --- a/common_syms/save.txt +++ /dev/null @@ -1,13 +0,0 @@ -gLastWrittenSector -gLastSaveCounter -gLastKnownGoodSector -gDamagedSaveSectors -gSaveCounter -gReadWriteSector -gIncrementalSectorId -gSaveUnusedVar -gSaveFileStatus -gGameContinueCallback -gRamSaveSectorLocations -gSaveUnusedVar2 -gSaveAttemptStatus diff --git a/common_syms/sound.txt b/common_syms/sound.txt deleted file mode 100644 index 0f6f2fc758..0000000000 --- a/common_syms/sound.txt +++ /dev/null @@ -1 +0,0 @@ -gDisableMusic diff --git a/common_syms/sprite.txt b/common_syms/sprite.txt deleted file mode 100644 index 627c01c0d0..0000000000 --- a/common_syms/sprite.txt +++ /dev/null @@ -1,2 +0,0 @@ -gOamMatrixAllocBitmap -gReservedSpritePaletteCount diff --git a/common_syms/start_menu.txt b/common_syms/start_menu.txt deleted file mode 100644 index 05beaf57c2..0000000000 --- a/common_syms/start_menu.txt +++ /dev/null @@ -1 +0,0 @@ -gMenuCallback diff --git a/common_syms/task.txt b/common_syms/task.txt deleted file mode 100644 index 6601bd11bb..0000000000 --- a/common_syms/task.txt +++ /dev/null @@ -1 +0,0 @@ -gTasks diff --git a/common_syms/text.txt b/common_syms/text.txt deleted file mode 100644 index cd8886e5b1..0000000000 --- a/common_syms/text.txt +++ /dev/null @@ -1,4 +0,0 @@ -gFonts -gDisableTextPrinters -gCurGlyph -gTextFlags diff --git a/common_syms/trainer_see.txt b/common_syms/trainer_see.txt deleted file mode 100644 index 0b30a632a0..0000000000 --- a/common_syms/trainer_see.txt +++ /dev/null @@ -1,5 +0,0 @@ -gWhichTrainerToFaceAfterBattle -gPostBattleMovementScript -gApproachingTrainers -gNoOfApproachingTrainers -gTrainerApproachedPlayer diff --git a/common_syms/tv.txt b/common_syms/tv.txt deleted file mode 100644 index 0370f65e1f..0000000000 --- a/common_syms/tv.txt +++ /dev/null @@ -1,4 +0,0 @@ -sCurTVShowSlot -sTV_SecretBaseVisitMovesTemp -sTV_DecorationsBuffer -sTV_SecretBaseVisitMonsTemp diff --git a/common_syms/window.txt b/common_syms/window.txt deleted file mode 100644 index 24c093a226..0000000000 --- a/common_syms/window.txt +++ /dev/null @@ -1,2 +0,0 @@ -gTransparentTileNumber -gWindowBgTilemapBuffers diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index f842b8c113..fdc7a59e4e 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -16219,6 +16219,12 @@ Move_RAGING_BULL:: loadspritegfx ANIM_TAG_IMPACT loadspritegfx ANIM_TAG_ANGER loadspritegfx ANIM_TAG_BREATH + loadspritegfx ANIM_TAG_BLUE_LIGHT_WALL + loadspritegfx ANIM_TAG_TORN_METAL + choosetwoturnanim RagingBullNormal, RagingBullShatteredWall +RagingBullNormal: + monbg ANIM_TARGET + setalpha 12, 8 createsprite gBreathPuffSpriteTemplate, ANIM_ATTACKER, 2 loopsewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER, 4, 2 createsprite gAngerMarkSpriteTemplate, ANIM_ATTACKER, 2, 0, -20, -28 @@ -16250,6 +16256,49 @@ Move_RAGING_BULL:: waitforvisualfinish restorebg waitbgfadein + clearmonbg ANIM_TARGET + end +RagingBullShatteredWall: + monbg ANIM_TARGET + setalpha 12, 8 + createsprite gBreathPuffSpriteTemplate, ANIM_ATTACKER, 2 + loopsewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER, 4, 2 + createsprite gAngerMarkSpriteTemplate, ANIM_ATTACKER, 2, 0, -20, -28 + delay 20 + createsprite gAngerMarkSpriteTemplate, ANIM_ATTACKER, 2, 0, 20, -28 + waitforvisualfinish + createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 2, ANIM_ATTACKER, 18, 6, 2, 4 + waitforvisualfinish + playsewithpan SE_M_SWIFT, SOUND_PAN_ATTACKER + call SetImpactBackground + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 0, 20, 0, 0, 4 + delay 3 + waitforvisualfinish + createsprite gBrickBreakWallSpriteTemplate, ANIM_ATTACKER, 3, ANIM_TARGET, 0, 0, 90, 10 + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 4, -10, 0, ANIM_TARGET, 0 + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 1, -32, 0, 0, 3 + delay 20 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 0 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_ATTACKER, 4, 0, 12, 1 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + delay 20 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 1 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 1 + waitforvisualfinish + createsprite gBrickBreakWallShardSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 0, -8, -12 + createsprite gBrickBreakWallShardSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 1, 8, -12 + createsprite gBrickBreakWallShardSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 2, -8, 12 + createsprite gBrickBreakWallShardSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 3, 8, 12 + playsewithpan SE_M_BRICK_BREAK, SOUND_PAN_TARGET + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 5 + delay 3 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 1, 0, 7 + waitforvisualfinish + restorebg + waitbgfadein + clearmonbg ANIM_TARGET end @ Credits to Z-nogyroP. Simple anim that combines Force Palm + Fake Out @@ -17013,44 +17062,618 @@ Move_AXE_KICK:: createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 1, 4 end +Move_SPIN_OUT:: + loadspritegfx ANIM_TAG_IMPACT + loadspritegfx ANIM_TAG_RAPID_SPIN + loopsewithpan SE_M_HARDEN, SOUND_PAN_ATTACKER, 28, 2 + createvisualtask AnimTask_MetallicShine, 5, 0, 0, RGB_BLACK + waitforvisualfinish + call SetHighSpeedBg + loopsewithpan SE_M_RAZOR_WIND2, SOUND_PAN_ATTACKER, 8, 3 + waitforvisualfinish + monbg ANIM_ATTACKER + createsprite gRapidSpinSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 32, -32, 40, -2 + createvisualtask AnimTask_RapinSpinMonElevation, 2, 0, 2, 0 + loopsewithpan SE_M_RAZOR_WIND2, SOUND_PAN_ATTACKER, 8, 4 + waitforvisualfinish + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, 0, 0, ANIM_TARGET, 2 + createvisualtask AnimTask_ShakeTargetBasedOnMovePowerOrDmg, 2, FALSE, 1, 10, 1, 0 + playsewithpan SE_M_DOUBLE_SLAP, SOUND_PAN_TARGET + waitforvisualfinish + delay 8 + createvisualtask AnimTask_RapinSpinMonElevation, 2, 0, 2, 1 + loopsewithpan SE_M_RAZOR_WIND2, SOUND_PAN_ATTACKER, 8, 4 + waitforvisualfinish + call UnsetHighSpeedBg + clearmonbg ANIM_ATTACKER + end + +Move_MORTAL_SPIN:: + loadspritegfx ANIM_TAG_IMPACT + loadspritegfx ANIM_TAG_RAPID_SPIN + loadspritegfx ANIM_TAG_POISON_BUBBLE + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_RAPID_SPIN, 0, 6, 6, RGB(15, 0, 15) + monbg ANIM_ATTACKER + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_ATTACKER, 1, 0, 13, RGB(10, 2, 19) + delay 16 + createsprite gRapidSpinSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 32, -32, 40, -2 + createvisualtask AnimTask_RapinSpinMonElevation, 2, 0, 2, 0 + loopsewithpan SE_M_RAZOR_WIND2, SOUND_PAN_ATTACKER, 8, 4 + waitforvisualfinish + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, 0, 0, ANIM_TARGET, 2 + createvisualtask AnimTask_ShakeTargetBasedOnMovePowerOrDmg, 2, FALSE, 1, 10, 1, 0 + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_ATTACKER, 1, 13, 0, RGB(10, 2, 19) + call PoisonBubblesEffect + waitforvisualfinish + delay 8 + createvisualtask AnimTask_RapinSpinMonElevation, 2, 0, 2, 1 + loopsewithpan SE_M_RAZOR_WIND2, SOUND_PAN_ATTACKER, 8, 4 + waitforvisualfinish + clearmonbg ANIM_ATTACKER + blendoff + end + +Move_FILLET_AWAY:: + loadspritegfx ANIM_TAG_CUT + createsprite gCuttingSliceSpriteTemplate, ANIM_ATTACKER, 2, 40, -32, 0 + playsewithpan SE_M_CUT, SOUND_PAN_ATTACKER + delay 5 + createsprite gCuttingSliceSpriteTemplate, ANIM_ATTACKER, 2, 20, -27, 0 + playsewithpan SE_M_CUT, SOUND_PAN_ATTACKER + delay 5 + createsprite gCuttingSliceSpriteTemplate, ANIM_ATTACKER, 2, 60, -37, 0 + playsewithpan SE_M_CUT, SOUND_PAN_ATTACKER + waitforvisualfinish + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_ATTACKER, 2, 0, 9, 0x7FFF + waitforvisualfinish + createvisualtask AnimTask_ShakeMon, 2, ANIM_ATTACKER, 0, 2, 4, 4 + waitforvisualfinish + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_ATTACKER, 2, 9, 0, 0x7FFF + waitforvisualfinish + blendoff + end + +Move_FLOWER_TRICK:: + loadspritegfx ANIM_TAG_SPOTLIGHT + loadspritegfx ANIM_TAG_LEAF @leaves + loadspritegfx ANIM_TAG_FLOWER @flowers + loadspritegfx ANIM_TAG_IMPACT + createvisualtask AnimTask_CreateSpotlight, 2 + createvisualtask AnimTask_HardwarePaletteFade, 2, (BLDCNT_TGT1_BG3 | BLDCNT_TGT1_OBJ | BLDCNT_TGT1_BD | BLDCNT_EFFECT_DARKEN), 3, 0, 10, FALSE + waitforvisualfinish + createsprite gSpotlightSpriteTemplate, ANIM_TARGET, 2, 0, -8 + delay 16 + createvisualtask SoundTask_PlaySE2WithPanning, 5, SE_M_ENCORE2, SOUND_PAN_TARGET + createvisualtask AnimTask_SwayMon, 5, 1, 8, 1536, 5, ANIM_TARGET + waitforvisualfinish + playsewithpan SE_M_DOUBLE_SLAP, SOUND_PAN_TARGET + createsprite gTropKickLeavesTemplate, ANIM_TARGET, 1, 0, 10, 192, 176, 40 + createsprite gTropKickLeavesTemplate, ANIM_TARGET, 1, 0, 10, -192, 240, 40 + createsprite gTropKickFlowerTemplate, ANIM_TARGET, 1, 0, 10, 192, -160, 40 + createsprite gTropKickFlowerTemplate, ANIM_TARGET, 1, 0, 10, -192, -112, 40 + createsprite gTropKickFlowerTemplate, ANIM_TARGET, 1, 0, 10, 160, 48, 40 + createsprite gTropKickLeavesTemplate, ANIM_TARGET, 1, 0, 10, -224, -32, 40 + createsprite gTropKickLeavesTemplate, ANIM_TARGET, 1, 0, 10, 112, -128, 40 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, ANIM_TARGET, 2 + waitforvisualfinish + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 + waitforvisualfinish + createvisualtask AnimTask_HardwarePaletteFade, 2, (BLDCNT_TGT1_BG3 | BLDCNT_TGT1_OBJ | BLDCNT_TGT1_BD | BLDCNT_EFFECT_DARKEN), 3, 10, 0, TRUE + createvisualtask AnimTask_RemoveSpotlight, 2 + end + +Move_MAKE_IT_RAIN:: + loadspritegfx ANIM_TAG_COIN + loadspritegfx ANIM_TAG_IMPACT + monbg ANIM_ATTACKER + setalpha 12, 8 + playsewithpan SE_M_RAZOR_WIND2, SOUND_PAN_ATTACKER + createsprite gCoinThrowSpriteTemplate, ANIM_ATTACKER, 2, 20, 0, 0, 0, 1152 + waitforvisualfinish + playsewithpan SE_M_PAY_DAY, SOUND_PAN_TARGET + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 1, 0, 0, ANIM_TARGET, 2 + createsprite gFallingCoinSpriteTemplate, ANIM_ATTACKER, 2 + createvisualtask AnimTask_ShakeMon2, 2, ANIM_TARGET, 1, 0, 6, 1 + waitforvisualfinish + delay 20 + createvisualtask AnimTask_IsTargetPlayerSide, 2 + jumpretfalse MakingItRainOnOpponent + jumprettrue MakingItRainOnPlayer +MakingItRainContinue: + waitbgfadeout + createsprite gShakeMonOrTerrainSpriteTemplate, ANIM_ATTACKER, 2, 7, 1, 11, 1 + loopsewithpan SE_M_PAY_DAY, SOUND_PAN_TARGET, 8, 15 + createsprite gMakingItRainTemplate, ANIM_TARGET, 2, -5, 0, -5, 1 + delay 2 + createsprite gMakingItRainTemplate, ANIM_TARGET, 2, 5, 0, 6, 1 + delay 2 + createsprite gMakingItRainTemplate, ANIM_TARGET, 2, 19, 0, 10, 1 + delay 2 + createsprite gMakingItRainTemplate, ANIM_TARGET, 2, -23, 0, -10, 1 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 5, 50, 1 + createvisualtask AnimTask_ShakeMon, 2, ANIM_DEF_PARTNER, 0, 5, 50, 1 + call MakingItRain + call MakingItRain + call MakingItRain + restorebg + waitbgfadein + blendoff + waitforvisualfinish + clearmonbg ANIM_ATTACKER + end +MakingItRainOnOpponent: + fadetobg BG_IMPACT_OPPONENT + goto MakingItRainContinue +MakingItRainOnPlayer: + fadetobg BG_IMPACT_PLAYER + goto MakingItRainContinue +MakingItRain: + createsprite gMakingItRainTemplate, ANIM_TARGET, 2, -20, 0, -10, 1 + delay 2 + createsprite gMakingItRainTemplate, ANIM_TARGET, 2, 28, 0, 10, 1 + delay 2 + createsprite gMakingItRainTemplate, ANIM_TARGET, 2, -10, 0, -5, 1 + delay 2 + createsprite gMakingItRainTemplate, ANIM_TARGET, 2, 10, 0, 6, 1 + delay 2 + createsprite gMakingItRainTemplate, ANIM_TARGET, 2, 24, 0, 10, 1 + delay 2 + createsprite gMakingItRainTemplate, ANIM_TARGET, 2, -32, 0, -10, 1 + delay 2 + createsprite gMakingItRainTemplate, ANIM_TARGET, 2, -20, 0, -10, 1 + delay 2 + createsprite gMakingItRainTemplate, ANIM_TARGET, 2, 30, 0, 10, 1 + delay 2 + return + +Move_SHED_TAIL:: + loopsewithpan SE_M_TAIL_WHIP, SOUND_PAN_ATTACKER, 24, 3 + createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 2, ANIM_ATTACKER, 12, 4, 2, 3 + waitforvisualfinish + playsewithpan SE_M_ATTRACT, SOUND_PAN_ATTACKER + createvisualtask AnimTask_MonToSubstitute, 2 + end + +Move_HYPER_DRILL:: + loadspritegfx ANIM_TAG_IMPACT + loadspritegfx ANIM_TAG_HORN_HIT + fadetobgfromset BG_GUILLOTINE_OPPONENT, BG_GUILLOTINE_PLAYER, BG_GUILLOTINE_CONTESTS + waitbgfadein + createsprite gBowMonSpriteTemplate, ANIM_ATTACKER, 2, 0 + playsewithpan SE_M_HEADBUTT, SOUND_PAN_ATTACKER + waitforvisualfinish + delay 2 + createsprite gBowMonSpriteTemplate, ANIM_ATTACKER, 2, 1 + createsprite gHornHitSpriteTemplate, ANIM_TARGET, 4, 0, 0, 12 + waitforvisualfinish + playse 20 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_ATTACKER, 2, 0, 40, 1 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 10, 0, 40, 1 + createsprite gFlashingHitSplatSpriteTemplate, ANIM_TARGET, 3, 0, 0, 1, 3 + playsewithpan SE_M_HORN_ATTACK, SOUND_PAN_TARGET + delay 4 + createsprite gFlashingHitSplatSpriteTemplate, ANIM_TARGET, 3, 0, 2, 1, 3 + playsewithpan SE_M_HORN_ATTACK, SOUND_PAN_TARGET + delay 4 + createsprite gFlashingHitSplatSpriteTemplate, ANIM_TARGET, 3, -4, 3, 1, 3 + playsewithpan SE_M_HORN_ATTACK, SOUND_PAN_TARGET + delay 4 + createsprite gFlashingHitSplatSpriteTemplate, ANIM_TARGET, 3, -8, -5, 1, 3 + playsewithpan SE_M_HORN_ATTACK, SOUND_PAN_TARGET + delay 4 + createsprite gFlashingHitSplatSpriteTemplate, ANIM_TARGET, 3, 4, -12, 1, 3 + playsewithpan SE_M_HORN_ATTACK, SOUND_PAN_TARGET + delay 4 + createsprite gFlashingHitSplatSpriteTemplate, ANIM_TARGET, 3, 16, 0, 1, 3 + playsewithpan SE_M_HORN_ATTACK, SOUND_PAN_TARGET + delay 4 + createsprite gFlashingHitSplatSpriteTemplate, ANIM_TARGET, 3, 5, 18, 1, 3 + playsewithpan SE_M_HORN_ATTACK, SOUND_PAN_TARGET + delay 4 + createsprite gFlashingHitSplatSpriteTemplate, ANIM_TARGET, 3, -17, 12, 1, 2 + playsewithpan SE_M_HORN_ATTACK, SOUND_PAN_TARGET + delay 4 + createsprite gFlashingHitSplatSpriteTemplate, ANIM_TARGET, 3, -21, -15, 1, 2 + playsewithpan SE_M_HORN_ATTACK, SOUND_PAN_TARGET + delay 4 + createsprite gFlashingHitSplatSpriteTemplate, ANIM_TARGET, 3, 8, -27, 1, 2 + playsewithpan SE_M_HORN_ATTACK, SOUND_PAN_TARGET + delay 4 + createsprite gFlashingHitSplatSpriteTemplate, ANIM_TARGET, 3, 32, 0, 1, 2 + playsewithpan SE_M_HORN_ATTACK, SOUND_PAN_TARGET + delay 4 + createsprite gBowMonSpriteTemplate, ANIM_ATTACKER, 2, 2 + createsprite gComplexPaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG | F_PAL_BATTLERS, 3, 1, RGB_BLACK, 8, RGB_BLACK, 0 + playsewithpan SE_M_RAZOR_WIND, SOUND_PAN_TARGET + waitforvisualfinish + createsprite gComplexPaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG | F_PAL_BATTLERS, 3, 1, RGB_BLACK, 8, RGB_BLACK, 0 + restorebg + waitbgfadein + blendoff + end + +Move_TWIN_BEAM:: + loadspritegfx ANIM_TAG_BLUE_RING + loadspritegfx ANIM_TAG_GOLD_RING + playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER + call SetPsychicBackground + createvisualtask AnimTask_StartSinAnimTimer, 5, 100 + createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_TELEPORT, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 2, 9, 0, 10 + call PsywaveRings + call PsybeamRings + call PsywaveRings + call PsybeamRings + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 1, 4, 0, 12, RGB(31, 18, 31) + call PsywaveRings + call PsybeamRings + call PsywaveRings + call PsybeamRings + call PsywaveRings + call PsybeamRings + call PsywaveRings + call PsybeamRings + waitforvisualfinish + delay 1 + call UnsetPsychicBg + end + +Move_COMEUPPANCE:: + loadspritegfx ANIM_TAG_IMPACT + monbg ANIM_TARGET + fadetobg BG_DARK + waitbgfadein + delay 0 + playsewithpan SE_M_DRAGON_RAGE, SOUND_PAN_ATTACKER + createvisualtask AnimTask_ShakeMon2, 5, ANIM_ATTACKER, 1, 0, 15, 1 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_ATTACKER, 3, 0, 9, RGB_RED + waitforvisualfinish + delay 10 + createvisualtask AnimTask_SwayMon, 5, 0, 16, 6144, 8, ANIM_ATTACKER + delay 5 + setalpha 12, 8 + createvisualtask AnimTask_ShakeMon2, 5, ANIM_TARGET, 4, 0, 30, 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 1, 0 + playsewithpan SE_M_COMET_PUNCH, +63 + delay 5 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 3, 24, 8, 1, 0 + playsewithpan SE_M_COMET_PUNCH, +63 + delay 5 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 3, -24, -16, 1, 0 + playsewithpan SE_M_COMET_PUNCH, +63 + delay 5 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 3, 8, 4, 1, 0 + playsewithpan SE_M_COMET_PUNCH, +63 + delay 5 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 3, -16, 19, 1, 0 + playsewithpan SE_M_COMET_PUNCH, +63 + delay 5 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 3, 18, -18, 1, 0 + playsewithpan SE_M_COMET_PUNCH, +63 + waitforvisualfinish + clearmonbg ANIM_TARGET + blendoff + restorebg + waitbgfadein + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_ATTACKER, 3, 9, 0, RGB_RED + waitforvisualfinish + clearmonbg ANIM_DEF_PARTNER + end + +Move_BLOOD_MOON:: + loadspritegfx ANIM_TAG_BLOOD_MOON + loadspritegfx ANIM_TAG_BEAM + loadspritegfx ANIM_TAG_RED_EXPLOSION + createvisualtask AnimTask_BlendBattleAnimPal, 5, F_PAL_BG, 0, 16, 16, RGB_BLACK + createsprite gVerticalDipSpriteTemplate, ANIM_ATTACKER, 2, 8, 1, ANIM_ATTACKER + delay 8 + playsewithpan SE_M_BARRIER, SOUND_PAN_ATTACKER + createsprite gMoonUpSpriteTemplate, ANIM_ATTACKER, 2 + waitforvisualfinish + delay 15 + playsewithpan SE_M_DETECT, 0 + waitforvisualfinish + createvisualtask AnimTask_IsTargetPlayerSide, 2 + jumpargeq 7 ANIM_TARGET BloodMoonOnPlayer +BloodMoonOnOpponent: + createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_HYPER_BEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 1, 10, 0, 5 + call BloodMoonOnslaughtOpponent + call BloodMoonOnslaughtOpponent + call BloodMoonOnslaughtOpponent + call BloodMoonOnslaughtOpponent + call BloodMoonOnslaughtOpponent + createsprite gBloodMoonOnslaughtSpriteTemplate, ANIM_TARGET, 2, 140, -16, 165, 40, 4 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + createsprite gRedExplosionSpriteTemplate, ANIM_TARGET, 4, 6, 5, 1, 0 + delay 0 + waitforvisualfinish + goto BloodMoonFinish +BloodMoonOnPlayer: + createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_HYPER_BEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 1, 10, 0, 5 + call BloodMoonOnslaughtPlayer + call BloodMoonOnslaughtPlayer + call BloodMoonOnslaughtPlayer + call BloodMoonOnslaughtPlayer + call BloodMoonOnslaughtPlayer + createsprite gBloodMoonOnslaughtSpriteTemplate, ANIM_TARGET, 2, 40, -16, 75, 80, 4 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + delay 0 + waitforvisualfinish +BloodMoonFinish: + createvisualtask AnimTask_BlendBattleAnimPal, 5, F_PAL_BG, 0, 0, 0, RGB_BLACK + waitforvisualfinish + clearmonbg ANIM_ATTACKER + end +BloodMoonOnslaughtOpponent: + createsprite gBloodMoonOnslaughtSpriteTemplate, ANIM_TARGET, 2, 140, -16, 165, 40, 4 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + createsprite gRedExplosionSpriteTemplate, ANIM_TARGET, 4, 6, 5, 1, 0 + delay 0 + createsprite gBloodMoonOnslaughtSpriteTemplate, ANIM_TARGET, 2, 140, -16, 165, 40, 4 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + createsprite gRedExplosionSpriteTemplate, ANIM_TARGET, 4, -16, -15, 1, 0 + delay 0 + createsprite gBloodMoonOnslaughtSpriteTemplate, ANIM_TARGET, 2, 140, -16, 165, 40, 4 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + createsprite gRedExplosionSpriteTemplate, ANIM_TARGET, 4, 16, -5, 1, 0 + delay 0 + createsprite gBloodMoonOnslaughtSpriteTemplate, ANIM_TARGET, 2, 140, -16, 165, 40, 4 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + createsprite gRedExplosionSpriteTemplate, ANIM_TARGET, 4, -12, 18, 1, 0 + delay 0 + createsprite gBloodMoonOnslaughtSpriteTemplate, ANIM_TARGET, 2, 140, -16, 165, 40, 4 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + createsprite gRedExplosionSpriteTemplate, ANIM_TARGET, 4, 0, 5, 1, 0 + delay 0 + return +BloodMoonOnslaughtPlayer: + createsprite gBloodMoonOnslaughtSpriteTemplate, ANIM_TARGET, 2, 40, -16, 75, 80, 4 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + createsprite gRedExplosionSpriteTemplate, ANIM_TARGET, 4, 6, 5, 1, 0 + delay 0 + createsprite gBloodMoonOnslaughtSpriteTemplate, ANIM_TARGET, 2, 40, -16, 75, 80, 4 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + createsprite gRedExplosionSpriteTemplate, ANIM_TARGET, 4, -16, -15, 1, 0 + delay 0 + createsprite gBloodMoonOnslaughtSpriteTemplate, ANIM_TARGET, 2, 40, -16, 75, 80, 4 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + createsprite gRedExplosionSpriteTemplate, ANIM_TARGET, 4, 16, -5, 1, 0 + delay 0 + createsprite gBloodMoonOnslaughtSpriteTemplate, ANIM_TARGET, 2, 40, -16, 75, 80, 4 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + createsprite gRedExplosionSpriteTemplate, ANIM_TARGET, 4, -12, 18, 1, 0 + delay 0 + createsprite gBloodMoonOnslaughtSpriteTemplate, ANIM_TARGET, 2, 40, -16, 75, 80, 4 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + createsprite gRedExplosionSpriteTemplate, ANIM_TARGET, 4, 0, 5, 1, 0 + delay 0 + return + +Move_FICKLE_BEAM:: + createvisualtask AnimTask_IsPowerOver99, 2 + waitforvisualfinish + jumpreteq FALSE, FickleBeamRegular + jumpreteq TRUE, FickleBeamIntense +FickleBeamRegular: + loadspritegfx ANIM_TAG_GOLD_RING + playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER + createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_PSYBEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 3, 4, 0, 15 + call PsybeamRings + call PsybeamRings + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 4, 25, 1 + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 2, 2, 0, 12, RGB(15, 8, 30) + call PsybeamRings + call PsybeamRings + call PsybeamRings + call PsybeamRings + call PsybeamRings + call PsybeamRings + call PsybeamRings + call PsybeamRings + call PsybeamRings + waitforvisualfinish + end +FickleBeamIntense: + loadspritegfx ANIM_TAG_ORBS + fadetobgfromset BG_SPACIAL_REND_ON_OPPONENT BG_SPACIAL_REND_ON_PLAYER BG_SPACIAL_REND_ON_OPPONENT + waitbgfadein + delay 10 + playsewithpan SE_M_HYPER_BEAM, SOUND_PAN_ATTACKER + createvisualtask AnimTask_ShakeMon2, 2, ANIM_ATTACKER, 1, 0, 4, 1 + waitforvisualfinish + delay 30 + createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_HYPER_BEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 1, 15, 0, 5 + createvisualtask AnimTask_ShakeMon, 2, ANIM_ATTACKER, 0, 4, 50, 1 + createvisualtask AnimTask_FlashAnimTagWithColor, 2, ANIM_TAG_ORBS, 1, 12, RGB_RED, 16, 0, 0 + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + createvisualtask AnimTask_ShakeMon2, 2, ANIM_TARGET, 4, 0, 50, 1 + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + waitforvisualfinish + restorebg + waitbgfadein + end + +Move_THUNDERCLAP:: + loadspritegfx ANIM_TAG_LIGHTNING + monbg ANIM_ATK_PARTNER + setalpha 12, 8 + createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 2, ANIM_ATTACKER, 24, 6, 1, 5 + createvisualtask AnimTask_TraceMonBlended, 2, 0, 4, 7, 3 + playsewithpan SE_M_JUMP_KICK, SOUND_PAN_ATTACKER + delay 4 + playsewithpan SE_M_THUNDER_WAVE, SOUND_PAN_TARGET + delay 1 + createsprite gLightningSpriteTemplate, ANIM_TARGET, 2, 0, -32 + playsewithpan SE_M_TRI_ATTACK2, SOUND_PAN_TARGET + delay 1 + createsprite gLightningSpriteTemplate, ANIM_TARGET, 2, 0, -16 + delay 1 + createsprite gLightningSpriteTemplate, ANIM_TARGET, 2, 0, 0 + delay 1 + createsprite gLightningSpriteTemplate, ANIM_TARGET, 2, 0, 16 + delay 10 + createvisualtask AnimTask_ShakeTargetInPattern, 2, 30, 3, TRUE, 0 + delay 2 + createvisualtask AnimTask_BlendBattleAnimPal, 5, F_PAL_BG, 3, 16, 0, RGB_WHITE + createvisualtask AnimTask_BlendBattleAnimPal, 5, F_PAL_TARGET, 0, 16, 16, RGB_BLACK + delay 4 + createvisualtask AnimTask_BlendBattleAnimPal, 5, F_PAL_TARGET, 0, 0, 0, RGB_BLACK + waitforvisualfinish + clearmonbg ANIM_ATK_PARTNER + blendoff + waitforvisualfinish + end + +Move_HARD_PRESS:: + loadspritegfx ANIM_TAG_EXPLOSION + loadspritegfx ANIM_TAG_ACUPRESSURE + loadspritegfx ANIM_TAG_PURPLE_HAND_OUTLINE + setalpha 15, 0 + call SetSteelBeamBackground + createvisualtask AnimTask_CompressTargetHorizontallyFast, 2 + createsprite gCrushGripExplosionTemplate, ANIM_TARGET, 0, 0, 0, 1, 1 + delay 3 + playsewithpan SE_M_EXPLOSION, SOUND_PAN_ATTACKER + createsprite gCrushGripExplosionTemplate, ANIM_TARGET, 0, 24, -24, 1, 1 + delay 3 + playsewithpan SE_M_EXPLOSION, SOUND_PAN_ATTACKER + createsprite gCrushGripExplosionTemplate, ANIM_TARGET, 0, -16, 16, 1, 1 + delay 3 + playsewithpan SE_M_EXPLOSION, SOUND_PAN_ATTACKER + createsprite gCrushGripExplosionTemplate, ANIM_TARGET, 0, -24, -12, 1, 1 + delay 3 + playsewithpan SE_M_EXPLOSION, SOUND_PAN_ATTACKER + createsprite gCrushGripExplosionTemplate, ANIM_TARGET, 0, 16, 16, 1, 1 + waitforvisualfinish + blendoff + call UnsetHighSpeedBg + end + +Move_DRAGON_CHEER:: + loadspritegfx ANIM_TAG_NOISE_LINE + loadspritegfx ANIM_TAG_CONFETTI + loadspritegfx ANIM_TAG_PINK_CLOUD + createvisualtask AnimTask_DeepInhale, 2, ANIM_ATTACKER + delay 12 + call RoarEffect + createvisualtask SoundTask_PlayCryHighPitch, 2, ANIM_ATTACKER, 3 + waitforvisualfinish + monbg ANIM_ATTACKER + playsewithpan SE_BALL_OPEN, SOUND_PAN_TARGET + createsprite gSmokeBallEscapeCloudSpriteTemplate, ANIM_ATTACKER, 122, 3, -14, 18, 24 + createsprite gSmokeBallEscapeCloudSpriteTemplate, ANIM_ATTACKER, 121, 3, 14, 6, 24 + createsprite gSmokeBallEscapeCloudSpriteTemplate, ANIM_ATTACKER, 120, 3, -12, 12, 24 + createsprite gSmokeBallEscapeCloudSpriteTemplate, ANIM_ATTACKER, 119, 3, 14, 18, 24 + createsprite gSmokeBallEscapeCloudSpriteTemplate, ANIM_ATTACKER, 118, 3, 0, 0, 24 + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + call CreateFlatterConfetti + waitforvisualfinish + clearmonbg ANIM_ATTACKER + delay 10 + end + +Move_MALIGNANT_CHAIN:: + loadspritegfx ANIM_TAG_PURPLE_CHAIN + loadspritegfx ANIM_TAG_POISON_BUBBLE + loopsewithpan SE_M_SCRATCH, SOUND_PAN_TARGET, 6, 2 + createsprite gChainBindingSpriteTemplate, ANIM_TARGET, 4, 0, 16, 0, 1 + delay 7 + createsprite gChainBindingSpriteTemplate, ANIM_TARGET, 2, 0, 8, 1, 1 + delay 3 + createvisualtask AnimTask_ShakeMon2, 2, ANIM_TARGET, 2, 0, 8, 1 + delay 20 + setarg 7, -1 + playsewithpan SE_M_BIND, SOUND_PAN_TARGET + waitforvisualfinish + call PoisonBubblesEffect + waitforvisualfinish + end + +Move_POPULATION_BOMB:: + loadspritegfx ANIM_TAG_CUT + monbg ANIM_TARGET + setalpha 12, 8 + playsewithpan SE_M_CUT, SOUND_PAN_TARGET + createvisualtask AnimTask_RandomBool, 2 + jumpretfalse PopulationBombSliceRight + jumprettrue PopulationBombSliceLeft +PopulationBombSliceRight: + createsprite gCuttingSliceSpriteTemplate, ANIM_ATTACKER, 2, 40, -32, 0 + goto PopulationBombContinue +PopulationBombSliceLeft: + createsprite gCuttingSliceSpriteTemplate, ANIM_ATTACKER, 2, 40, -32, 1 +PopulationBombContinue: + delay 5 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 10, 1 + waitforvisualfinish + clearmonbg ANIM_TARGET + blendoff + waitforvisualfinish + end + Move_TERA_BLAST:: Move_ORDER_UP:: -Move_SPIN_OUT:: -Move_POPULATION_BOMB:: Move_GLAIVE_RUSH:: Move_REVIVAL_BLESSING:: Move_SALT_CURE:: Move_TRIPLE_DIVE:: -Move_MORTAL_SPIN:: Move_DOODLE:: -Move_FILLET_AWAY:: -Move_FLOWER_TRICK:: -Move_MAKE_IT_RAIN:: Move_RUINATION:: Move_COLLISION_COURSE:: Move_ELECTRO_DRIFT:: -Move_SHED_TAIL:: -Move_HYPER_DRILL:: -Move_TWIN_BEAM:: Move_ARMOR_CANNON:: -Move_COMEUPPANCE:: Move_BLAZING_TORQUE:: Move_WICKED_TORQUE:: Move_NOXIOUS_TORQUE:: Move_COMBAT_TORQUE:: Move_MAGICAL_TORQUE:: Move_PSYBLADE:: -Move_BLOOD_MOON:: Move_MATCHA_GOTCHA:: Move_TERA_STARSTORM:: -Move_FICKLE_BEAM:: -Move_THUNDERCLAP:: Move_MIGHTY_CLEAVE:: Move_TACHYON_CUTTER:: -Move_HARD_PRESS:: -Move_DRAGON_CHEER:: Move_SUPERCELL_SLAM:: -Move_MALIGNANT_CHAIN:: end @to do @@@@@@@@@@@@@@@@@@@@@@@ GEN 1-3 @@@@@@@@@@@@@@@@@@@@@@@ diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index beb3bd5423..386eec22fa 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -30,6 +30,19 @@ BattleScript_DamageToQuarterTargetHP:: damagetoquartertargethp goto BattleScript_HitFromAtkAnimation +BattleScript_EffectFickleBeam:: + attackcanceler + attackstring + ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + ficklebeamdamagecalculation + goto BattleScript_HitFromCritCalc +BattleScript_FickleBeamDoubled:: + pause B_WAIT_TIME_SHORTEST + printstring STRINGID_FICKLEBEAMDOUBLED + waitmessage B_WAIT_TIME_LONG + goto BattleScript_HitFromCritCalc + BattleScript_Terastallization:: @ TODO: no string prints in S/V, but right now this helps with clarity printstring STRINGID_PKMNSTORINGENERGY @@ -565,7 +578,7 @@ BattleScript_Teatimerod: statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_TeatimeBuffer jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_TeatimeBuffer printfromtable gStatUpStringIds - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG moveendto MOVEEND_NEXT_TARGET jumpifnexttargetvalid BattleScript_TeatimeLoop moveendcase MOVEEND_CLEAR_BITS @@ -577,7 +590,7 @@ BattleScript_Teatimemotor: statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_TeatimeBuffer jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_TeatimeBuffer printfromtable gStatUpStringIds - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG moveendto MOVEEND_NEXT_TARGET jumpifnexttargetvalid BattleScript_TeatimeLoop moveendcase MOVEEND_CLEAR_BITS @@ -865,6 +878,7 @@ BattleScript_OctlockTurnDmgEnd: BattleScript_EffectPoltergeist:: attackcanceler + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE attackstring ppreduce checkpoltergeist BS_TARGET, BattleScript_ButItFailed @@ -914,19 +928,10 @@ BattleScript_BothCanNoLongerEscape:: return BattleScript_EffectHyperspaceFury:: - jumpifspecies BS_ATTACKER, SPECIES_HOOPA_UNBOUND, BattleScript_EffectHyperspaceFuryUnbound + jumpifspecies BS_ATTACKER, SPECIES_HOOPA_UNBOUND, BattleScript_EffectHit jumpifspecies BS_ATTACKER, SPECIES_HOOPA_CONFINED, BattleScript_ButHoopaCantUseIt goto BattleScript_PokemonCantUseTheMove -BattleScript_EffectHyperspaceFuryUnbound:: - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - pause B_WAIT_TIME_LONG - ppreduce - seteffectprimary MOVE_EFFECT_FEINT - goto BattleScript_HitFromCritCalc - BattleScript_ButHoopaCantUseIt: printstring STRINGID_BUTHOOPACANTUSEIT waitmessage B_WAIT_TIME_LONG @@ -7136,7 +7141,7 @@ BattleScript_TargetFormChangeWithStringNoPopup:: BattleScript_BattlerFormChangeWithStringEnd3:: pause 5 - call BattleScript_AbilityPopUp + call BattleScript_AbilityPopUpScripting flushtextbox handleformchange BS_SCRIPTING, 0 handleformchange BS_SCRIPTING, 1 @@ -7740,6 +7745,15 @@ BattleScript_CheekPouchActivates:: copybyte gBattlerAttacker, sSAVED_BATTLER return +BattleScript_PickupActivates:: + pause 5 + tryrecycleitem BattleScript_PickupActivatesEnd + call BattleScript_AbilityPopUp + printstring STRINGID_XFOUNDONEY + waitmessage B_WAIT_TIME_LONG +BattleScript_PickupActivatesEnd: + end3 + BattleScript_HarvestActivates:: pause 5 tryrecycleitem BattleScript_HarvestActivatesEnd @@ -7987,7 +8001,7 @@ BattleScript_DeltaStreamActivates:: end3 BattleScript_ProtosynthesisActivates:: - call BattleScript_AbilityPopUp + call BattleScript_AbilityPopUpScripting printstring STRINGID_SUNLIGHTACTIVATEDABILITY waitmessage B_WAIT_TIME_MED printstring STRINGID_STATWASHEIGHTENED diff --git a/data/battle_scripts_2.s b/data/battle_scripts_2.s index 6238afb36c..7fe22195c8 100644 --- a/data/battle_scripts_2.s +++ b/data/battle_scripts_2.s @@ -45,7 +45,7 @@ BattleScript_UseItemMessage: printfromtable gTrainerUsedItemStringIds waitmessage B_WAIT_TIME_LONG return - + BattleScript_ItemRestoreHPRet: bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE diff --git a/dev_scripts/followers/rename_to_graphics_pokemon.py b/dev_scripts/followers/rename_to_graphics_pokemon.py index bad1758b0c..a89348ddb4 100644 --- a/dev_scripts/followers/rename_to_graphics_pokemon.py +++ b/dev_scripts/followers/rename_to_graphics_pokemon.py @@ -59,6 +59,6 @@ def rellocate_follower_graphics(): #os.popen('cp followers/' + name + '.png followers/' + name + '/follower.png') #os.remove('followers/' + name + '.png') #print(pth) - #subprocess.run(["tools/gbagfx/gbagfx " + name +".png " + name + "_normal.pal'" + str(count) + "'"]) + #subprocess.run(["tools/gbagfx/gbagfx " + name +".png " + name + "_normal.pal'" + str(count) + "'"]) rellocate_follower_graphics() diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index fce328d858..603fa225db 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -3,6 +3,8 @@ - [README](./README.md) - [Installation](./INSTALL.md) - [Setting up WSL1 (Legacy Portion)](./legacy_WSL1_INSTALL.md) +- [Run documentation site locally](local_mdbook/index.md) + - [Ubuntu WSL1/WSL2](local_mdbook/ubuntu_WSL.md) - [AI Flags](./ai_flags.md) - [Tutorials]() - [How to add new AI Flags](./ai_logic.md) @@ -10,10 +12,10 @@ - [How to add a new move](./how_to_new_move.md) - [How to add a new trainer class](./how_to_trainer_class.md) - [How to add a new Pokémon]() - - [v1.9.0](./how_to_new_pokemon_1_9_0.md) - - [v1.8.0](./how_to_new_pokemon_1_8_0.md) - - [v1.7.0](./how_to_new_pokemon_1_7_0.md) - - [v1.6.0](./how_to_new_pokemon_1_6_0.md) + - [v1.9.x](./how_to_new_pokemon_1_9_0.md) + - [v1.8.x](./how_to_new_pokemon_1_8_0.md) + - [v1.7.x](./how_to_new_pokemon_1_7_0.md) + - [v1.6.x](./how_to_new_pokemon_1_6_0.md) - [How to use the Testing System](./how_to_testing_system.md) - [Changelog](./CHANGELOG.md) - [1.9.x]() diff --git a/docs/ai_flags.md b/docs/ai_flags.md index cc5c1631ff..bb7b1b7444 100644 --- a/docs/ai_flags.md +++ b/docs/ai_flags.md @@ -21,14 +21,14 @@ AI: Check Bad Move / Try to Faint / Check Viability. The name of each flag is ju * Sequence Switching ## `COMPETITIVE_PARTY_SYNTAX != TRUE` / Not Found -If you are not using competitive syntax parties, instead access the trainer data directly in [`src/data/trainers.h`](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/trainers.h), and add flags like so, typed exactly the same as the flag names themselves: +If you are not using competitive syntax parties, instead access the trainer data directly in [`src/data/trainers.h`](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/trainers.h), and add flags like so, typed exactly the same as the flag names themselves: `.aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY` # What AI Flags does pokeemerald-expansion have? This section lists all of expansion’s AI Flags and briefly describes the effect they have on the AI’s behaviour. In all cases, please check the corresponding function or surrounding code around their implementation for more details. Some of these functions are vanilla, some share a name with vanilla but have been modified to varying degrees, and some are completely new. ## `AI_FLAG_CHECK_BAD_MOVE` -The AI will avoid using moves that are likely to fail in the current situation. This flag helps prevent the AI from making ineffective choices, such as using moves into immunities, into invulnerable states, or when the moves are otherwise hindered by abilities, terrain, or status conditions. +The AI will avoid using moves that are likely to fail in the current situation. This flag helps prevent the AI from making ineffective choices, such as using moves into immunities, into invulnerable states, or when the moves are otherwise hindered by abilities, terrain, or status conditions. ## `AI_FLAG_TRY_TO_FAINT` AI will prioritize KOing the player if able rather than using status moves. Will prioritize using a move that can OHKO the player. If the player can KO the AI’s mon and the AI’s mon is slower, prioritize priority moves (this does not prevent the AI from switching out instead). @@ -58,12 +58,12 @@ AI will generally behave more recklessly. This AI enables the following behaviou * Prioritize Explosion moves ## `AI_FLAG_PREFER_STRONGEST_MOVE` -Adds score bonus to any move the AI has that either OHKOs or 2HKOs the player. +Adds score bonus to any move the AI has that either OHKOs or 2HKOs the player. Keep in mind that this is a weaker form of `AI_FLAG_TRY_TO_FAINT` at scoring OHKOs as it does not take into account who is attacking first, it does however handle 2HKOs. ## `AI_FLAG_PREFER_BATON_PASS` -AI prefers raising its own stats if it has >= 60% HP, as well as Ingrain, Aqua Ring, and Protect. Prioritizes Baton Bass if the mon is rooted (Ingrain) or has the Aqua Ring effect, and doesn’t if it has been Leech Seeded. +AI prefers raising its own stats if it has >= 60% HP, as well as Ingrain, Aqua Ring, and Protect. Prioritizes Baton Bass if the mon is rooted (Ingrain) or has the Aqua Ring effect, and doesn’t if it has been Leech Seeded. ## `AI_FLAG_DOUBLE_BATTLE` This flag is automatically set in double battles, and controls much of the doubles-specific scoring. I’ll summarize some of its scoring as follows: @@ -83,7 +83,7 @@ With respect to the AI’s mons, in doubles: In both singles and doubles: * Prioritizes not using moves that require the user fainting (Destiny Bond, Explosion etc.) and healing moves while on >= 70% HP. * Prioritize not using moves that require the user fainting or losing significant HP (Belly Drum etc) while between 30% and 70% HP -* Prioritize not using setup moves (Light Screen etc.) and Bide while on <= 30% HP +* Prioritize not using setup moves (Light Screen etc.) and Bide while on <= 30% HP With respect to the player’s mons: * Prioritize not using many status moves (stat buffs, Poison, Pain Split) if the player has between 30% and 70% HP @@ -96,7 +96,7 @@ AI prioritizes setting up field effects (Trick Room, Rain Dance, etc.) and side AI does not understand ability suppression (Mold Breaker etc., weather suppression (Air Lock etc.), redirection abilities (Lightningrod etc.) being temporarily removed due to move effects (Sky Drop etc.), or item suppression (Magic Room etc.) and will ignore them. This is a handicap flag. ## `AI_FLAG_WILL_SUICIDE` -AI prioritizes self destruction moves (Explosion, Memento). +AI prioritizes self destruction moves (Explosion, Memento). ## `AI_FLAG_PREFER_STATUS_MOVES` AI gets a score bonus for status moves. This should be combined with `AI_FLAG_CHECK_BAD_MOVE` to prevent using only status moves. @@ -127,7 +127,7 @@ Affects when the AI chooses to switch. AI will make smarter decisions about when Marks the last Pokemon in the party as the Ace Pokemon. It will not be used unless it is the last one remaining, or is forced to be switched in (Roar, U-Turn with 1 mon remaining, etc.) ## `AI_FLAG_OMNISCIENT` -AI has full knowledge of player moves, abilities, and hold items, and can use this knowledge when making decisions. +AI has full knowledge of player moves, abilities, and hold items, and can use this knowledge when making decisions. ## `AI_FLAG_SMART_MON_CHOICES` Affects what the AI chooses to send out after a switch. AI will make smarter decisions when choosing which mon to send out mid-battle and after a KO, which are handled separately. Automatically included when `AI_FLAG_SMART_SWITCHING` is enabled. @@ -148,7 +148,7 @@ And will choose mons after a mid-battle switch prioritizing the following criter * Has Baton Pass ## `AI_FLAG_CONSERVATIVE` -AI always assumes it will roll the lowest possible result when comparing damage in scoring. +AI always assumes it will roll the lowest possible result when comparing damage in scoring. ## `AI_FLAG_SEQUENCE_SWITCHING` AI will always switch out after a KO in exactly party order as defined in the trainer data (ie. slot 1, then 2, then 3, etc.). The AI will never switch out mid-battle unless forced to (Roar etc.). If the AI uses a move that requires a switch where it makes a decision about what to send in (U-Turn etc.), it will always switch out into the lowest available party index. diff --git a/docs/changelogs/1.5.x/1.5.2.md b/docs/changelogs/1.5.x/1.5.2.md index ab6735c7a3..69e0ecaabf 100644 --- a/docs/changelogs/1.5.x/1.5.2.md +++ b/docs/changelogs/1.5.x/1.5.2.md @@ -92,5 +92,5 @@ * Court Change by @DizzyEggg in https://github.com/rh-hideout/pokeemerald-expansion/pull/3160 * Item Effects * Utility Umbrella, by @AsparagusEduardo in https://github.com/rh-hideout/pokeemerald-expansion/pull/2835 - + **Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.5.1...expansion/1.5.2 \ No newline at end of file diff --git a/docs/changelogs/1.5.x/1.5.3.md b/docs/changelogs/1.5.x/1.5.3.md index 831814740a..85748b2375 100644 --- a/docs/changelogs/1.5.x/1.5.3.md +++ b/docs/changelogs/1.5.x/1.5.3.md @@ -9,8 +9,8 @@ ## CRITICAL FIX, please update to avoid the issues detailed down below: - Fixed memory corruption when handling trigger sprites by @SBird1337 in https://github.com/rh-hideout/pokeemerald-expansion/pull/3238 - This had the posibility of manifesting in weird ways, like camera and music changes, NPC duplication and more. If you've had this issue in the past, we ***heavily*** recommend you update to this version of the expansion. - - Thank you @Bassoonian for helping us pinpointing the issue. - + - Thank you @Bassoonian for helping us pinpointing the issue. + ![image](https://github.com/rh-hideout/pokeemerald-expansion/assets/2904965/26b9b984-c5db-4dac-85f7-5fc4e95a32ce) ![image](https://github.com/rh-hideout/pokeemerald-expansion/assets/2904965/d490eb30-ce54-4b90-bb2e-79c2e9bb50ac) diff --git a/docs/changelogs/1.7.x/1.7.2.md b/docs/changelogs/1.7.x/1.7.2.md index 34aa131e70..a92d778956 100644 --- a/docs/changelogs/1.7.x/1.7.2.md +++ b/docs/changelogs/1.7.x/1.7.2.md @@ -41,7 +41,7 @@ * Clodsire * Crocalor * Dolliv - * Dudunsparce + * Dudunsparce * Esparthra ### Fixed * Multiple Pokémon graphical fixes by @katykat5099 in https://github.com/rh-hideout/pokeemerald-expansion/pull/3805 diff --git a/docs/changelogs/1.9.x/1.9.1.md b/docs/changelogs/1.9.x/1.9.1.md new file mode 100644 index 0000000000..8393727c2a --- /dev/null +++ b/docs/changelogs/1.9.x/1.9.1.md @@ -0,0 +1,140 @@ +# Version 1.9.1 + +```md +## How to update +- If you haven't set up a remote, run the command `git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion`. +- Once you have your remote set up, run the command `git pull RHH expansion/1.9.1`. +``` + +## 🌋 *REFACTORS* 🌋 +* Removed `ENDTURN_RETALIATE` in [#5182](https://github.com/rh-hideout/pokeemerald-expansion/pull/5182) +* Removed `ENDTURN_WEATHER_FORM` and `allowedToChangeFormInWeather` in [#5171](https://github.com/rh-hideout/pokeemerald-expansion/pull/5171) + +## 🧬 General 🧬 +### Added +* Move Relearner UI now displays move category by @kittenchilly in [#5081](https://github.com/rh-hideout/pokeemerald-expansion/pull/5081) +### Fixed +* Fixes wrong padding field in `SpeciesInfo` struct by @AlexOn1ine in [#5139](https://github.com/rh-hideout/pokeemerald-expansion/pull/5139) +* Fixed specific tiles changing to PC tiles when using Box Link/Debug PC option by @cawtds in [#5141](https://github.com/rh-hideout/pokeemerald-expansion/pull/5141) + +## 🐉 Pokémon 🐉 +### Fixed +* Fixed stray transparent pixels in Urshifu sprites by @hedara90 in [#5071](https://github.com/rh-hideout/pokeemerald-expansion/pull/5071) +* Fixed `bufferspeciesname` not working for species IDs over 1023 by @SBird1337 in [#5088](https://github.com/rh-hideout/pokeemerald-expansion/pull/5088) +* Fixed overworld Pokémon breaking for species IDs above 1535 by @hedara90, @mrgriffin and +@SarnPoke in [#5179](https://github.com/rh-hideout/pokeemerald-expansion/pull/5179) +* Fixed overworld palettes for multiple species by @hedara90 in [#5107](https://github.com/rh-hideout/pokeemerald-expansion/pull/5107) + * Dialga Origin (Normal and Shiny) + * Palkia Origin (Normal and Shiny) + * Giratina Origin (shiny palette fixed by @hedara90 in [#5108](https://github.com/rh-hideout/pokeemerald-expansion/pull/5108)) + * Xerneas Neutral/Active (Normal and Shiny) + * Enamorus Incarnate/Therian (Normal and Shiny) +* Fixed/added missing Pokémon sprites and palettes by @Cafeei in [#5126](https://github.com/rh-hideout/pokeemerald-expansion/pull/5126) + * Overworld: + * Shiny Sneasler, Morelul, Bounsweet, Bruxish, Guzzlord, Regieleki, Zacian, Zamazenta + * Hisuian Zorua sprite + * Shiny Summer Sawsbuck + * Shiny Galarian Yamask, Darumaka, Zigzagoon, Zapdos, Ponyta, Rapidash, Slowpoke, Farfetch'd, Weezing, Mr. Mime, Articuno, Moltres, Slowking, Stunfisk, Darmanitan + * Shiny Hisuian Sneasel, Qwilfish, Samurott, + * Battle sprites: + * Shiny Sneasler, Cursola, Pincurchin, Runerigus + * Shiny Galarian Yamask, Darumaka +* Fixed Unown Overworld follower sprites by Sarn by @hedara90 in [#5146](https://github.com/rh-hideout/pokeemerald-expansion/pull/5146) + +## ⚔️ Battle General ⚔️ +### Changed +* Set new animation particles by default to off by @AlexOn1ine in [#5161](https://github.com/rh-hideout/pokeemerald-expansion/pull/5161) +### Fixed +* Fixed speed ties by @mrgriffin in [#4780](https://github.com/rh-hideout/pokeemerald-expansion/pull/4780) + * Cleanup by @hedara90 in [#5092](https://github.com/rh-hideout/pokeemerald-expansion/pull/5092) +* Fixed Defiant/Competitive not working after the battler enters the field with a Court Changed Sticky Web on its side of the field by @PhallenTree in [#5093](https://github.com/rh-hideout/pokeemerald-expansion/pull/5093) +* Fixed `trainerproc` not properly parsing line markers, which caused erroring lines to be offset by @mrgriffin in [#5122](https://github.com/rh-hideout/pokeemerald-expansion/pull/5122) +* Fixed initial Zigzagoon battle being able to use a Gimmick by @AlexOn1ine in [#5129](https://github.com/rh-hideout/pokeemerald-expansion/pull/5129) +* Fixed incorrect rounding when `maxHP` is lower than 16 by @hedara90 in [#5183](https://github.com/rh-hideout/pokeemerald-expansion/pull/5183) + * This caused these Pokémon to not be hurt by Sandstorm/Hail. +* Fixes UB in `Cmd_averagestats` by @mrgriffin and @AlexOn1ine in [#5191](https://github.com/rh-hideout/pokeemerald-expansion/pull/5191) + +## 🤹 Moves 🤹 +### Added +* Added move animations for multiple moves by @TheTrueSadfish in [#5159](https://github.com/rh-hideout/pokeemerald-expansion/pull/5159) + * Spin Out, Mortal Spin, Fillet Away, Flower Trick, Make It Rain, Shed Tail, Hyper Drill, Twin Beam, Comeuppance, Blood Moon, Fickle Beam, Thunder Clap, Hard Press, Dragon Cheer, Malignant Chain. + * Purple chains by ogwon on Discord, beam by @TheTrueSadfish and livra on Discord. +### Changed +* Adjusted Raging Bull's animation to include Brick Break's wall break effect by @TheTrueSadfish in [#5159](https://github.com/rh-hideout/pokeemerald-expansion/pull/5159) +### Fixed +* Fixed non-grass Ivy Cudgel breaking battle UI by @hedara90 in [#5117](https://github.com/rh-hideout/pokeemerald-expansion/pull/5117) +* Fixes Stomping Tantrum effect not doubling power in certain situations by @AlexOn1ine in [#5140](https://github.com/rh-hideout/pokeemerald-expansion/pull/5140) +* Fixed Fickle Beam's description by @PhallenTree in [#5093](https://github.com/rh-hideout/pokeemerald-expansion/pull/5093) +* Fixed Revelation Dance interactions with Z-Move, Roost and typeless mons by @PhallenTree in [#5133](https://github.com/rh-hideout/pokeemerald-expansion/pull/5133) +* Fixes Poltergeist missing its accuracy check by @AlexOn1ine in [#5168](https://github.com/rh-hideout/pokeemerald-expansion/pull/5168) +* Fixed Fickle Beam not showing its message by @TheTrueSadfish in [#5159](https://github.com/rh-hideout/pokeemerald-expansion/pull/5159) +* Fixed Retaliate not working correctly if the party member fainted via passive damage during end of turn by @hedara90 in [#5182](https://github.com/rh-hideout/pokeemerald-expansion/pull/5182) +* Fixed Flame Burst's passive damage being based off current HP rather than Max HP by @hedara90 in [#5182](https://github.com/rh-hideout/pokeemerald-expansion/pull/5182) +* Fixed using Population Bomb with Loaded Dice printing garbage text by @kittenchilly in [#5195](https://github.com/rh-hideout/pokeemerald-expansion/pull/5195) + +## 🎭 Abilities 🎭 +### Added +* Added in-battle effect of Pickup by @PhallenTree in [#5170](https://github.com/rh-hideout/pokeemerald-expansion/pull/5170) +### Fixed +* Fixes Purifying Salt not halving damage for dynamic move types by @AlexOn1ine in [#5145](https://github.com/rh-hideout/pokeemerald-expansion/pull/5145) +* Fixed Dancer-called moves not changing their type based on the new user by @PhallenTree in [#5133](https://github.com/rh-hideout/pokeemerald-expansion/pull/5133) +* Fixed Ice Face not regenerating after switching in during Hail/Snow by @hedara90 in [#5171](https://github.com/rh-hideout/pokeemerald-expansion/pull/5171) +* Fixed Wind Rider not activating when switched in while Tailwind is active on the user's side of the field activation and tests by @PhallenTree in https://github.com/rh-hideout/pokeemerald-expansion/pull/5207 + +## 🧶 Items 🧶 +### Added +* Added Dowsing Machine's expanded name by @kittenchilly in [#5134](https://github.com/rh-hideout/pokeemerald-expansion/pull/5134) +### Fixed +* Fixes Booster Energy not increasing speed by @AlexOn1ine in [#5167](https://github.com/rh-hideout/pokeemerald-expansion/pull/5167) + +## 🤖 Battle AI 🤖 +### Changed +* Adjusted AI calculation for Triple Kick Effect by @AlexOn1ine in [#5127](https://github.com/rh-hideout/pokeemerald-expansion/pull/5127) +### Fixed +* Fix Switch AI Bug: AI never switching out when it could be OHKO'd by @Pawkkie in [#5089](https://github.com/rh-hideout/pokeemerald-expansion/pull/5089) +* Adds missing AI checks for poltergeist by @AlexOn1ine in [#5189](https://github.com/rh-hideout/pokeemerald-expansion/pull/5189) + +## 🧹 Other Cleanup 🧹 +* `IsValidForBattle` function formatting by @AlexOn1ine in [#5085](https://github.com/rh-hideout/pokeemerald-expansion/pull/5085) +* Opportunist/Mirror Herb cleanup by @AlexOn1ine in [#5120](https://github.com/rh-hideout/pokeemerald-expansion/pull/5120) + * Cleanup by @AlexOn1ine in [#5158](https://github.com/rh-hideout/pokeemerald-expansion/pull/5158) +* Remove trailing whitespace (master) by @AsparagusEduardo in [#5174](https://github.com/rh-hideout/pokeemerald-expansion/pull/5174) + +## 🧪 Test Runner 🧪 +### Added +* Added missing Move Effect TODO tests - Volume C by @AsparagusEduardo in [#5094](https://github.com/rh-hideout/pokeemerald-expansion/pull/5094) +* Added multiple missing ability TODO tests by @AsparagusEduardo in [#5163](https://github.com/rh-hideout/pokeemerald-expansion/pull/5163) +* Added missing Guard/Power split tests by @mrgriffin and @AlexOn1ine in [#5191](https://github.com/rh-hideout/pokeemerald-expansion/pull/5191) +* Added missing Harvest and Pickup tests by @PhallenTree in [#5170](https://github.com/rh-hideout/pokeemerald-expansion/pull/5170) +* Added missing Round tests by @hedara90 in https://github.com/rh-hideout/pokeemerald-expansion/pull/5196 +* Added missing Wind Rider tests by @PhallenTree in https://github.com/rh-hideout/pokeemerald-expansion/pull/5207 +### Changed +* Fixed G-Max Replenish not considering Gen 5+ Pickup by @PhallenTree in [#5170](https://github.com/rh-hideout/pokeemerald-expansion/pull/5170) +### Fixed +* Fixed `RandomUniformExcept` not being exclusive on the higher boundary by @PhallenTree in [#5170](https://github.com/rh-hideout/pokeemerald-expansion/pull/5170) + + +## 📚 Documentation 📚 +* Added guide to running documentation website locally by @AsparagusEduardo in [#5059](https://github.com/rh-hideout/pokeemerald-expansion/pull/5059) +* How to docs and fixes to be added to the mdbook documentation site by @anrichtait in [#5070](https://github.com/rh-hideout/pokeemerald-expansion/pull/5070) +* Improved 1.8 ⇒ 1.9 non-Competitive syntax migration instructions by @mrgriffin in [#5079](https://github.com/rh-hideout/pokeemerald-expansion/pull/5079) + +## 📦 Branch Synchronisation 📦 +### pret +* 5th of August in [#5098](https://github.com/rh-hideout/pokeemerald-expansion/pull/5098) + * Fixed bottom half of Mt. Pyre not being labeled in PokeNav by @fdeblasio in [pret#2018](https://github.com/pret/pokeemerald/pull/2018) +* 7th of August in [#5116](https://github.com/rh-hideout/pokeemerald-expansion/pull/5116) + * Changed type1 and type2 to be consistent by @pkmnsnfrn in [pret#2021](https://github.com/pret/pokeemerald/pull/2021) +* 14th of August in [#5165](https://github.com/rh-hideout/pokeemerald-expansion/pull/5165) + * Fix type for offset in MapConnection by @GriffinRichards in [pret#2011](https://github.com/pret/pokeemerald/pull/2011) +### Followers +* 7th of August in [#5110](https://github.com/rh-hideout/pokeemerald-expansion/pull/5110) + * Fixed expanded OW IDs by @pkmnsnfrn in [aarant#38](https://github.com/aarant/pokeemerald/pull/38) + * Fix two small text errors in follower dialogue by @Bassoonian in [aarant#39](https://github.com/aarant/pokeemerald/pull/39) + +**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.9.0...expansion/1.9.1 + +## New Contributors +* @TheTrueSadfish made their first contribution in https://github.com/rh-hideout/pokeemerald-expansion/pull/5159 + + diff --git a/docs/changelogs/template.md b/docs/changelogs/template.md index 6641d612f3..a40afebad3 100644 --- a/docs/changelogs/template.md +++ b/docs/changelogs/template.md @@ -122,7 +122,10 @@ ### Fixed * N/A -## 📦 Pret merges 📦 +## 📦 Branch Synchronisation 📦 +### pret's base pokeemerald +* N/A +### merrp/aarant's followers * N/A diff --git a/docs/how_to_new_pokemon_1_6_0.md b/docs/how_to_new_pokemon_1_6_0.md index d965e48a5f..9bf3e2e61f 100644 --- a/docs/how_to_new_pokemon_1_6_0.md +++ b/docs/how_to_new_pokemon_1_6_0.md @@ -384,7 +384,7 @@ Edit [src/data/text/species_names.h](https://github.com/rh-hideout/pokeemerald-e const u8 gSpeciesNames[][POKEMON_NAME_LENGTH + 1] = { [SPECIES_NONE] = _("??????????"), [SPECIES_BULBASAUR] = _("Bulbasaur"), - ... + ... [SPECIES_ENAMORUS] = _("Enamorus"), + [SPECIES_MEWTHREE] = _("Mewthree"), }; @@ -482,7 +482,7 @@ Append to [src/data/pokemon/pokedex_text.h](https://github.com/rh-hideout/pokeem "winter. According to legend, this\n" "Pokémon's love gives rise to the\n" "budding of fresh life across the land."); - + +const u8 gMewthreePokedexText[] = _( + "The rumors became true.\n" + "This is Mews final form.\n" @@ -509,7 +509,7 @@ Edit [src/data/pokemon/pokedex_entries.h](https://github.com/rh-hideout/pokeemer .trainerScale = 296, .trainerOffset = 1, }, - + + [NATIONAL_DEX_MEWTHREE] = + { + .categoryName = _("NEW SPECIES"), @@ -553,7 +553,7 @@ Edit [src/data/pokemon/pokedex_orders.h](https://github.com/rh-hideout/pokeemera NATIONAL_DEX_DUGTRIO, ... }; - + const u16 gPokedexOrder_Height[] = { ... @@ -598,7 +598,7 @@ Edit [src/data/pokemon/species_info.h](https://github.com/rh-hideout/pokeemerald }, + [SPECIES_MEWTHREE] = -+ { ++ { + .baseHP = 106, + .baseAttack = 150, + .baseDefense = 70, diff --git a/docs/how_to_new_pokemon_1_7_0.md b/docs/how_to_new_pokemon_1_7_0.md index 801ae8e549..30c1f82dbe 100644 --- a/docs/how_to_new_pokemon_1_7_0.md +++ b/docs/how_to_new_pokemon_1_7_0.md @@ -170,7 +170,7 @@ Edit [src/data/pokemon/species_info.h](https://github.com/rh-hideout/pokeemerald }, + [SPECIES_MEWTHREE] = -+ { ++ { + .baseHP = 106, + .baseAttack = 150, + .baseDefense = 70, @@ -234,7 +234,7 @@ That's all the basic fields present in vanilla emerald, so now let's take a look { ... [SPECIES_MEWTHREE] = - { + { ... .isLegendary = TRUE, .allPerfectIVs = TRUE, @@ -309,7 +309,7 @@ Lastly, we add the cry to our species entry { ... [SPECIES_MEWTHREE] = - { + { ... .isLegendary = TRUE, .allPerfectIVs = TRUE, @@ -388,7 +388,7 @@ Now we can add the number and entry to our Mewthree: { ... [SPECIES_MEWTHREE] = - { + { ... .cryId = CRY_MEWTHREE, + .natDexNum = NATIONAL_DEX_MEWTHREE, @@ -409,7 +409,7 @@ Now we can add the number and entry to our Mewthree: ``` ![image](https://github.com/rh-hideout/pokeemerald-expansion/assets/2904965/3759dd4c-8da5-4b1c-9a50-b9e9d0815e7f) -The values `pokemonScale`, `pokemonOffset`, `trainerScale` and `trainerOffset` are used for the height comparison figure in the Pokédex. +The values `pokemonScale`, `pokemonOffset`, `trainerScale` and `trainerOffset` are used for the height comparison figure in the Pokédex. `height` and `weight` are specified in decimeters and hectograms respectively (which are meters and kilograms multiplied by 10, so 2.5 meters are 25 decimeters). @@ -443,7 +443,7 @@ Edit [src/data/pokemon/pokedex_orders.h](https://github.com/rh-hideout/pokeemera NATIONAL_DEX_DUGTRIO, ... }; - + const u16 gPokedexOrder_Height[] = { ... @@ -560,7 +560,7 @@ Now that we have all the external data ready, we just need to add it to `gSpecie { ... [SPECIES_MEWTHREE] = - { + { ... .pokemonScale = 256, .pokemonOffset = 0, @@ -612,7 +612,7 @@ Let's explain each of these: - Used to define what Y position of the back sprite. When working with the animation debug menu, we recommend aligning the back sprite to the white background, as it was designed to properyly align with the real battle layout. - `backAnimId`: - Like `frontAnimId` except for the back sprites and them being a single frame. The IDs listed [here](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/pokemon_animation.h) are used to represent 3 different animations that happen based on the the Pokémon's nature. -- `PALETTES` +- `PALETTES` - This macro was created to handle both regular and shiny palettes of a Pokémon. It just needs the species suffix to call the corresponding palette. ```c #define PALETTES(pal) \ @@ -650,7 +650,7 @@ We're almost there just a bit left! { ... [SPECIES_MEWTHREE] = - { + { ... .abilities = { ABILITY_INSOMNIA, ABILITY_NONE, ABILITY_NONE }, .bodyColor = BODY_COLOR_PURPLE, @@ -745,7 +745,7 @@ Again, we need to register the learnset in `gSpeciesInfo`: { ... [SPECIES_MEWTHREE] = - { + { ... PALETTES(Mewthree), ICON(Mewthree, 2), @@ -846,7 +846,7 @@ Once more, we need to register the learnset in `gSpeciesInfo`: { ... [SPECIES_MEWTHREE] = - { + { ... FOOTPRINT(Mewthree) .levelUpLearnset = sMewthreeLevelUpLearnset, @@ -869,7 +869,7 @@ Edit `gSpeciesInfo`: { ... [SPECIES_MEWTWO] = - { + { ... FOOTPRINT(Mewtwo) .isLegendary = TRUE, diff --git a/docs/how_to_new_pokemon_1_8_0.md b/docs/how_to_new_pokemon_1_8_0.md index c4c7ab621c..6dbb009fcf 100644 --- a/docs/how_to_new_pokemon_1_8_0.md +++ b/docs/how_to_new_pokemon_1_8_0.md @@ -181,7 +181,7 @@ Edit [src/data/pokemon/species_info.h](https://github.com/rh-hideout/pokeemerald }, + [SPECIES_MEWTHREE] = -+ { ++ { + .baseHP = 106, + .baseAttack = 150, + .baseDefense = 70, @@ -245,7 +245,7 @@ That's all the basic fields present in vanilla emerald, so now let's take a look { ... [SPECIES_MEWTHREE] = - { + { ... .isLegendary = TRUE, .allPerfectIVs = TRUE, @@ -320,7 +320,7 @@ Lastly, we add the cry to our species entry { ... [SPECIES_MEWTHREE] = - { + { ... .isLegendary = TRUE, .allPerfectIVs = TRUE, @@ -399,7 +399,7 @@ Now we can add the number and entry to our Mewthree: { ... [SPECIES_MEWTHREE] = - { + { ... .cryId = CRY_MEWTHREE, + .natDexNum = NATIONAL_DEX_MEWTHREE, @@ -420,7 +420,7 @@ Now we can add the number and entry to our Mewthree: ``` ![image](https://github.com/rh-hideout/pokeemerald-expansion/assets/2904965/3759dd4c-8da5-4b1c-9a50-b9e9d0815e7f) -The values `pokemonScale`, `pokemonOffset`, `trainerScale` and `trainerOffset` are used for the height comparison figure in the Pokédex. +The values `pokemonScale`, `pokemonOffset`, `trainerScale` and `trainerOffset` are used for the height comparison figure in the Pokédex. `height` and `weight` are specified in decimeters and hectograms respectively (which are meters and kilograms multiplied by 10, so 2.5 meters are 25 decimeters). @@ -454,7 +454,7 @@ Edit [src/data/pokemon/pokedex_orders.h](https://github.com/rh-hideout/pokeemera NATIONAL_DEX_DUGTRIO, ... }; - + const u16 gPokedexOrder_Height[] = { ... @@ -571,7 +571,7 @@ Now that we have all the external data ready, we just need to add it to `gSpecie { ... [SPECIES_MEWTHREE] = - { + { ... .pokemonScale = 256, .pokemonOffset = 0, @@ -651,7 +651,7 @@ We're almost there just a bit left! { ... [SPECIES_MEWTHREE] = - { + { ... .abilities = { ABILITY_INSOMNIA, ABILITY_NONE, ABILITY_NONE }, .bodyColor = BODY_COLOR_PURPLE, @@ -746,7 +746,7 @@ Again, we need to register the learnset in `gSpeciesInfo`: { ... [SPECIES_MEWTHREE] = - { + { ... PALETTES(Mewthree), ICON(Mewthree, 2), @@ -847,7 +847,7 @@ Once more, we need to register the learnset in `gSpeciesInfo`: { ... [SPECIES_MEWTHREE] = - { + { ... FOOTPRINT(Mewthree) .levelUpLearnset = sMewthreeLevelUpLearnset, @@ -870,7 +870,7 @@ Edit `gSpeciesInfo`: { ... [SPECIES_MEWTWO] = - { + { ... FOOTPRINT(Mewtwo) .isLegendary = TRUE, diff --git a/docs/how_to_new_pokemon_1_9_0.md b/docs/how_to_new_pokemon_1_9_0.md index 84742c3a76..e64f8e6e66 100644 --- a/docs/how_to_new_pokemon_1_9_0.md +++ b/docs/how_to_new_pokemon_1_9_0.md @@ -176,7 +176,7 @@ Edit [src/data/pokemon/species_info.h](https://github.com/rh-hideout/pokeemerald }, + [SPECIES_MEWTHREE] = -+ { ++ { + .baseHP = 106, + .baseAttack = 150, + .baseDefense = 70, @@ -240,7 +240,7 @@ That's all the basic fields present in vanilla emerald, so now let's take a look { ... [SPECIES_MEWTHREE] = - { + { ... .isLegendary = TRUE, .allPerfectIVs = TRUE, @@ -315,7 +315,7 @@ Lastly, we add the cry to our species entry { ... [SPECIES_MEWTHREE] = - { + { ... .isLegendary = TRUE, .allPerfectIVs = TRUE, @@ -394,7 +394,7 @@ Now we can add the number and entry to our Mewthree: { ... [SPECIES_MEWTHREE] = - { + { ... .cryId = CRY_MEWTHREE, + .natDexNum = NATIONAL_DEX_MEWTHREE, @@ -415,7 +415,7 @@ Now we can add the number and entry to our Mewthree: ``` ![image](https://github.com/rh-hideout/pokeemerald-expansion/assets/2904965/3759dd4c-8da5-4b1c-9a50-b9e9d0815e7f) -The values `pokemonScale`, `pokemonOffset`, `trainerScale` and `trainerOffset` are used for the height comparison figure in the Pokédex. +The values `pokemonScale`, `pokemonOffset`, `trainerScale` and `trainerOffset` are used for the height comparison figure in the Pokédex. `height` and `weight` are specified in decimeters and hectograms respectively (which are meters and kilograms multiplied by 10, so 2.5 meters are 25 decimeters). @@ -449,7 +449,7 @@ Edit [src/data/pokemon/pokedex_orders.h](https://github.com/rh-hideout/pokeemera NATIONAL_DEX_DUGTRIO, ... }; - + const u16 gPokedexOrder_Height[] = { ... @@ -566,7 +566,7 @@ Now that we have all the external data ready, we just need to add it to `gSpecie { ... [SPECIES_MEWTHREE] = - { + { ... .pokemonScale = 256, .pokemonOffset = 0, @@ -646,7 +646,7 @@ We're almost there just a bit left! { ... [SPECIES_MEWTHREE] = - { + { ... .abilities = { ABILITY_INSOMNIA, ABILITY_NONE, ABILITY_NONE }, .bodyColor = BODY_COLOR_PURPLE, @@ -745,7 +745,7 @@ Again, we need to register the learnset in `gSpeciesInfo`: { ... [SPECIES_MEWTHREE] = - { + { ... PALETTES(Mewthree), ICON(Mewthree, 2), @@ -846,7 +846,7 @@ Once more, we need to register the learnset in `gSpeciesInfo`: { ... [SPECIES_MEWTHREE] = - { + { ... FOOTPRINT(Mewthree) .levelUpLearnset = sMewthreeLevelUpLearnset, @@ -869,7 +869,7 @@ Edit `gSpeciesInfo`: { ... [SPECIES_MEWTWO] = - { + { ... FOOTPRINT(Mewtwo) .isLegendary = TRUE, @@ -1097,7 +1097,7 @@ And finally, in `gSpeciesInfo`: { ... [SPECIES_MEWTHREE] = - { + { ... FOOTPRINT(Mewthree) + OVERWORLD( diff --git a/docs/how_to_testing_system.md b/docs/how_to_testing_system.md index 793465114c..1f25f9847e 100644 --- a/docs/how_to_testing_system.md +++ b/docs/how_to_testing_system.md @@ -1,11 +1,11 @@ # How to use the Testing System ## Running Tests -To run all the tests use: -`make check -j` -To run specific tests, e.g. Spikes ones, use: -`make check TESTS='Spikes'` -To build a ROM (pokemerald-test.elf) that can be opened in mgba to view specific tests, e.g. Spikes ones, use: +To run all the tests use: +`make check -j` +To run specific tests, e.g. Spikes ones, use: +`make check TESTS='Spikes'` +To build a ROM (pokemerald-test.elf) that can be opened in mgba to view specific tests, e.g. Spikes ones, use: `make pokeemerald-test.elf TESTS='Spikes'` ## How to Write Tests @@ -48,21 +48,21 @@ SINGLE_BATTLE_TEST("Stun Spore inflicts paralysis") STATUS_ICON(opponent, paralysis: TRUE); // 4. } } -``` +``` -The `ASSUMPTIONS` block documents that Stun Spore has `EFFECT_PARALYZE`. -If Stun Spore did not have that effect it would cause the tests in the file to be skipped. We write our tests like this so that hackers can change the effects of moves without causing tests to fail. +The `ASSUMPTIONS` block documents that Stun Spore has `EFFECT_PARALYZE`. +If Stun Spore did not have that effect it would cause the tests in the file to be skipped. We write our tests like this so that hackers can change the effects of moves without causing tests to fail. -`SINGLE_BATTLE_TEST` defines the name of the test. Related tests should start with the same prefix, e.g. Stun Spore tests should start with "Stun Spore", this allows just the Stun Spore-related tests to be run with: -`make check TESTS='Stun Spore'` +`SINGLE_BATTLE_TEST` defines the name of the test. Related tests should start with the same prefix, e.g. Stun Spore tests should start with "Stun Spore", this allows just the Stun Spore-related tests to be run with: +`make check TESTS='Stun Spore'` -`GIVEN` initializes the parties, `PLAYER` and `OPPONENT` add a Pokémon to their respective parties. They can both accept a block which further customizes the Pokémon's stats, moves, item, ability, etc. +`GIVEN` initializes the parties, `PLAYER` and `OPPONENT` add a Pokémon to their respective parties. They can both accept a block which further customizes the Pokémon's stats, moves, item, ability, etc. -`WHEN` describes the turns, and `TURN` describes the choices made in a single turn. `MOVE` causes the player to use Stun Spore and adds the move to the Pokémon's moveset if an explicit Moves was not specified. -Pokémon that are not mentioned in a `TURN` use Celebrate. -The test runner rigs the RNG so that unless otherwise specified, moves always hit, never critical hit, always activate their secondary effects, and always roll the same damage modifier. +`WHEN` describes the turns, and `TURN` describes the choices made in a single turn. `MOVE` causes the player to use Stun Spore and adds the move to the Pokémon's moveset if an explicit Moves was not specified. +Pokémon that are not mentioned in a `TURN` use Celebrate. +The test runner rigs the RNG so that unless otherwise specified, moves always hit, never critical hit, always activate their secondary effects, and always roll the same damage modifier. -`SCENE` describes the player-visible output of the battle. In this case `ANIMATION` checks that the Stun Spore animation played, `MESSAGE` checks the paralysis message was shown, and `STATUS_ICON` checks that the opponent's HP bar shows a PRZ icon. +`SCENE` describes the player-visible output of the battle. In this case `ANIMATION` checks that the Stun Spore animation played, `MESSAGE` checks the paralysis message was shown, and `STATUS_ICON` checks that the opponent's HP bar shows a PRZ icon. ### Example 2 As a second example, to manually test that Stun Spore does not effect Grass-types you might: @@ -90,8 +90,8 @@ SINGLE_BATTLE_TEST("Stun Spore does not affect Grass-types") } } ``` -The `ASSUME` commands are documenting the reasons why Stun Spore does not affect Oddish, namely that Stun Spore is a powder move, and Oddish is a Grass-type. These `ASSUME` statements function similarly to the ones in `ASSUMPTIONS` but apply only to the one test. -NOT inverts the meaning of a `SCENE` check, so applying it to `ANIMATION` requires that the Stun Spore animation does not play. `MESSAGE` checks that the message was shown. +The `ASSUME` commands are documenting the reasons why Stun Spore does not affect Oddish, namely that Stun Spore is a powder move, and Oddish is a Grass-type. These `ASSUME` statements function similarly to the ones in `ASSUMPTIONS` but apply only to the one test. +NOT inverts the meaning of a `SCENE` check, so applying it to `ANIMATION` requires that the Stun Spore animation does not play. `MESSAGE` checks that the message was shown. The checks in `SCENE` are ordered, so together this says "The doesn't affect message is shown, and the Stun Spore animation does not play at any time before that". Normally you would only test one or the other, or even better, just `NOT STATUS_ICON(opponent, paralysis: TRUE);` to say that Oddish was not paralyzed without specifying the exact outputs which led to that. ### Example 3 @@ -131,9 +131,9 @@ SINGLE_BATTLE_TEST("Meditate raises Attack", s16 damage) } ``` -`PARAMETRIZE` causes a test to run multiple times, once per `PARAMETRIZE` block (e.g. once with `raiseAttack = FALSE` and once with `raiseAttack = TRUE`). -The `HP_BAR` command's `captureDamage` causes the change in HP to be stored in a variable, and the variable chosen is `results[i].damage`. -`results[i]` contains all the variables defined at the end of `SINGLE_BATTLE_TEST`, `i` is the current `PARAMETRIZE` index. +`PARAMETRIZE` causes a test to run multiple times, once per `PARAMETRIZE` block (e.g. once with `raiseAttack = FALSE` and once with `raiseAttack = TRUE`). +The `HP_BAR` command's `captureDamage` causes the change in HP to be stored in a variable, and the variable chosen is `results[i].damage`. +`results[i]` contains all the variables defined at the end of `SINGLE_BATTLE_TEST`, `i` is the current `PARAMETRIZE` index. `FINALLY` runs after the last parameter has finished, and uses `EXPECT_MUL_EQ` to check that the second battle deals 1.5× the damage of the first battle (with a small tolerance to account for rounding). You might notice that all the tests check the outputs the player could see rather than the internal battle state. e.g. the Meditate test could have used `gBattleMons[B_POSITION_OPPONENT_LEFT].hp` instead of using `HP_BAR` to capture the damage. This is a deliberate choice, by checking what the player can observe the tests are more robust to refactoring, e.g. if `gBattleMons` got moved into `gBattleStruct` then any test that used it would need to be updated. @@ -144,8 +144,8 @@ The overworld is not available, so it is only possible to test commands which do ## REFERENCE ### `ASSUME` -`ASSUME(cond)` -Causes the test to be skipped if `cond` is false. Used to document any prerequisites of the test, e.g. to test Burn reducing the Attack of a Pokémon we can observe the damage of a physical attack with and without the burn. To document that this test assumes the attack is physical we can use: +`ASSUME(cond)` +Causes the test to be skipped if `cond` is false. Used to document any prerequisites of the test, e.g. to test Burn reducing the Attack of a Pokémon we can observe the damage of a physical attack with and without the burn. To document that this test assumes the attack is physical we can use: `ASSUME(gMovesInfo[MOVE_WHATEVER].category == DAMAGE_CATEGORY_PHYSICAL);` ### `ASSUMPTIONS` @@ -164,16 +164,16 @@ ASSUMPTIONS ``` ### `SINGLE_BATTLE_TEST` -`SINGLE_BATTLE_TEST(name, results...)` and `DOUBLE_BATTLE_TEST(name, results...)` -Define single- and double- battles. The names should start with the name of the mechanic being tested so that it is easier to run all the related tests. `results` contains variable declarations to be placed into the `results` array which is available in tests using `PARAMETRIZE` commands. +`SINGLE_BATTLE_TEST(name, results...)` and `DOUBLE_BATTLE_TEST(name, results...)` +Define single- and double- battles. The names should start with the name of the mechanic being tested so that it is easier to run all the related tests. `results` contains variable declarations to be placed into the `results` array which is available in tests using `PARAMETRIZE` commands. The main differences for doubles are: - Move targets sometimes need to be explicit. - Instead of `player` and `opponent` there is `playerLeft`, `playerRight`, `opponentLeft`, and `opponentRight`. ### `AI_SINGLE_BATTLE_TEST` -`AI_SINGLE_BATTLE_TEST(name, results...)` and `AI_DOUBLE_BATTLE_TEST(name, results...)` +`AI_SINGLE_BATTLE_TEST(name, results...)` and `AI_DOUBLE_BATTLE_TEST(name, results...)` Define battles where opponent mons are controlled by AI, the same that runs -when battling regular Trainers. The flags for AI should be specified by the `AI_FLAGS` command. +when battling regular Trainers. The flags for AI should be specified by the `AI_FLAGS` command. The rules remain the same as with the `SINGLE` and `DOUBLE` battle tests with some differences: - opponent's action is specified by the `EXPECT_MOVE` / `EXPECT_SEND_OUT` / `EXPECT_SWITCH` commands - we don't control what opponent actually does, instead we make sure the opponent does what we expect it to do @@ -182,7 +182,7 @@ The rules remain the same as with the `SINGLE` and `DOUBLE` battle tests with so ### `KNOWN_FAILING` `KNOWN_FAILING;` -Marks a test as not passing due to a bug. If there is an issue number associated with the bug it should be included in a comment. If the test passes the developer will be notified to remove `KNOWN_FAILING`. +Marks a test as not passing due to a bug. If there is an issue number associated with the bug it should be included in a comment. If the test passes the developer will be notified to remove `KNOWN_FAILING`. For example: ``` SINGLE_BATTLE_TEST("Jump Kick has no recoil if no target") @@ -192,7 +192,7 @@ SINGLE_BATTLE_TEST("Jump Kick has no recoil if no target") } ``` ### `PARAMETRIZE` -`PARAMETERIZE { parameter; }` +`PARAMETERIZE { parameter; }` Runs a test multiple times. `i` will be set to which parameter is running, and `results` will contain an entry for each parameter, e.g.: ``` SINGLE_BATTLE_TEST("Blaze boosts Fire-type moves in a pinch", s16 damage) @@ -246,7 +246,7 @@ Contains the initial state of the parties before the battle. ## `RNGSeed` `RNGSeed(seed)` -Explicitly sets the RNG seed. Try to avoid using this because it is a very fragile tool. +Explicitly sets the RNG seed. Try to avoid using this because it is a very fragile tool. Example: ``` GIVEN { @@ -256,10 +256,10 @@ GIVEN { ``` ### `FLAG_SET` -`FLAG_SET(flagId)` -Sets the specified flag. Can currently only set one flag at a time. -Cleared between parameters and at the end of the test. -Example: +`FLAG_SET(flagId)` +Sets the specified flag. Can currently only set one flag at a time. +Cleared between parameters and at the end of the test. +Example: ``` GIVEN { FLAG_SET(FLAG_SYS_EXAMPLE_FLAG); @@ -268,8 +268,8 @@ GIVEN { ``` ### `PLAYER` and `OPPONENT` -`PLAYER(species)` and `OPPONENT(species` -Adds the species to the player's or opponent's party respectively. +`PLAYER(species)` and `OPPONENT(species` +Adds the species to the player's or opponent's party respectively. The Pokémon can be further customized with the following functions: - `Gender(MON_MALE | MON_FEMALE)` - `Nature(nature)` @@ -280,14 +280,14 @@ The Pokémon can be further customized with the following functions: - `Moves(moves...)` - `Friendship(friendship)` - `Status1(status1)` -For example to create a level 42 Wobbuffet that is poisoned: -`PLAYER(SPECIES_WOBBUFFET) { Level(42); Status1(STATUS1_POISON); }` -**Note if Speed is specified for any Pokémon then it must be specified for all Pokémon.** +For example to create a level 42 Wobbuffet that is poisoned: +`PLAYER(SPECIES_WOBBUFFET) { Level(42); Status1(STATUS1_POISON); }` +**Note if Speed is specified for any Pokémon then it must be specified for all Pokémon.** **Note if Moves is specified then MOVE will not automatically add moves to the moveset.** ### `AI_FLAGS` -`AI_FLAGS(flags)` -Specifies which AI flags are run during the test. Has use only for AI tests. +`AI_FLAGS(flags)` +Specifies which AI flags are run during the test. Has use only for AI tests. The most common combination is `AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT)` which is the general 'smart' AI. ### `WHEN` @@ -300,8 +300,8 @@ The most common combination is `AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_ Contains the choices that battlers make during the battle. ### `TURN` -`TURN { ... }` -Groups the choices made by the battlers on a single turn. If Speeds have not been explicitly specified then the order of the `MOVE` commands in the `TURN` will be used to infer the Speeds of the Pokémon, e.g.: +`TURN { ... }` +Groups the choices made by the battlers on a single turn. If Speeds have not been explicitly specified then the order of the `MOVE` commands in the `TURN` will be used to infer the Speeds of the Pokémon, e.g.: ``` // player's speed will be greater than opponent's speed. TURN { MOVE(player, MOVE_SPLASH); MOVE(opponent, MOVE_SPLASH); } @@ -311,7 +311,7 @@ Groups the choices made by the battlers on a single turn. If Speeds have not bee The inference process is naive, if your test contains anything that modifies the speed of a battler you should specify them explicitly. ### `MOVE` -`MOVE(battler, move | moveSlot:, [megaEvolve:], [hit:], [criticalHit:], [target:], [allowed:], [WITH_RNG(tag, value])` +`MOVE(battler, move | moveSlot:, [megaEvolve:], [hit:], [criticalHit:], [target:], [allowed:], [WITH_RNG(tag, value])` Used when the battler chooses Fight. Either the move ID (e.g. `MOVE_TACKLE` or move slot must be specified. - `megaEvolve: TRUE` causes the battler to Mega Evolve if able - `hit: FALSE` causes the move to miss @@ -325,35 +325,35 @@ Used when the battler chooses Fight. Either the move ID (e.g. `MOVE_TACKLE` or m If the battler does not have an explicit Moves specified the moveset will be populated based on the `MOVE`s it uses. ### `FORCED_MOVE` -`FORCED_MOVE(battler)` +`FORCED_MOVE(battler)` Used when the battler chooses Fight and then their move is chosen for them, e.g. when affected by Encore. ``` FORCED_MOVE(player); ``` ### `SWITCH` -`SWITCH(battler, partyIndex)` +`SWITCH(battler, partyIndex)` Used when the battler chooses Switch. ``` SWITCH(player, 1); ``` ### `SKIP_TURN` -`SKIP_TURN(battler)` +`SKIP_TURN(battler)` Used when the battler cannot choose an action, e.g. when locked into Thrash. ``` SKIP_TURN(player); ``` ### `SEND_OUT` -`SEND_OUT(battler, partyIndex)` +`SEND_OUT(battler, partyIndex)` Used when the battler chooses to switch to another Pokémon but not via Switch, e.g. after fainting or due to a U-turn. ``` SEND_OUT(player, 1); ``` ### `USE_ITEM` -`USE_ITEM(battler, itemId, [partyIndex:], [move:])` +`USE_ITEM(battler, itemId, [partyIndex:], [move:])` Used when the battler chooses to use an item from the Bag. The item ID (e.g. ITEM_POTION) must be specified, and party index and move slot if applicable, e.g: ``` USE_ITEM(player, ITEM_X_ATTACK); @@ -378,15 +378,15 @@ Contains an abridged description of the UI during the `THEN`. The order of the d ``` ### `ABILITY_POPUP` -`ABILITY_POPUP(battler, [ability])` -Causes the test to fail if the battler's ability pop-up is not shown. +`ABILITY_POPUP(battler, [ability])` +Causes the test to fail if the battler's ability pop-up is not shown. If specified, ability is the ability shown in the pop-up. ``` ABILITY_POPUP(opponent, ABILITY_MOLD_BREAKER); ``` ### `ANIMATION` -`ANIMATION(type, animId, [battler], [target:])` +`ANIMATION(type, animId, [battler], [target:])` Causes the test to fail if the animation does not play. A common use of this command is to check if a move was successful, e.g.: ``` ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); @@ -394,7 +394,7 @@ Causes the test to fail if the animation does not play. A common use of this com `target` can only be specified for `ANIM_TYPE_MOVE`. ### `EXPERIENCE_BAR` -`EXPERIENCE_BAR(battler, [exp: | captureGainedExp:])` +`EXPERIENCE_BAR(battler, [exp: | captureGainedExp:])` If `exp:` is used, causes the test to fail if that amount of experience is not gained, e.g.: ``` EXPERIENCE_BAR(player, exp: 0); @@ -404,11 +404,11 @@ If `captureGainedExp:` is used, causes the test to fail if the Experience bar do u32 exp; EXPERIENCE_BAR(player, captureGainedExp: &exp); ``` -If none of the above are used, causes the test to fail if the Exp does not change at all. +If none of the above are used, causes the test to fail if the Exp does not change at all. **Please note that due to nature of tests, this command is only usable in `WILD_BATTLE_TEST` and will fail elsewhere.** ### `HP_BAR` -`HP_BAR(battler, [damage: | hp: | captureDamage: | captureHP:])` +`HP_BAR(battler, [damage: | hp: | captureDamage: | captureHP:])` If `hp:` or `damage:` are used, causes the test to fail if that amount of damage is not dealt, e.g.: ``` HP_BAR(player, hp: 0); @@ -422,9 +422,9 @@ If `captureDamage:` or `captureHP:` are used, causes the test to fail if the HP If none of the above are used, causes the test to fail if the HP does not change at all. ### MESSAGE -`MESSAGE(pattern)` -Causes the test to fail if the message in pattern is not displayed. -Spaces in pattern match newlines (\n, \l, and \p) in the message. +`MESSAGE(pattern)` +Causes the test to fail if the message in pattern is not displayed. +Spaces in pattern match newlines (\n, \l, and \p) in the message. Often used to check that a battler took its turn but it failed, e.g.: ``` MESSAGE("Wobbuffet used Dream Eater!"); @@ -432,7 +432,7 @@ Often used to check that a battler took its turn but it failed, e.g.: ``` ### `STATUS_ICON` -`STATUS_ICON(battler, status1 | none: | sleep: | poison: | burn: | freeze: | paralysis:, badPoison:)` +`STATUS_ICON(battler, status1 | none: | sleep: | poison: | burn: | freeze: | paralysis:, badPoison:)` Causes the test to fail if the battler's status is not changed to the specified status. ``` STATUS_ICON(player, badPoison: TRUE); @@ -447,7 +447,7 @@ If the expected status icon is parametrized the corresponding `STATUS1` constant ``` ### `NOT` -`NOT sceneCommand` +`NOT sceneCommand` Causes the test to fail if the `SCENE` command succeeds before the following command succeeds. ``` // Our Wobbuffet does not Celebrate before the foe's. @@ -519,27 +519,27 @@ Contains code to run after the battle has finished. If the test is using `PARAME Contains checks to run after all `PARAMETERIZE` commands have run. Prefer to write your checks in `THEN` where possible, because a failure in `THEN` will be tagged with which parameter it corresponds to. ### `EXPECT` -`EXPECT(cond)` +`EXPECT(cond)` Causes the test to fail if `cond` is false. ### `EXPECT_XX` -`EXPECT_EQ(a, b)` -`a == b` +`EXPECT_EQ(a, b)` +`a == b` -`EXPECT_NE(a, b)` -`a != b` +`EXPECT_NE(a, b)` +`a != b` -`EXPECT_LT(a, b)` -`a < b` +`EXPECT_LT(a, b)` +`a < b` -`EXPECT_LE(a, b)` -`a <= b` +`EXPECT_LE(a, b)` +`a <= b` -`EXPECT_GT(a, b)` -`a > b` +`EXPECT_GT(a, b)` +`a > b` -`EXPECT_GE(a, b)` -`a >= b` +`EXPECT_GE(a, b)` +`a >= b` Causes the test to fail if a and b compare incorrectly, e.g. ``` @@ -547,7 +547,7 @@ Causes the test to fail if a and b compare incorrectly, e.g. ``` ### `EXPECT_MUL_EQ` -`EXPECT_MUL_EQ(a, m, b)` +`EXPECT_MUL_EQ(a, m, b)` Causes the test to fail if `a*m != b` (within a threshold), e.g. ``` // Expect results[0].damage * 1.5 == results[1].damage. @@ -557,7 +557,7 @@ Causes the test to fail if a and b compare incorrectly, e.g. ## Overworld Command Reference ### `OVERWORLD_SCRIPT` -`OVERWORLD_SCRIPT(instructions...)` +`OVERWORLD_SCRIPT(instructions...)` Returns a pointer to a compiled overworld script. Cannot be used to initialize global `const` data, although the pointer **IS** to `const` data. Note that each script command must be followed by a ;, e.g.: ``` @@ -568,7 +568,7 @@ const u8 *myScript = OVERWORLD_SCRIPT( ``` ### `RUN_OVERWORLD_SCRIPT` -`RUN_OVERWORLD_SCRIPT(instructions...)` +`RUN_OVERWORLD_SCRIPT(instructions...)` Runs an overworld script in the immediate script context, which means that commands like `waitstate` are not supported. ``` RUN_OVERWORLD_SCRIPT( diff --git a/docs/how_to_trainer_class.md b/docs/how_to_trainer_class.md index a47cbe19c5..3ce0217c28 100644 --- a/docs/how_to_trainer_class.md +++ b/docs/how_to_trainer_class.md @@ -12,13 +12,13 @@ * [Usage](#usage) ## Quick Summary -(Page contains out of date information, [new instructions for Sprites here](https://github.com/rh-hideout/pokeemerald-expansion/pull/3597).) +(Page contains out of date information, [new instructions for Sprites here](https://github.com/rh-hideout/pokeemerald-expansion/pull/3597).) If you've done this before and just need a quick lookup, here's what files you need: 1. GFX into [graphics/trainers/front_pics](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/graphics/trainers/front_pics) 2. Palette into [graphics/trainers/palettes](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/graphics/trainers/palettes) 3. Register sprites to [include/graphics.h](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/graphics.h) 4. Point game to where graphic files are found: [src/data/graphics/trainers](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/graphics/trainers.h) -5. Add animation to: [src/data/trainer_graphics/front_pic_anims.h](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/trainer_graphics/front_pic_anims.h) +5. Add animation to: [src/data/trainer_graphics/front_pic_anims.h](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/trainer_graphics/front_pic_anims.h) 6. Add the trainer to all three structs in: [src/data/trainer_graphics/front_pic_table.h](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/trainer_graphics/front_pic_table.h) 7. Add trainer to [include/constants/trainers.h](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/constants/trainers.h) diff --git a/docs/local_mdbook/index.md b/docs/local_mdbook/index.md new file mode 100644 index 0000000000..ef362dc45f --- /dev/null +++ b/docs/local_mdbook/index.md @@ -0,0 +1,2 @@ +## Running documentation website locally +- [Ubuntu WSL1/WSL2](/docs/local_mdbook/ubuntu_WSL.md) diff --git a/docs/local_mdbook/ubuntu_WSL.md b/docs/local_mdbook/ubuntu_WSL.md new file mode 100644 index 0000000000..88ee2468e6 --- /dev/null +++ b/docs/local_mdbook/ubuntu_WSL.md @@ -0,0 +1,51 @@ +Note: For further information beyond this very basic guide, please visit mdBook's [official documentation](https://rust-lang.github.io/mdBook/). + +## Running documentation website locally (Ubuntu WSL1/WSL2) +### Previous Requirements: +- Option 1: Install via Rust toolchain + - Install Rust toolchain if you don't have it via the `sudo apt install cargo` command. + - Install mdBook via the `cargo install mdbook` command. Once finished, this message will pop up, with {USER} being your Ubuntu + ``` + warning: be sure to add `/home/{USER}/.cargo/bin` to your PATH to be able to run the installed binaries + ``` + - Add `/home/{USER}/.cargo/bin` to your PATH (with {USER} being the Ubuntu username.) + - Run command `nano ~/.profile` to edit the file. + - Add the following lines, ***replacing {USER} with your Linux username.*** + ```diff + # set PATH so it includes user's private bin if it exists + if [ -d "$HOME/bin" ] ; then + PATH="$HOME/bin:$PATH" + fi + + # set PATH so it includes user's private bin if it exists + if [ -d "$HOME/.local/bin" ] ; then + PATH="$HOME/.local/bin:$PATH" + fi + + +# set PATH so it includes cargo bin if it exists + +if [ -d "/home/{USER}/.cargo/bin" ] ; then + + PATH="/home/{USER}/.cargo/bin:$PATH" + +fi + ``` + - Run the `source ~/.profile` command to refresh the path in the current session. +- Option 2: Install downloaded binaries directly + - TODO: Add documentation of this process. + +### Running the website +- Navigate to the `docs` folder on the repository. +- Run `mdbook serve`. Once started, you may now open the website on your browser by going to `http://127.0.0.1:3000`. +- Every change done to the `docs` folder will be reflected with an automatic refresh. +- To stop the server and go back to the terminal, press `Ctrl + C`. + +### Modifying the website +- The navigation menu on the left is handled by `docs/SUMMARY.md`. Every file added needs to be added somewhere here in order to become visible, otherwise you'll get a 404 error. +- Any Markdown files (.md extension) added to the `docs/` directory will automatically be read by mdBook. +- To add Markdown files that are not in the `docs/` directory, you may create an empty `.md` file and add the following ***without the "----"***: + ```md + {{ ----#include ../INSTALL.md}}` + ``` + This will include the `INSTALL.md` Markdown file from the root directory. + +Once you're set up, you can now check your changes before pushing them to your repo! :D + +We hope that this will make it easier for users to contribute to the documentation :) diff --git a/gflib/sprite.c b/gflib/sprite.c index 7823888cb5..9ba1662c9d 100644 --- a/gflib/sprite.c +++ b/gflib/sprite.c @@ -52,7 +52,6 @@ static void SortSprites(u32 *spritePriorities, s32 n); static u32 CreateSpriteAt(u32 index, const struct SpriteTemplate *template, s16 x, s16 y, u32 subpriority); static void ResetOamMatrices(void); static void ResetSprite(struct Sprite *sprite); -static void RequestSpriteFrameImageCopy(u16 index, u16 tileNum, const struct SpriteFrameImage *images); static void ResetAllSprites(void); static void BeginAnim(struct Sprite *sprite); static void ContinueAnim(struct Sprite *sprite); @@ -75,7 +74,6 @@ static void AffineAnimCmd_end(u8 matrixNum, struct Sprite *sprite); static void AffineAnimCmd_frame(u8 matrixNum, struct Sprite *sprite); static void CopyOamMatrix(u8 destMatrixIndex, struct OamMatrix *srcMatrix); static u8 GetSpriteMatrixNum(struct Sprite *sprite); -static void SetSpriteOamFlipBits(struct Sprite *sprite, u8 hFlip, u8 vFlip); static void AffineAnimStateRestartAnim(u8 matrixNum); static void AffineAnimStateStartAnim(u8 matrixNum, u8 animNum); static void AffineAnimStateReset(u8 matrixNum); diff --git a/gflib/sprite.h b/gflib/sprite.h index 6a3084add2..937ed42ced 100644 --- a/gflib/sprite.h +++ b/gflib/sprite.h @@ -331,5 +331,7 @@ u8 SpriteTileAllocBitmapOp(u16 bit, u8 op); void ClearSpriteCopyRequests(void); void ResetAffineAnimData(void); u32 GetSpanPerImage(u32 shape, u32 size); +void RequestSpriteFrameImageCopy(u16 index, u16 tileNum, const struct SpriteFrameImage *images); +void SetSpriteOamFlipBits(struct Sprite *sprite, u8 hFlip, u8 vFlip); #endif //GUARD_SPRITE_H diff --git a/graphics/battle_anims/sprites/beam.png b/graphics/battle_anims/sprites/beam.png new file mode 100644 index 0000000000..cce0a23a4c Binary files /dev/null and b/graphics/battle_anims/sprites/beam.png differ diff --git a/graphics/battle_anims/sprites/blood_moon.png b/graphics/battle_anims/sprites/blood_moon.png new file mode 100644 index 0000000000..014c7bd445 Binary files /dev/null and b/graphics/battle_anims/sprites/blood_moon.png differ diff --git a/graphics/battle_anims/sprites/purple_chain.png b/graphics/battle_anims/sprites/purple_chain.png new file mode 100644 index 0000000000..8c46b34aeb Binary files /dev/null and b/graphics/battle_anims/sprites/purple_chain.png differ diff --git a/graphics/battle_anims/sprites/red_explosion.png b/graphics/battle_anims/sprites/red_explosion.png new file mode 100644 index 0000000000..2c974db5c9 Binary files /dev/null and b/graphics/battle_anims/sprites/red_explosion.png differ diff --git a/graphics/pokemon/absol/mega/front.png b/graphics/pokemon/absol/mega/front.png index e7656154da..bc89ac2de0 100644 Binary files a/graphics/pokemon/absol/mega/front.png and b/graphics/pokemon/absol/mega/front.png differ diff --git a/graphics/pokemon/aerodactyl/mega/front.png b/graphics/pokemon/aerodactyl/mega/front.png index 86d51181f0..c581404a89 100644 Binary files a/graphics/pokemon/aerodactyl/mega/front.png and b/graphics/pokemon/aerodactyl/mega/front.png differ diff --git a/graphics/pokemon/archen/overworld.png b/graphics/pokemon/archen/overworld.png index e25f19ba7f..6dce497d6d 100644 Binary files a/graphics/pokemon/archen/overworld.png and b/graphics/pokemon/archen/overworld.png differ diff --git a/graphics/pokemon/archeops/overworld.png b/graphics/pokemon/archeops/overworld.png index 8a8a23a4ed..6d8faa6597 100644 Binary files a/graphics/pokemon/archeops/overworld.png and b/graphics/pokemon/archeops/overworld.png differ diff --git a/graphics/pokemon/articuno/galarian/overworld.png b/graphics/pokemon/articuno/galarian/overworld.png index 734f4802d9..51e46babdb 100644 Binary files a/graphics/pokemon/articuno/galarian/overworld.png and b/graphics/pokemon/articuno/galarian/overworld.png differ diff --git a/graphics/pokemon/articuno/galarian/overworld_normal.pal b/graphics/pokemon/articuno/galarian/overworld_normal.pal index 4bf32062c4..a341d1c098 100644 --- a/graphics/pokemon/articuno/galarian/overworld_normal.pal +++ b/graphics/pokemon/articuno/galarian/overworld_normal.pal @@ -3,17 +3,17 @@ JASC-PAL 16 60 184 151 0 0 0 -21 12 31 -0 0 0 +120 200 248 +160 224 248 102 69 138 212 190 233 149 111 190 41 28 44 -233 232 233 +232 204 232 190 163 198 162 126 172 -120 200 248 -160 224 248 +203 181 209 +255 255 255 56 56 56 24 24 24 -15 15 15 +0 0 0 diff --git a/graphics/pokemon/articuno/galarian/overworld_shiny.pal b/graphics/pokemon/articuno/galarian/overworld_shiny.pal index 4bf32062c4..590f0cc88a 100644 --- a/graphics/pokemon/articuno/galarian/overworld_shiny.pal +++ b/graphics/pokemon/articuno/galarian/overworld_shiny.pal @@ -3,17 +3,17 @@ JASC-PAL 16 60 184 151 0 0 0 -21 12 31 -0 0 0 -102 69 138 -212 190 233 -149 111 190 +79 185 255 +110 216 255 +40 64 128 +96 144 216 +40 96 184 41 28 44 -233 232 233 -190 163 198 -162 126 172 -120 200 248 -160 224 248 -56 56 56 -24 24 24 -15 15 15 +153 211 247 +104 192 248 +83 156 230 +179 226 255 +227 248 255 +224 240 255 +181 209 230 +255 255 255 diff --git a/graphics/pokemon/basculin/blue_striped/overworld.png b/graphics/pokemon/basculin/blue_striped/overworld.png index b8f0a34583..b900662eaf 100644 Binary files a/graphics/pokemon/basculin/blue_striped/overworld.png and b/graphics/pokemon/basculin/blue_striped/overworld.png differ diff --git a/graphics/pokemon/blitzle/overworld.png b/graphics/pokemon/blitzle/overworld.png index 09a594f17b..67c7ae568e 100644 Binary files a/graphics/pokemon/blitzle/overworld.png and b/graphics/pokemon/blitzle/overworld.png differ diff --git a/graphics/pokemon/blitzle/overworld_normal.pal b/graphics/pokemon/blitzle/overworld_normal.pal index cd08b136eb..1dfabc67aa 100644 --- a/graphics/pokemon/blitzle/overworld_normal.pal +++ b/graphics/pokemon/blitzle/overworld_normal.pal @@ -10,7 +10,7 @@ JASC-PAL 0 0 0 200 200 200 0 168 216 -0 0 0 +248 224 88 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/blitzle/overworld_shiny.pal b/graphics/pokemon/blitzle/overworld_shiny.pal index 422cd57da4..56c8507e85 100644 --- a/graphics/pokemon/blitzle/overworld_shiny.pal +++ b/graphics/pokemon/blitzle/overworld_shiny.pal @@ -10,7 +10,7 @@ JASC-PAL 0 0 0 200 200 200 24 232 104 -0 0 0 +248 224 88 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/bombirdier/front.png b/graphics/pokemon/bombirdier/front.png index 97159715f2..b8aa83644b 100644 Binary files a/graphics/pokemon/bombirdier/front.png and b/graphics/pokemon/bombirdier/front.png differ diff --git a/graphics/pokemon/bounsweet/back.png b/graphics/pokemon/bounsweet/back.png index cd2a5401b5..c6ddb69f5d 100644 Binary files a/graphics/pokemon/bounsweet/back.png and b/graphics/pokemon/bounsweet/back.png differ diff --git a/graphics/pokemon/bounsweet/overworld.png b/graphics/pokemon/bounsweet/overworld.png index b3920bd8f2..c64dd42ad1 100644 Binary files a/graphics/pokemon/bounsweet/overworld.png and b/graphics/pokemon/bounsweet/overworld.png differ diff --git a/graphics/pokemon/bounsweet/overworld_shiny.pal b/graphics/pokemon/bounsweet/overworld_shiny.pal index c97f75961d..769d9abd9e 100644 --- a/graphics/pokemon/bounsweet/overworld_shiny.pal +++ b/graphics/pokemon/bounsweet/overworld_shiny.pal @@ -2,11 +2,11 @@ JASC-PAL 0100 16 255 255 255 -225 232 232 +247 240 184 216 192 248 232 200 0 160 128 240 -136 153 149 +200 192 128 224 104 128 200 112 152 176 64 104 diff --git a/graphics/pokemon/bruxish/overworld.png b/graphics/pokemon/bruxish/overworld.png index 18b2325a80..04757426e6 100644 Binary files a/graphics/pokemon/bruxish/overworld.png and b/graphics/pokemon/bruxish/overworld.png differ diff --git a/graphics/pokemon/bruxish/overworld_shiny.pal b/graphics/pokemon/bruxish/overworld_shiny.pal index 624b47c64a..7de5796528 100644 --- a/graphics/pokemon/bruxish/overworld_shiny.pal +++ b/graphics/pokemon/bruxish/overworld_shiny.pal @@ -5,13 +5,13 @@ JASC-PAL 248 244 244 232 208 136 225 220 64 -224 216 208 +248 248 248 196 203 194 200 160 80 232 56 40 104 208 152 59 105 101 -140 82 158 +56 160 104 75 74 26 56 160 104 105 44 76 diff --git a/graphics/pokemon/crustle/overworld_normal.pal b/graphics/pokemon/crustle/overworld_normal.pal index fe051f639a..8d988e808a 100644 --- a/graphics/pokemon/crustle/overworld_normal.pal +++ b/graphics/pokemon/crustle/overworld_normal.pal @@ -8,10 +8,10 @@ JASC-PAL 128 96 64 224 192 64 192 128 0 -229 229 247 96 32 0 -224 128 64 +229 229 247 192 96 64 +224 128 64 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/crustle/overworld_shiny.pal b/graphics/pokemon/crustle/overworld_shiny.pal index 3104d02aba..c1030a0ad3 100644 --- a/graphics/pokemon/crustle/overworld_shiny.pal +++ b/graphics/pokemon/crustle/overworld_shiny.pal @@ -8,10 +8,10 @@ JASC-PAL 96 88 80 176 192 72 48 40 24 -229 229 247 48 40 24 -136 152 72 -96 104 48 +229 229 247 +137 153 67 +179 206 83 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/cursola/front.png b/graphics/pokemon/cursola/front.png index 2e40363812..5dd4cea7de 100644 Binary files a/graphics/pokemon/cursola/front.png and b/graphics/pokemon/cursola/front.png differ diff --git a/graphics/pokemon/cursola/shiny.pal b/graphics/pokemon/cursola/shiny.pal index 552b1077fc..9259843950 100644 --- a/graphics/pokemon/cursola/shiny.pal +++ b/graphics/pokemon/cursola/shiny.pal @@ -2,16 +2,16 @@ JASC-PAL 0100 16 152 208 160 -184 184 184 +145 145 145 248 240 248 120 120 120 224 216 224 208 200 208 -144 136 144 +92 92 92 184 176 184 -224 96 144 +192 96 224 248 248 248 -248 160 192 +221 173 237 16 16 16 72 72 72 56 56 56 diff --git a/graphics/pokemon/darmanitan/galarian/overworld.png b/graphics/pokemon/darmanitan/galarian/overworld.png index dda43e6e07..f6d78555e5 100644 Binary files a/graphics/pokemon/darmanitan/galarian/overworld.png and b/graphics/pokemon/darmanitan/galarian/overworld.png differ diff --git a/graphics/pokemon/darmanitan/galarian/overworld_normal.pal b/graphics/pokemon/darmanitan/galarian/overworld_normal.pal index f573721897..2036748fc6 100644 --- a/graphics/pokemon/darmanitan/galarian/overworld_normal.pal +++ b/graphics/pokemon/darmanitan/galarian/overworld_normal.pal @@ -6,14 +6,14 @@ JASC-PAL 167 167 167 215 215 215 10 34 40 -93 188 210 +40 192 168 0 0 0 120 155 209 79 111 160 255 255 255 -10 10 10 -11 11 11 -12 12 12 -13 13 13 -14 14 14 -15 15 15 +255 255 255 +255 255 255 +255 255 255 +255 255 255 +255 255 255 +255 255 255 diff --git a/graphics/pokemon/darmanitan/galarian/overworld_shiny.pal b/graphics/pokemon/darmanitan/galarian/overworld_shiny.pal index f573721897..e61043b14e 100644 --- a/graphics/pokemon/darmanitan/galarian/overworld_shiny.pal +++ b/graphics/pokemon/darmanitan/galarian/overworld_shiny.pal @@ -6,14 +6,14 @@ JASC-PAL 167 167 167 215 215 215 10 34 40 -93 188 210 +72 160 216 0 0 0 -120 155 209 -79 111 160 +190 224 117 +74 105 37 +255 255 255 +255 255 255 +255 255 255 +255 255 255 +255 255 255 +255 255 255 255 255 255 -10 10 10 -11 11 11 -12 12 12 -13 13 13 -14 14 14 -15 15 15 diff --git a/graphics/pokemon/darumaka/galarian/back.png b/graphics/pokemon/darumaka/galarian/back.png index 94115f536a..8aef0d7756 100644 Binary files a/graphics/pokemon/darumaka/galarian/back.png and b/graphics/pokemon/darumaka/galarian/back.png differ diff --git a/graphics/pokemon/darumaka/galarian/overworld_shiny.pal b/graphics/pokemon/darumaka/galarian/overworld_shiny.pal index 44a066b5bc..409dc17fba 100644 --- a/graphics/pokemon/darumaka/galarian/overworld_shiny.pal +++ b/graphics/pokemon/darumaka/galarian/overworld_shiny.pal @@ -5,15 +5,15 @@ JASC-PAL 10 34 40 36 36 36 0 0 0 -93 188 210 +120 203 214 215 215 215 -56 134 152 -29 45 70 +32 146 160 +31 51 8 128 128 128 -120 155 209 -79 111 160 +182 212 119 +120 184 40 167 167 167 -55 72 127 +64 104 16 +255 255 255 +40 93 104 255 255 255 -80 108 152 -15 15 15 diff --git a/graphics/pokemon/darumaka/galarian/shiny.pal b/graphics/pokemon/darumaka/galarian/shiny.pal index 21bd015c8a..f7748fd8d4 100644 --- a/graphics/pokemon/darumaka/galarian/shiny.pal +++ b/graphics/pokemon/darumaka/galarian/shiny.pal @@ -2,11 +2,11 @@ JASC-PAL 0100 16 152 208 160 -40 104 96 +40 93 104 16 16 16 -40 192 168 -104 232 208 -32 160 136 +40 170 192 +104 218 232 +32 146 160 184 184 192 232 232 224 64 104 16 diff --git a/graphics/pokemon/diancie/mega/back.png b/graphics/pokemon/diancie/mega/back.png index cb9a177a0d..3816c40d78 100644 Binary files a/graphics/pokemon/diancie/mega/back.png and b/graphics/pokemon/diancie/mega/back.png differ diff --git a/graphics/pokemon/diancie/mega/front.png b/graphics/pokemon/diancie/mega/front.png index ef48adeebd..73f34c79c9 100644 Binary files a/graphics/pokemon/diancie/mega/front.png and b/graphics/pokemon/diancie/mega/front.png differ diff --git a/graphics/pokemon/diancie/mega/normal.pal b/graphics/pokemon/diancie/mega/normal.pal index 0d9dd14457..d7bca64866 100644 --- a/graphics/pokemon/diancie/mega/normal.pal +++ b/graphics/pokemon/diancie/mega/normal.pal @@ -2,18 +2,18 @@ JASC-PAL 0100 16 152 208 160 -144 80 120 -16 16 16 -216 96 160 -248 200 216 -248 248 248 -232 160 176 -72 64 104 -168 160 208 -120 112 152 -224 40 72 -240 208 104 -224 216 224 -192 208 208 -112 136 136 -248 248 248 +89 80 89 +115 115 115 +166 58 112 +217 85 69 +255 229 102 +128 115 128 +217 87 152 +179 161 179 +242 242 242 +242 145 178 +24 24 24 +255 204 217 +227 219 224 +191 191 191 +255 249 251 diff --git a/graphics/pokemon/diancie/mega/shiny.pal b/graphics/pokemon/diancie/mega/shiny.pal index f221fb1d59..d69f1886bc 100644 --- a/graphics/pokemon/diancie/mega/shiny.pal +++ b/graphics/pokemon/diancie/mega/shiny.pal @@ -2,18 +2,18 @@ JASC-PAL 0100 16 152 208 160 -144 80 120 -16 16 16 -216 96 160 -248 200 216 -248 248 248 -232 160 176 -48 48 48 -136 136 136 -88 88 88 -224 40 72 -240 208 104 -224 216 224 -168 48 104 -112 40 72 -224 112 160 +62 60 64 +140 45 99 +166 58 112 +230 85 121 +255 229 102 +99 90 99 +217 87 152 +140 125 140 +254 92 155 +242 145 178 +24 24 24 +255 204 217 +194 174 189 +194 72 133 +232 220 228 diff --git a/graphics/pokemon/dwebble/overworld.png b/graphics/pokemon/dwebble/overworld.png index fe33f3a71b..41e57f9a16 100644 Binary files a/graphics/pokemon/dwebble/overworld.png and b/graphics/pokemon/dwebble/overworld.png differ diff --git a/graphics/pokemon/escavalier/overworld.png b/graphics/pokemon/escavalier/overworld.png index 340131a534..deb3cb0738 100644 Binary files a/graphics/pokemon/escavalier/overworld.png and b/graphics/pokemon/escavalier/overworld.png differ diff --git a/graphics/pokemon/excadrill/overworld_shiny.pal b/graphics/pokemon/excadrill/overworld_shiny.pal index 4879340ef8..49918df388 100644 --- a/graphics/pokemon/excadrill/overworld_shiny.pal +++ b/graphics/pokemon/excadrill/overworld_shiny.pal @@ -8,7 +8,7 @@ JASC-PAL 176 64 96 152 152 192 75 81 113 -78 140 154 +60 91 97 78 140 154 5 5 5 201 206 220 diff --git a/graphics/pokemon/farfetchd/galarian/overworld.png b/graphics/pokemon/farfetchd/galarian/overworld.png index 343ece6bd6..bde1b5b7ec 100644 Binary files a/graphics/pokemon/farfetchd/galarian/overworld.png and b/graphics/pokemon/farfetchd/galarian/overworld.png differ diff --git a/graphics/pokemon/farfetchd/galarian/overworld_normal.pal b/graphics/pokemon/farfetchd/galarian/overworld_normal.pal index 0a555549b1..3df22685d9 100644 --- a/graphics/pokemon/farfetchd/galarian/overworld_normal.pal +++ b/graphics/pokemon/farfetchd/galarian/overworld_normal.pal @@ -10,7 +10,7 @@ JASC-PAL 238 234 255 49 89 41 255 202 49 -0 0 0 +213 210 197 65 117 57 57 48 49 82 68 65 diff --git a/graphics/pokemon/farfetchd/galarian/overworld_shiny.pal b/graphics/pokemon/farfetchd/galarian/overworld_shiny.pal index 0a555549b1..2d02e605e7 100644 --- a/graphics/pokemon/farfetchd/galarian/overworld_shiny.pal +++ b/graphics/pokemon/farfetchd/galarian/overworld_shiny.pal @@ -4,16 +4,16 @@ JASC-PAL 57 153 197 0 0 0 156 161 115 -180 174 156 +200 176 112 180 145 41 -115 93 90 +128 96 96 238 234 255 49 89 41 255 202 49 -0 0 0 -65 117 57 -57 48 49 -82 68 65 213 210 197 +65 117 57 +72 56 64 +96 72 80 +240 216 176 24 20 16 41 44 41 diff --git a/graphics/pokemon/garganacl/back.png b/graphics/pokemon/garganacl/back.png index d8590c6ce0..09b120f72f 100644 Binary files a/graphics/pokemon/garganacl/back.png and b/graphics/pokemon/garganacl/back.png differ diff --git a/graphics/pokemon/garganacl/front.png b/graphics/pokemon/garganacl/front.png index 416f535b35..d983a91346 100644 Binary files a/graphics/pokemon/garganacl/front.png and b/graphics/pokemon/garganacl/front.png differ diff --git a/graphics/pokemon/garganacl/normal.pal b/graphics/pokemon/garganacl/normal.pal index 2acd11e3b9..da3c63de41 100644 --- a/graphics/pokemon/garganacl/normal.pal +++ b/graphics/pokemon/garganacl/normal.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -153 211 165 -179 179 179 -217 217 217 -242 242 242 -138 138 138 -77 50 38 -148 104 90 +156 213 164 +123 123 123 +197 180 189 +255 255 255 +82 82 82 +148 98 90 +139 115 98 +197 148 123 +8 8 8 +65 49 41 +98 82 74 +238 139 24 +246 230 24 +90 74 57 +230 213 205 0 0 0 -102 61 44 -195 146 123 -245 147 45 -251 242 54 -46 43 40 -93 86 80 -220 191 179 -145 131 122 diff --git a/graphics/pokemon/garganacl/shiny.pal b/graphics/pokemon/garganacl/shiny.pal index 0b0979dd27..ea99f676a1 100644 --- a/graphics/pokemon/garganacl/shiny.pal +++ b/graphics/pokemon/garganacl/shiny.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -153 211 165 -161 104 55 -214 153 99 -237 173 116 -128 81 41 -77 50 38 -148 104 90 +156 213 164 +123 98 65 +189 148 106 +230 172 139 +90 57 49 +148 98 90 +139 115 98 +197 148 123 +8 8 8 +65 49 41 +98 82 74 +238 139 24 +246 230 24 +90 74 57 +230 213 205 0 0 0 -102 61 44 -195 146 123 -245 147 45 -251 242 54 -46 43 40 -93 86 80 -220 191 179 -145 131 122 diff --git a/graphics/pokemon/guzzlord/overworld.png b/graphics/pokemon/guzzlord/overworld.png index f9e52bd083..f8e2dd5fe5 100644 Binary files a/graphics/pokemon/guzzlord/overworld.png and b/graphics/pokemon/guzzlord/overworld.png differ diff --git a/graphics/pokemon/guzzlord/overworld_shiny.pal b/graphics/pokemon/guzzlord/overworld_shiny.pal index bc1316f82d..9e0be85bef 100644 --- a/graphics/pokemon/guzzlord/overworld_shiny.pal +++ b/graphics/pokemon/guzzlord/overworld_shiny.pal @@ -8,9 +8,9 @@ JASC-PAL 168 64 16 232 232 232 30 91 114 -69 73 85 +227 227 227 176 168 168 -42 45 50 +62 65 70 43 37 30 29 31 37 18 20 23 diff --git a/graphics/pokemon/kilowattrel/back.png b/graphics/pokemon/kilowattrel/back.png index 26eb440b6a..d72494af1c 100755 Binary files a/graphics/pokemon/kilowattrel/back.png and b/graphics/pokemon/kilowattrel/back.png differ diff --git a/graphics/pokemon/kilowattrel/front.png b/graphics/pokemon/kilowattrel/front.png index 3a8e971644..fdb1a38e48 100755 Binary files a/graphics/pokemon/kilowattrel/front.png and b/graphics/pokemon/kilowattrel/front.png differ diff --git a/graphics/pokemon/kilowattrel/shiny.pal b/graphics/pokemon/kilowattrel/shiny.pal index a9ad2ba3a8..ab148371be 100755 --- a/graphics/pokemon/kilowattrel/shiny.pal +++ b/graphics/pokemon/kilowattrel/shiny.pal @@ -8,7 +8,7 @@ JASC-PAL 248 204 48 192 144 40 248 252 248 -212 95 60 +131 27 27 16 16 16 96 248 208 128 128 128 @@ -16,4 +16,4 @@ JASC-PAL 212 95 60 120 92 32 72 88 96 -48 56 72 +90 91 92 diff --git a/graphics/pokemon/krokorok/overworld.png b/graphics/pokemon/krokorok/overworld.png index 8f1b68615c..47e57ccd5e 100644 Binary files a/graphics/pokemon/krokorok/overworld.png and b/graphics/pokemon/krokorok/overworld.png differ diff --git a/graphics/pokemon/krookodile/overworld.png b/graphics/pokemon/krookodile/overworld.png index 9bac013544..d905625c55 100644 Binary files a/graphics/pokemon/krookodile/overworld.png and b/graphics/pokemon/krookodile/overworld.png differ diff --git a/graphics/pokemon/krookodile/overworld_normal.pal b/graphics/pokemon/krookodile/overworld_normal.pal index 04d2244669..e416936398 100644 --- a/graphics/pokemon/krookodile/overworld_normal.pal +++ b/graphics/pokemon/krookodile/overworld_normal.pal @@ -10,8 +10,8 @@ JASC-PAL 25 25 33 99 99 99 236 236 246 -99 99 99 -185 172 189 +35 35 35 +152 142 156 38 37 38 129 138 129 182 191 199 diff --git a/graphics/pokemon/krookodile/overworld_shiny.pal b/graphics/pokemon/krookodile/overworld_shiny.pal index 070a0a4e5d..c89ebe28de 100644 --- a/graphics/pokemon/krookodile/overworld_shiny.pal +++ b/graphics/pokemon/krookodile/overworld_shiny.pal @@ -8,10 +8,10 @@ JASC-PAL 168 136 88 0 0 0 224 200 88 -99 99 99 +48 48 48 236 236 246 168 144 64 -185 172 189 +122 94 0 38 37 38 129 138 129 182 191 199 diff --git a/graphics/pokemon/landorus/anim_front.png b/graphics/pokemon/landorus/anim_front.png index 762c5cd2e7..08808382b9 100644 Binary files a/graphics/pokemon/landorus/anim_front.png and b/graphics/pokemon/landorus/anim_front.png differ diff --git a/graphics/pokemon/landorus/back.png b/graphics/pokemon/landorus/back.png index f70121ac4f..9df361e4b6 100644 Binary files a/graphics/pokemon/landorus/back.png and b/graphics/pokemon/landorus/back.png differ diff --git a/graphics/pokemon/landorus/normal.pal b/graphics/pokemon/landorus/normal.pal index bbacdca837..36dd9dbac0 100644 --- a/graphics/pokemon/landorus/normal.pal +++ b/graphics/pokemon/landorus/normal.pal @@ -10,10 +10,10 @@ JASC-PAL 184 72 80 160 88 56 240 120 64 -51 51 34 +96 48 16 248 200 96 -51 51 51 +72 40 24 96 64 48 119 51 85 128 128 128 -0 0 0 +128 96 72 diff --git a/graphics/pokemon/landorus/shiny.pal b/graphics/pokemon/landorus/shiny.pal index 25f3ac5c93..c76bc2922b 100644 --- a/graphics/pokemon/landorus/shiny.pal +++ b/graphics/pokemon/landorus/shiny.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -152 208 160 -88 112 88 -16 16 16 -248 248 248 -152 176 160 -88 64 40 -240 96 8 -160 96 16 -248 160 40 -80 48 24 -248 192 0 -56 32 16 -72 48 32 -120 72 40 -128 128 128 -0 0 0 +153 204 153 +90 115 90 +17 17 17 +255 255 255 +164 189 164 +115 65 57 +238 98 8 +180 115 24 +255 164 41 +82 49 24 +255 197 0 +41 24 16 +74 49 32 +172 82 32 +90 115 90 +106 65 41 diff --git a/graphics/pokemon/latias/mega/front.png b/graphics/pokemon/latias/mega/front.png index bb51350564..491f02fa4b 100644 Binary files a/graphics/pokemon/latias/mega/front.png and b/graphics/pokemon/latias/mega/front.png differ diff --git a/graphics/pokemon/latios/mega/front.png b/graphics/pokemon/latios/mega/front.png index cc20e9d1cb..ebca8034d8 100644 Binary files a/graphics/pokemon/latios/mega/front.png and b/graphics/pokemon/latios/mega/front.png differ diff --git a/graphics/pokemon/lillipup/overworld_shiny.pal b/graphics/pokemon/lillipup/overworld_shiny.pal index 63bbc81935..ffdd1a31f2 100644 --- a/graphics/pokemon/lillipup/overworld_shiny.pal +++ b/graphics/pokemon/lillipup/overworld_shiny.pal @@ -2,11 +2,11 @@ JASC-PAL 0100 16 152 208 160 -104 72 16 -96 72 24 +97 62 1 +171 105 39 184 128 72 -232 176 88 0 0 0 +224 169 81 240 216 152 88 88 88 232 232 248 diff --git a/graphics/pokemon/magearna/back.png b/graphics/pokemon/magearna/back.png index 17568f8bb2..2e3a77c512 100644 Binary files a/graphics/pokemon/magearna/back.png and b/graphics/pokemon/magearna/back.png differ diff --git a/graphics/pokemon/magearna/shiny.pal b/graphics/pokemon/magearna/shiny.pal index cb523c62f3..a8573fe8e9 100644 --- a/graphics/pokemon/magearna/shiny.pal +++ b/graphics/pokemon/magearna/shiny.pal @@ -2,18 +2,18 @@ JASC-PAL 0100 16 153 211 165 -175 92 10 -252 238 137 -219 168 62 -218 192 200 -183 132 149 -119 83 89 +103 114 114 +234 236 236 +158 166 166 +209 216 216 +162 176 176 +110 130 130 16 16 16 -115 128 128 -248 248 248 -185 185 185 +94 100 100 +191 194 194 +140 147 147 252 154 188 248 82 111 12 168 201 -54 237 227 +221 233 229 67 63 61 diff --git a/graphics/pokemon/medicham/mega/back.png b/graphics/pokemon/medicham/mega/back.png index 692470be7a..336d79ce1c 100644 Binary files a/graphics/pokemon/medicham/mega/back.png and b/graphics/pokemon/medicham/mega/back.png differ diff --git a/graphics/pokemon/medicham/mega/front.png b/graphics/pokemon/medicham/mega/front.png index d375b55d42..9438f9d0df 100644 Binary files a/graphics/pokemon/medicham/mega/front.png and b/graphics/pokemon/medicham/mega/front.png differ diff --git a/graphics/pokemon/medicham/mega/normal.pal b/graphics/pokemon/medicham/mega/normal.pal index f7b8a8fd4e..2b0f86482e 100644 --- a/graphics/pokemon/medicham/mega/normal.pal +++ b/graphics/pokemon/medicham/mega/normal.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -152 208 160 -176 72 88 -88 64 72 -136 128 136 -200 88 112 -224 112 136 -248 248 248 -208 200 200 -168 160 168 -16 16 16 -232 184 88 -160 112 40 -240 216 128 -64 160 184 -224 224 224 -16 72 88 +153 211 165 +23 75 93 +82 65 74 +164 115 41 +131 65 74 +180 74 90 +238 189 90 +230 115 139 +67 163 189 +139 131 139 +172 164 172 +17 17 17 +246 222 131 +197 197 197 +222 222 222 +250 250 250 diff --git a/graphics/pokemon/medicham/mega/shiny.pal b/graphics/pokemon/medicham/mega/shiny.pal index 2a07de3b1d..09fef3a592 100644 --- a/graphics/pokemon/medicham/mega/shiny.pal +++ b/graphics/pokemon/medicham/mega/shiny.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -152 208 160 -16 72 88 -16 16 16 -136 128 136 -32 120 200 -80 160 224 -232 224 200 -232 224 200 -216 168 128 -16 16 16 -160 112 40 -160 112 40 -240 216 128 -64 160 184 -232 224 200 -16 72 88 +153 211 165 +0 122 112 +148 82 32 +163 153 24 +57 98 172 +90 131 205 +229 226 36 +156 180 255 +0 193 190 +180 123 65 +205 156 98 +17 17 17 +255 249 140 +230 189 131 +255 230 164 +250 250 250 diff --git a/graphics/pokemon/moltres/galarian/overworld.png b/graphics/pokemon/moltres/galarian/overworld.png index 87e93311a8..b6aeb63f96 100644 Binary files a/graphics/pokemon/moltres/galarian/overworld.png and b/graphics/pokemon/moltres/galarian/overworld.png differ diff --git a/graphics/pokemon/moltres/galarian/overworld_normal.pal b/graphics/pokemon/moltres/galarian/overworld_normal.pal index ef0bee86ea..ca9a549d10 100644 --- a/graphics/pokemon/moltres/galarian/overworld_normal.pal +++ b/graphics/pokemon/moltres/galarian/overworld_normal.pal @@ -12,8 +12,8 @@ JASC-PAL 249 181 225 120 200 248 160 224 248 -11 11 11 -12 12 12 -13 13 13 -14 14 14 -15 15 15 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 diff --git a/graphics/pokemon/moltres/galarian/overworld_shiny.pal b/graphics/pokemon/moltres/galarian/overworld_shiny.pal index ef0bee86ea..8330f2687a 100644 --- a/graphics/pokemon/moltres/galarian/overworld_shiny.pal +++ b/graphics/pokemon/moltres/galarian/overworld_shiny.pal @@ -5,15 +5,15 @@ JASC-PAL 0 0 0 0 0 0 61 0 25 -24 24 24 -56 56 56 -173 28 86 -235 88 147 -249 181 225 +229 185 8 +248 208 48 +240 80 32 +240 128 48 +248 232 104 120 200 248 160 224 248 -11 11 11 -12 12 12 -13 13 13 -14 14 14 -15 15 15 +255 255 255 +255 255 255 +255 255 255 +255 255 255 +255 255 255 diff --git a/graphics/pokemon/morelull/overworld.png b/graphics/pokemon/morelull/overworld.png index 6d164768a6..5f85740da2 100644 Binary files a/graphics/pokemon/morelull/overworld.png and b/graphics/pokemon/morelull/overworld.png differ diff --git a/graphics/pokemon/morelull/overworld_normal.pal b/graphics/pokemon/morelull/overworld_normal.pal index 52cbf93f93..6efa8c740b 100644 --- a/graphics/pokemon/morelull/overworld_normal.pal +++ b/graphics/pokemon/morelull/overworld_normal.pal @@ -6,11 +6,11 @@ JASC-PAL 245 210 217 220 210 232 242 196 206 -196 196 196 +184 131 178 191 196 122 158 158 158 171 152 193 -184 131 178 +196 196 255 146 150 89 224 124 140 120 120 120 diff --git a/graphics/pokemon/morelull/overworld_shiny.pal b/graphics/pokemon/morelull/overworld_shiny.pal index 87d1e9509a..7f3068c455 100644 --- a/graphics/pokemon/morelull/overworld_shiny.pal +++ b/graphics/pokemon/morelull/overworld_shiny.pal @@ -2,11 +2,11 @@ JASC-PAL 0100 16 255 255 255 -176 112 64 -240 144 120 +230 227 233 +186 57 24 220 210 232 -208 120 24 -196 196 196 +209 134 54 +240 192 72 191 196 122 158 158 158 112 40 24 diff --git a/graphics/pokemon/mr_mime/galarian/overworld.png b/graphics/pokemon/mr_mime/galarian/overworld.png index 122bda4a13..fd95946076 100644 Binary files a/graphics/pokemon/mr_mime/galarian/overworld.png and b/graphics/pokemon/mr_mime/galarian/overworld.png differ diff --git a/graphics/pokemon/mr_mime/galarian/overworld_normal.pal b/graphics/pokemon/mr_mime/galarian/overworld_normal.pal index 0166ba80d5..9783b2507f 100644 --- a/graphics/pokemon/mr_mime/galarian/overworld_normal.pal +++ b/graphics/pokemon/mr_mime/galarian/overworld_normal.pal @@ -7,7 +7,7 @@ JASC-PAL 89 106 134 59 49 48 53 69 94 -175 154 153 +135 118 118 0 0 0 246 226 225 255 255 255 @@ -16,4 +16,4 @@ JASC-PAL 190 190 190 113 170 190 104 104 104 -15 15 15 +255 255 255 diff --git a/graphics/pokemon/mr_mime/galarian/overworld_shiny.pal b/graphics/pokemon/mr_mime/galarian/overworld_shiny.pal index 0166ba80d5..b2ee5a4fd1 100644 --- a/graphics/pokemon/mr_mime/galarian/overworld_shiny.pal +++ b/graphics/pokemon/mr_mime/galarian/overworld_shiny.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -197 44 44 +128 63 60 0 0 0 15 20 29 -89 106 134 +112 96 136 59 49 48 -53 69 94 -175 154 153 +96 72 104 +114 93 92 0 0 0 246 226 225 255 255 255 57 57 57 -164 222 242 +144 176 208 190 190 190 -113 170 190 +112 136 184 104 104 104 -15 15 15 +255 255 255 diff --git a/graphics/pokemon/naclstack/back.png b/graphics/pokemon/naclstack/back.png index 34d80185e7..6d0238f3f4 100644 Binary files a/graphics/pokemon/naclstack/back.png and b/graphics/pokemon/naclstack/back.png differ diff --git a/graphics/pokemon/naclstack/front.png b/graphics/pokemon/naclstack/front.png index 4055c46cf3..646b29881c 100644 Binary files a/graphics/pokemon/naclstack/front.png and b/graphics/pokemon/naclstack/front.png differ diff --git a/graphics/pokemon/naclstack/normal.pal b/graphics/pokemon/naclstack/normal.pal index 2fd0dd7abd..19fea0383f 100644 --- a/graphics/pokemon/naclstack/normal.pal +++ b/graphics/pokemon/naclstack/normal.pal @@ -1,17 +1,19 @@ JASC-PAL 0100 -14 -153 211 165 -113 113 113 +16 +156 213 164 +148 98 90 +98 82 74 +123 123 123 +197 148 123 +230 213 205 +197 180 189 255 255 255 -180 180 180 -18 18 18 -198 135 110 -135 86 81 -246 195 158 -87 44 39 -107 65 60 -255 160 0 -255 255 0 -66 22 28 -194 103 16 +82 82 82 +65 49 41 +139 115 98 +8 8 8 +238 139 24 +246 230 24 +0 0 0 +0 0 0 diff --git a/graphics/pokemon/naclstack/shiny.pal b/graphics/pokemon/naclstack/shiny.pal index a8f14a01b0..94d60d4731 100644 --- a/graphics/pokemon/naclstack/shiny.pal +++ b/graphics/pokemon/naclstack/shiny.pal @@ -1,17 +1,19 @@ JASC-PAL 0100 -14 -153 211 165 -164 70 47 -235 145 61 -211 94 44 -18 18 18 -198 135 110 -135 86 81 -246 195 158 -87 44 39 -107 65 60 -255 160 0 -255 255 0 -66 22 28 -194 103 16 +16 +156 213 164 +148 98 90 +98 82 74 +123 98 65 +197 148 123 +230 213 205 +197 131 106 +238 189 148 +90 57 49 +65 49 41 +139 115 98 +8 8 8 +238 139 24 +246 230 24 +0 0 0 +0 0 0 diff --git a/graphics/pokemon/orthworm/front.png b/graphics/pokemon/orthworm/front.png index 87535ce92c..14884ce2c7 100755 Binary files a/graphics/pokemon/orthworm/front.png and b/graphics/pokemon/orthworm/front.png differ diff --git a/graphics/pokemon/pincurchin/shiny.pal b/graphics/pokemon/pincurchin/shiny.pal index dd03c31a28..a2b0a156a7 100644 --- a/graphics/pokemon/pincurchin/shiny.pal +++ b/graphics/pokemon/pincurchin/shiny.pal @@ -13,7 +13,7 @@ JASC-PAL 248 136 40 248 240 40 192 88 16 -0 0 0 -0 0 0 +173 255 239 +20 255 210 0 0 0 0 0 0 diff --git a/graphics/pokemon/ponyta/galarian/back.png b/graphics/pokemon/ponyta/galarian/back.png index fe45584312..f798d5cb45 100644 Binary files a/graphics/pokemon/ponyta/galarian/back.png and b/graphics/pokemon/ponyta/galarian/back.png differ diff --git a/graphics/pokemon/ponyta/galarian/overworld.png b/graphics/pokemon/ponyta/galarian/overworld.png index ac61386576..683780312b 100644 Binary files a/graphics/pokemon/ponyta/galarian/overworld.png and b/graphics/pokemon/ponyta/galarian/overworld.png differ diff --git a/graphics/pokemon/ponyta/galarian/overworld_normal.pal b/graphics/pokemon/ponyta/galarian/overworld_normal.pal index 81bbedb6be..2889031392 100644 --- a/graphics/pokemon/ponyta/galarian/overworld_normal.pal +++ b/graphics/pokemon/ponyta/galarian/overworld_normal.pal @@ -1,7 +1,7 @@ JASC-PAL 0100 16 -131 129 131 +152 208 160 123 72 123 131 121 90 32 32 32 diff --git a/graphics/pokemon/ponyta/galarian/overworld_shiny.pal b/graphics/pokemon/ponyta/galarian/overworld_shiny.pal index 81bbedb6be..143612d3ea 100644 --- a/graphics/pokemon/ponyta/galarian/overworld_shiny.pal +++ b/graphics/pokemon/ponyta/galarian/overworld_shiny.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -131 129 131 -123 72 123 +152 208 160 +200 144 48 131 121 90 32 32 32 -230 222 164 -197 109 197 -65 113 106 -213 153 213 +192 216 200 +240 200 80 +66 149 97 +248 240 160 189 186 189 -246 226 172 +71 180 150 238 234 255 0 0 0 -106 222 222 -115 113 65 -230 186 230 -246 242 222 +128 248 176 +72 88 72 +229 218 105 +232 248 240 diff --git a/graphics/pokemon/ponyta/galarian/shiny.pal b/graphics/pokemon/ponyta/galarian/shiny.pal index 707eb51faa..62925ea1a8 100644 --- a/graphics/pokemon/ponyta/galarian/shiny.pal +++ b/graphics/pokemon/ponyta/galarian/shiny.pal @@ -2,15 +2,15 @@ JASC-PAL 0100 16 152 208 160 -72 184 120 -16 144 64 -128 248 176 -200 144 48 -248 240 160 -240 200 80 +72 200 232 +48 152 168 +128 224 216 +199 171 123 +247 244 203 +240 219 158 72 88 72 16 16 16 -88 32 120 +64 56 165 232 248 240 192 216 200 136 160 144 diff --git a/graphics/pokemon/qwilfish/hisuian/overworld_shiny.pal b/graphics/pokemon/qwilfish/hisuian/overworld_shiny.pal index 63bab6514a..9f03da9c2e 100644 --- a/graphics/pokemon/qwilfish/hisuian/overworld_shiny.pal +++ b/graphics/pokemon/qwilfish/hisuian/overworld_shiny.pal @@ -2,11 +2,11 @@ JASC-PAL 0100 16 152 208 160 -131 123 98 +56 55 50 131 123 106 74 57 131 0 0 0 -189 49 156 +128 92 240 189 189 189 148 139 139 238 238 255 diff --git a/graphics/pokemon/rapidash/galarian/back.png b/graphics/pokemon/rapidash/galarian/back.png index df065bf1f0..59816614d9 100644 Binary files a/graphics/pokemon/rapidash/galarian/back.png and b/graphics/pokemon/rapidash/galarian/back.png differ diff --git a/graphics/pokemon/rapidash/galarian/overworld.png b/graphics/pokemon/rapidash/galarian/overworld.png index f2a28d0427..1271349061 100644 Binary files a/graphics/pokemon/rapidash/galarian/overworld.png and b/graphics/pokemon/rapidash/galarian/overworld.png differ diff --git a/graphics/pokemon/rapidash/galarian/overworld_shiny.pal b/graphics/pokemon/rapidash/galarian/overworld_shiny.pal index f317ac3300..fa425be9b7 100644 --- a/graphics/pokemon/rapidash/galarian/overworld_shiny.pal +++ b/graphics/pokemon/rapidash/galarian/overworld_shiny.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -128 128 128 +152 208 160 18 2 31 -61 9 100 +0 24 96 71 113 111 107 220 217 167 235 232 62 62 62 -121 74 121 +176 144 32 245 243 220 -198 110 198 +237 237 137 255 255 255 0 0 0 -214 154 214 -226 187 226 +233 217 173 +248 248 208 232 232 248 230 223 160 diff --git a/graphics/pokemon/rapidash/galarian/shiny.pal b/graphics/pokemon/rapidash/galarian/shiny.pal index c1b04fe6b8..3a76f1576d 100644 --- a/graphics/pokemon/rapidash/galarian/shiny.pal +++ b/graphics/pokemon/rapidash/galarian/shiny.pal @@ -6,11 +6,11 @@ JASC-PAL 128 224 200 56 192 168 16 16 16 -176 144 32 +176 160 104 240 240 240 -224 216 128 +224 220 175 0 24 96 -248 248 208 +247 247 228 104 104 120 200 200 208 160 160 176 diff --git a/graphics/pokemon/regieleki/overworld.png b/graphics/pokemon/regieleki/overworld.png index 83a177ae2e..154015c385 100644 Binary files a/graphics/pokemon/regieleki/overworld.png and b/graphics/pokemon/regieleki/overworld.png differ diff --git a/graphics/pokemon/regieleki/overworld_normal.pal b/graphics/pokemon/regieleki/overworld_normal.pal index 1c69e174c2..f6bab934e8 100644 --- a/graphics/pokemon/regieleki/overworld_normal.pal +++ b/graphics/pokemon/regieleki/overworld_normal.pal @@ -10,7 +10,7 @@ JASC-PAL 208 168 8 248 248 192 248 152 192 -0 0 0 +232 119 176 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/regieleki/overworld_shiny.pal b/graphics/pokemon/regieleki/overworld_shiny.pal index 52fc33ef18..ae43ceece9 100644 --- a/graphics/pokemon/regieleki/overworld_shiny.pal +++ b/graphics/pokemon/regieleki/overworld_shiny.pal @@ -9,8 +9,8 @@ JASC-PAL 172 164 205 172 172 106 238 246 172 -230 238 49 -0 0 0 +248 152 192 +232 119 176 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/runerigus/shiny.pal b/graphics/pokemon/runerigus/shiny.pal index 6166d5bfd6..8fd4e72f06 100644 --- a/graphics/pokemon/runerigus/shiny.pal +++ b/graphics/pokemon/runerigus/shiny.pal @@ -10,7 +10,7 @@ JASC-PAL 216 208 208 184 88 208 144 40 168 -168 56 208 +56 208 174 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/salamence/anim_front.png b/graphics/pokemon/salamence/anim_front.png index 977f43a6f8..41a8818996 100644 Binary files a/graphics/pokemon/salamence/anim_front.png and b/graphics/pokemon/salamence/anim_front.png differ diff --git a/graphics/pokemon/salamence/mega/front.png b/graphics/pokemon/salamence/mega/front.png index bec9a92549..44812fa058 100644 Binary files a/graphics/pokemon/salamence/mega/front.png and b/graphics/pokemon/salamence/mega/front.png differ diff --git a/graphics/pokemon/samurott/hisuian/overworld.png b/graphics/pokemon/samurott/hisuian/overworld.png index 6dd47d5777..7d4db0b87d 100644 Binary files a/graphics/pokemon/samurott/hisuian/overworld.png and b/graphics/pokemon/samurott/hisuian/overworld.png differ diff --git a/graphics/pokemon/samurott/hisuian/overworld_normal.pal b/graphics/pokemon/samurott/hisuian/overworld_normal.pal index e6be3b5f56..15854747e9 100644 --- a/graphics/pokemon/samurott/hisuian/overworld_normal.pal +++ b/graphics/pokemon/samurott/hisuian/overworld_normal.pal @@ -6,7 +6,7 @@ JASC-PAL 0 0 0 238 238 255 189 189 197 -16 24 49 +14 22 48 189 49 49 32 24 32 41 49 74 diff --git a/graphics/pokemon/samurott/hisuian/overworld_shiny.pal b/graphics/pokemon/samurott/hisuian/overworld_shiny.pal index 827453552a..494b52f0aa 100644 --- a/graphics/pokemon/samurott/hisuian/overworld_shiny.pal +++ b/graphics/pokemon/samurott/hisuian/overworld_shiny.pal @@ -8,7 +8,7 @@ JASC-PAL 189 189 197 16 24 49 180 164 156 -197 189 197 +84 80 84 222 213 222 139 115 106 238 238 246 diff --git a/graphics/pokemon/sawsbuck/summer/overworld.png b/graphics/pokemon/sawsbuck/summer/overworld.png index 7bb026e55d..1926a5f071 100644 Binary files a/graphics/pokemon/sawsbuck/summer/overworld.png and b/graphics/pokemon/sawsbuck/summer/overworld.png differ diff --git a/graphics/pokemon/sawsbuck/summer/overworld_shiny.pal b/graphics/pokemon/sawsbuck/summer/overworld_shiny.pal index 34f7d0f0b4..4d2a5df53c 100644 --- a/graphics/pokemon/sawsbuck/summer/overworld_shiny.pal +++ b/graphics/pokemon/sawsbuck/summer/overworld_shiny.pal @@ -5,13 +5,13 @@ JASC-PAL 0 0 0 8 136 64 27 81 44 -40 19 12 -199 170 85 -233 219 172 -176 104 32 +238 222 164 +74 16 8 +84 35 16 +178 114 49 128 64 16 -207 124 25 -141 98 51 +183 167 84 +255 255 255 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/serperior/overworld.png b/graphics/pokemon/serperior/overworld.png index 8cee61f966..4b71f89831 100644 Binary files a/graphics/pokemon/serperior/overworld.png and b/graphics/pokemon/serperior/overworld.png differ diff --git a/graphics/pokemon/serperior/overworld_normal.pal b/graphics/pokemon/serperior/overworld_normal.pal index 3733e903b2..6600b8af88 100644 --- a/graphics/pokemon/serperior/overworld_normal.pal +++ b/graphics/pokemon/serperior/overworld_normal.pal @@ -3,17 +3,17 @@ JASC-PAL 16 128 208 232 12 98 39 -106 115 57 +115 112 57 24 156 74 -236 173 21 +248 248 248 8 16 16 156 213 156 236 173 21 115 164 115 -12 98 39 -236 173 21 +5 59 26 +248 128 0 24 156 74 -0 0 0 -0 0 0 -0 0 0 +208 152 8 +12 98 39 +5 59 26 0 0 0 diff --git a/graphics/pokemon/serperior/overworld_shiny.pal b/graphics/pokemon/serperior/overworld_shiny.pal index eafc2d1fda..2a03f663f2 100644 --- a/graphics/pokemon/serperior/overworld_shiny.pal +++ b/graphics/pokemon/serperior/overworld_shiny.pal @@ -8,12 +8,12 @@ JASC-PAL 207 215 195 7 14 14 168 232 104 -185 175 53 +224 248 152 96 166 87 -40 56 48 -212 33 0 +40 48 56 +248 64 24 24 156 74 -0 0 0 -0 0 0 -0 0 0 +184 179 114 +43 99 64 +0 72 40 0 0 0 diff --git a/graphics/pokemon/servine/overworld.png b/graphics/pokemon/servine/overworld.png index b329b47837..5c9caeec8c 100644 Binary files a/graphics/pokemon/servine/overworld.png and b/graphics/pokemon/servine/overworld.png differ diff --git a/graphics/pokemon/servine/overworld_normal.pal b/graphics/pokemon/servine/overworld_normal.pal index ca1ffe3c14..58041cf5a3 100644 --- a/graphics/pokemon/servine/overworld_normal.pal +++ b/graphics/pokemon/servine/overworld_normal.pal @@ -10,9 +10,9 @@ JASC-PAL 141 120 48 251 243 199 110 64 20 -0 0 0 -0 0 0 -0 0 0 +193 193 147 +63 89 63 +184 72 32 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/servine/overworld_shiny.pal b/graphics/pokemon/servine/overworld_shiny.pal index ff9fff5133..ef343bda48 100644 --- a/graphics/pokemon/servine/overworld_shiny.pal +++ b/graphics/pokemon/servine/overworld_shiny.pal @@ -3,16 +3,16 @@ JASC-PAL 16 152 208 160 32 48 72 -0 0 0 237 151 18 40 152 168 -63 74 11 32 88 160 -138 103 54 +0 0 0 +74 58 11 218 221 187 -0 0 0 -0 0 0 -0 0 0 +144 24 40 +182 189 145 +63 84 89 +248 48 48 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/shroodle/back.png b/graphics/pokemon/shroodle/back.png index ffecfe183c..3bb3cb4a58 100755 Binary files a/graphics/pokemon/shroodle/back.png and b/graphics/pokemon/shroodle/back.png differ diff --git a/graphics/pokemon/shroodle/front.png b/graphics/pokemon/shroodle/front.png index 38dac9194a..aa6410070e 100755 Binary files a/graphics/pokemon/shroodle/front.png and b/graphics/pokemon/shroodle/front.png differ diff --git a/graphics/pokemon/shroodle/shiny.pal b/graphics/pokemon/shroodle/shiny.pal index bb3f9a6a7d..67046e31cf 100755 --- a/graphics/pokemon/shroodle/shiny.pal +++ b/graphics/pokemon/shroodle/shiny.pal @@ -2,18 +2,18 @@ JASC-PAL 0100 16 152 208 160 -96 88 88 -232 236 200 +125 121 118 +236 235 232 16 16 16 -176 168 136 -64 76 104 -72 60 56 +172 166 153 +79 104 117 +72 68 65 48 36 40 -128 156 168 -168 168 224 -96 108 136 +187 210 227 +173 114 205 +128 149 168 248 252 248 -208 200 248 +225 171 233 184 176 184 -160 112 224 +225 52 239 0 0 0 diff --git a/graphics/pokemon/sigilyph/overworld.png b/graphics/pokemon/sigilyph/overworld.png index 3f28054070..a39813710c 100644 Binary files a/graphics/pokemon/sigilyph/overworld.png and b/graphics/pokemon/sigilyph/overworld.png differ diff --git a/graphics/pokemon/sigilyph/overworld_normal.pal b/graphics/pokemon/sigilyph/overworld_normal.pal index 95d6d5cb63..32ef424021 100644 --- a/graphics/pokemon/sigilyph/overworld_normal.pal +++ b/graphics/pokemon/sigilyph/overworld_normal.pal @@ -2,17 +2,17 @@ JASC-PAL 0100 16 152 208 160 -33 112 129 -72 70 22 +16 88 105 +147 50 4 7 7 7 63 164 227 171 92 25 255 191 5 40 40 40 -192 192 203 +248 248 248 47 155 63 -0 0 0 -0 0 0 +206 0 46 +18 117 33 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/sigilyph/overworld_shiny.pal b/graphics/pokemon/sigilyph/overworld_shiny.pal index 24e47afc05..9c3f2da54b 100644 --- a/graphics/pokemon/sigilyph/overworld_shiny.pal +++ b/graphics/pokemon/sigilyph/overworld_shiny.pal @@ -2,18 +2,18 @@ JASC-PAL 0100 16 152 208 160 -203 38 19 -90 63 20 +117 76 35 +120 48 7 7 7 7 -248 136 0 +248 168 72 +97 120 16 192 224 88 -40 40 40 -209 88 56 -128 152 40 -192 192 203 -0 0 0 -0 0 0 -0 0 0 +48 48 48 +248 248 248 +160 136 80 +217 79 61 +181 114 72 +199 172 109 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/slowking/galarian/overworld.png b/graphics/pokemon/slowking/galarian/overworld.png index 5babfe384b..4ff3b7f4b7 100644 Binary files a/graphics/pokemon/slowking/galarian/overworld.png and b/graphics/pokemon/slowking/galarian/overworld.png differ diff --git a/graphics/pokemon/slowking/galarian/overworld_normal.pal b/graphics/pokemon/slowking/galarian/overworld_normal.pal index aa19348aaa..7b64228b1d 100644 --- a/graphics/pokemon/slowking/galarian/overworld_normal.pal +++ b/graphics/pokemon/slowking/galarian/overworld_normal.pal @@ -4,16 +4,16 @@ JASC-PAL 41 194 156 49 52 74 16 129 8 -197 202 213 +182 235 136 230 230 246 156 157 115 90 80 115 189 210 139 -148 109 115 +49 52 74 98 36 74 0 0 0 131 121 139 -164 165 180 +82 64 128 131 76 106 189 174 189 131 113 180 diff --git a/graphics/pokemon/slowking/galarian/overworld_shiny.pal b/graphics/pokemon/slowking/galarian/overworld_shiny.pal index aa19348aaa..9a2bdbc76e 100644 --- a/graphics/pokemon/slowking/galarian/overworld_shiny.pal +++ b/graphics/pokemon/slowking/galarian/overworld_shiny.pal @@ -2,18 +2,18 @@ JASC-PAL 0100 16 41 194 156 -49 52 74 -16 129 8 -197 202 213 +60 52 140 +166 48 112 +215 117 170 230 230 246 156 157 115 -90 80 115 +80 91 138 189 210 139 -148 109 115 -98 36 74 +49 52 74 +128 39 93 0 0 0 131 121 139 -164 165 180 -131 76 106 +82 64 128 +154 70 116 189 174 189 -131 113 180 +112 140 196 diff --git a/graphics/pokemon/slowpoke/galarian/overworld.png b/graphics/pokemon/slowpoke/galarian/overworld.png index 277a1f3a87..38352ce27e 100644 Binary files a/graphics/pokemon/slowpoke/galarian/overworld.png and b/graphics/pokemon/slowpoke/galarian/overworld.png differ diff --git a/graphics/pokemon/slowpoke/galarian/overworld_shiny.pal b/graphics/pokemon/slowpoke/galarian/overworld_shiny.pal index 39773f539f..ee20b05797 100644 --- a/graphics/pokemon/slowpoke/galarian/overworld_shiny.pal +++ b/graphics/pokemon/slowpoke/galarian/overworld_shiny.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -128 128 128 +152 208 160 66 63 0 -96 40 48 -173 166 8 -239 229 9 +80 72 0 +136 120 16 +171 144 18 0 0 0 -204 109 117 -240 152 160 +200 176 0 +248 216 0 160 168 176 104 80 16 208 168 96 240 216 144 232 232 248 -13 13 13 -14 14 14 -15 15 15 +255 255 255 +255 255 255 +255 255 255 diff --git a/graphics/pokemon/sneasel/hisuian/overworld.png b/graphics/pokemon/sneasel/hisuian/overworld.png index 7f4c335a9e..a830d0c0e8 100644 Binary files a/graphics/pokemon/sneasel/hisuian/overworld.png and b/graphics/pokemon/sneasel/hisuian/overworld.png differ diff --git a/graphics/pokemon/sneasel/hisuian/overworld_normal.pal b/graphics/pokemon/sneasel/hisuian/overworld_normal.pal index e909571475..3a4e58b0eb 100644 --- a/graphics/pokemon/sneasel/hisuian/overworld_normal.pal +++ b/graphics/pokemon/sneasel/hisuian/overworld_normal.pal @@ -4,16 +4,16 @@ JASC-PAL 152 208 160 74 74 98 16 16 16 -32 24 32 +70 19 70 98 115 164 164 189 222 57 74 82 -74 49 90 +113 65 145 123 139 180 255 255 255 -90 98 106 +71 53 97 164 123 222 205 49 74 246 180 65 230 139 16 -131 148 172 +97 25 97 diff --git a/graphics/pokemon/sneasel/hisuian/overworld_shiny.pal b/graphics/pokemon/sneasel/hisuian/overworld_shiny.pal index e2b78ba441..580e24ee3e 100644 --- a/graphics/pokemon/sneasel/hisuian/overworld_shiny.pal +++ b/graphics/pokemon/sneasel/hisuian/overworld_shiny.pal @@ -2,18 +2,18 @@ JASC-PAL 0100 16 152 208 160 -82 82 82 +48 48 48 16 16 16 -189 156 49 -98 115 123 +87 68 9 +47 66 69 131 148 156 57 74 82 -230 205 82 -115 131 131 +255 212 0 +79 110 110 255 255 255 -90 82 98 +50 39 61 90 82 98 230 205 82 -156 172 238 -156 172 238 -131 148 172 +135 149 204 +112 128 193 +204 170 0 diff --git a/graphics/pokemon/sneasler/overworld.png b/graphics/pokemon/sneasler/overworld.png index 29f5dc9d48..b81dedda54 100644 Binary files a/graphics/pokemon/sneasler/overworld.png and b/graphics/pokemon/sneasler/overworld.png differ diff --git a/graphics/pokemon/sneasler/overworld_shiny.pal b/graphics/pokemon/sneasler/overworld_shiny.pal index 1cfe27b932..a77780060f 100644 --- a/graphics/pokemon/sneasler/overworld_shiny.pal +++ b/graphics/pokemon/sneasler/overworld_shiny.pal @@ -5,15 +5,15 @@ JASC-PAL 8 8 8 32 32 41 205 172 65 -180 172 131 -213 205 156 +114 109 83 +171 165 128 74 57 82 -65 49 57 +80 56 84 213 205 156 57 74 82 255 255 255 -98 82 90 -156 172 238 +106 84 119 156 172 238 +116 132 198 230 197 82 -74 106 49 +104 176 47 diff --git a/graphics/pokemon/sneasler/shiny.pal b/graphics/pokemon/sneasler/shiny.pal index 8c1df6a506..ca2ee6ce6e 100755 --- a/graphics/pokemon/sneasler/shiny.pal +++ b/graphics/pokemon/sneasler/shiny.pal @@ -7,7 +7,7 @@ JASC-PAL 53 54 84 69 95 178 186 130 25 -222 47 65 +61 167 61 246 204 70 117 136 224 121 95 49 diff --git a/graphics/pokemon/snivy/overworld.png b/graphics/pokemon/snivy/overworld.png index b361587109..8c05173922 100644 Binary files a/graphics/pokemon/snivy/overworld.png and b/graphics/pokemon/snivy/overworld.png differ diff --git a/graphics/pokemon/spidops/front.png b/graphics/pokemon/spidops/front.png index 944a911070..d6bfb05623 100644 Binary files a/graphics/pokemon/spidops/front.png and b/graphics/pokemon/spidops/front.png differ diff --git a/graphics/pokemon/stunfisk/galarian/overworld.png b/graphics/pokemon/stunfisk/galarian/overworld.png index 1e72ba6a4d..dc394873e7 100644 Binary files a/graphics/pokemon/stunfisk/galarian/overworld.png and b/graphics/pokemon/stunfisk/galarian/overworld.png differ diff --git a/graphics/pokemon/stunfisk/galarian/overworld_normal.pal b/graphics/pokemon/stunfisk/galarian/overworld_normal.pal index 9070fb58ea..5d6a48cd76 100644 --- a/graphics/pokemon/stunfisk/galarian/overworld_normal.pal +++ b/graphics/pokemon/stunfisk/galarian/overworld_normal.pal @@ -11,9 +11,9 @@ JASC-PAL 255 255 255 0 0 0 119 108 95 -111 59 50 +168 20 20 199 199 199 -12 12 12 -13 13 13 -14 14 14 -15 15 15 +255 255 255 +255 255 255 +255 255 255 +255 255 255 diff --git a/graphics/pokemon/stunfisk/galarian/overworld_shiny.pal b/graphics/pokemon/stunfisk/galarian/overworld_shiny.pal index 9070fb58ea..7fe680b775 100644 --- a/graphics/pokemon/stunfisk/galarian/overworld_shiny.pal +++ b/graphics/pokemon/stunfisk/galarian/overworld_shiny.pal @@ -5,13 +5,13 @@ JASC-PAL 29 32 27 59 64 56 95 102 90 -142 172 96 -157 146 133 -205 246 140 +168 160 56 +160 128 112 +240 224 80 255 255 255 0 0 0 119 108 95 -111 59 50 +168 20 20 199 199 199 12 12 12 13 13 13 diff --git a/graphics/pokemon/swoobat/overworld.png b/graphics/pokemon/swoobat/overworld.png index ad665f8346..4648f80f63 100644 Binary files a/graphics/pokemon/swoobat/overworld.png and b/graphics/pokemon/swoobat/overworld.png differ diff --git a/graphics/pokemon/swoobat/overworld_shiny.pal b/graphics/pokemon/swoobat/overworld_shiny.pal index 84b110886f..8a3678398f 100644 --- a/graphics/pokemon/swoobat/overworld_shiny.pal +++ b/graphics/pokemon/swoobat/overworld_shiny.pal @@ -2,18 +2,18 @@ JASC-PAL 0100 16 104 48 152 -72 32 0 +87 48 2 248 192 48 232 144 16 1 1 1 198 217 180 -198 217 180 -72 32 0 +136 192 120 +41 18 0 96 48 16 -167 89 102 -198 217 180 -167 89 102 +144 72 112 198 217 180 +106 48 87 +248 160 232 198 217 180 1 1 1 0 0 0 diff --git a/graphics/pokemon/throh/overworld.png b/graphics/pokemon/throh/overworld.png index dabd0d8eba..69b2fef486 100644 Binary files a/graphics/pokemon/throh/overworld.png and b/graphics/pokemon/throh/overworld.png differ diff --git a/graphics/pokemon/throh/overworld_normal.pal b/graphics/pokemon/throh/overworld_normal.pal index 61eb765859..913583fc68 100644 --- a/graphics/pokemon/throh/overworld_normal.pal +++ b/graphics/pokemon/throh/overworld_normal.pal @@ -4,7 +4,7 @@ JASC-PAL 152 208 160 87 18 18 87 18 18 -152 208 160 +33 33 25 0 0 0 218 79 79 164 40 40 diff --git a/graphics/pokemon/tranquill/overworld.png b/graphics/pokemon/tranquill/overworld.png index 8ce1d6fcce..859cdf1543 100644 Binary files a/graphics/pokemon/tranquill/overworld.png and b/graphics/pokemon/tranquill/overworld.png differ diff --git a/graphics/pokemon/tranquill/overworld_normal.pal b/graphics/pokemon/tranquill/overworld_normal.pal index 718a5bffae..04e2105542 100644 --- a/graphics/pokemon/tranquill/overworld_normal.pal +++ b/graphics/pokemon/tranquill/overworld_normal.pal @@ -11,8 +11,8 @@ JASC-PAL 126 101 54 224 176 38 117 117 117 -0 0 0 -0 0 0 +126 101 54 +248 248 248 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/tranquill/overworld_shiny.pal b/graphics/pokemon/tranquill/overworld_shiny.pal index 0436c80854..b6c3f5a586 100644 --- a/graphics/pokemon/tranquill/overworld_shiny.pal +++ b/graphics/pokemon/tranquill/overworld_shiny.pal @@ -5,14 +5,14 @@ JASC-PAL 48 64 48 72 128 72 0 0 0 -49 45 41 112 168 112 -184 248 184 +195 237 195 +160 102 204 96 79 92 201 144 119 -217 217 233 -0 0 0 -0 0 0 +129 167 131 +80 56 96 +248 248 248 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/unown/b/overworld.png b/graphics/pokemon/unown/b/overworld.png index b2500cca0c..1e8ab69c11 100644 Binary files a/graphics/pokemon/unown/b/overworld.png and b/graphics/pokemon/unown/b/overworld.png differ diff --git a/graphics/pokemon/unown/c/overworld.png b/graphics/pokemon/unown/c/overworld.png index d7f631f31e..a53b43e06f 100644 Binary files a/graphics/pokemon/unown/c/overworld.png and b/graphics/pokemon/unown/c/overworld.png differ diff --git a/graphics/pokemon/unown/d/overworld.png b/graphics/pokemon/unown/d/overworld.png index 426e517d5d..d8796d0200 100644 Binary files a/graphics/pokemon/unown/d/overworld.png and b/graphics/pokemon/unown/d/overworld.png differ diff --git a/graphics/pokemon/unown/e/overworld.png b/graphics/pokemon/unown/e/overworld.png index 741a5ef42e..34fd50f004 100644 Binary files a/graphics/pokemon/unown/e/overworld.png and b/graphics/pokemon/unown/e/overworld.png differ diff --git a/graphics/pokemon/unown/exclamation_mark/overworld.png b/graphics/pokemon/unown/exclamation_mark/overworld.png index 4271c7ab99..96073167d0 100644 Binary files a/graphics/pokemon/unown/exclamation_mark/overworld.png and b/graphics/pokemon/unown/exclamation_mark/overworld.png differ diff --git a/graphics/pokemon/unown/f/overworld.png b/graphics/pokemon/unown/f/overworld.png index ea3332e941..789e65cc1d 100644 Binary files a/graphics/pokemon/unown/f/overworld.png and b/graphics/pokemon/unown/f/overworld.png differ diff --git a/graphics/pokemon/unown/g/overworld.png b/graphics/pokemon/unown/g/overworld.png index d9308fbe3a..38f70bdcf4 100644 Binary files a/graphics/pokemon/unown/g/overworld.png and b/graphics/pokemon/unown/g/overworld.png differ diff --git a/graphics/pokemon/unown/h/overworld.png b/graphics/pokemon/unown/h/overworld.png index 9abe3e4001..a5f030dbd6 100644 Binary files a/graphics/pokemon/unown/h/overworld.png and b/graphics/pokemon/unown/h/overworld.png differ diff --git a/graphics/pokemon/unown/i/overworld.png b/graphics/pokemon/unown/i/overworld.png index 39aa3b8572..b360c0faac 100644 Binary files a/graphics/pokemon/unown/i/overworld.png and b/graphics/pokemon/unown/i/overworld.png differ diff --git a/graphics/pokemon/unown/j/overworld.png b/graphics/pokemon/unown/j/overworld.png index af240eafd3..e1c88938d7 100644 Binary files a/graphics/pokemon/unown/j/overworld.png and b/graphics/pokemon/unown/j/overworld.png differ diff --git a/graphics/pokemon/unown/k/overworld.png b/graphics/pokemon/unown/k/overworld.png index b448f866e6..41e0372218 100644 Binary files a/graphics/pokemon/unown/k/overworld.png and b/graphics/pokemon/unown/k/overworld.png differ diff --git a/graphics/pokemon/unown/l/overworld.png b/graphics/pokemon/unown/l/overworld.png index b11096a1ab..dbbe738b8b 100644 Binary files a/graphics/pokemon/unown/l/overworld.png and b/graphics/pokemon/unown/l/overworld.png differ diff --git a/graphics/pokemon/unown/m/overworld.png b/graphics/pokemon/unown/m/overworld.png index 0d5f60e297..1952491154 100644 Binary files a/graphics/pokemon/unown/m/overworld.png and b/graphics/pokemon/unown/m/overworld.png differ diff --git a/graphics/pokemon/unown/n/overworld.png b/graphics/pokemon/unown/n/overworld.png index 8b39392831..5cb9e11487 100644 Binary files a/graphics/pokemon/unown/n/overworld.png and b/graphics/pokemon/unown/n/overworld.png differ diff --git a/graphics/pokemon/unown/o/overworld.png b/graphics/pokemon/unown/o/overworld.png index 23a5f2e277..1314548e92 100644 Binary files a/graphics/pokemon/unown/o/overworld.png and b/graphics/pokemon/unown/o/overworld.png differ diff --git a/graphics/pokemon/unown/p/overworld.png b/graphics/pokemon/unown/p/overworld.png index f3699ebdcd..fc497afc09 100644 Binary files a/graphics/pokemon/unown/p/overworld.png and b/graphics/pokemon/unown/p/overworld.png differ diff --git a/graphics/pokemon/unown/q/overworld.png b/graphics/pokemon/unown/q/overworld.png index 1e2bc7f46f..5e29b1a4d4 100644 Binary files a/graphics/pokemon/unown/q/overworld.png and b/graphics/pokemon/unown/q/overworld.png differ diff --git a/graphics/pokemon/unown/question_mark/overworld.png b/graphics/pokemon/unown/question_mark/overworld.png index e4d2102883..743b7edbfe 100644 Binary files a/graphics/pokemon/unown/question_mark/overworld.png and b/graphics/pokemon/unown/question_mark/overworld.png differ diff --git a/graphics/pokemon/unown/r/overworld.png b/graphics/pokemon/unown/r/overworld.png index 70194b27cd..493b1f0e06 100644 Binary files a/graphics/pokemon/unown/r/overworld.png and b/graphics/pokemon/unown/r/overworld.png differ diff --git a/graphics/pokemon/unown/s/overworld.png b/graphics/pokemon/unown/s/overworld.png index 2dacced847..d088d0d2b6 100644 Binary files a/graphics/pokemon/unown/s/overworld.png and b/graphics/pokemon/unown/s/overworld.png differ diff --git a/graphics/pokemon/unown/t/overworld.png b/graphics/pokemon/unown/t/overworld.png index cb476bf5ee..e8435537f2 100644 Binary files a/graphics/pokemon/unown/t/overworld.png and b/graphics/pokemon/unown/t/overworld.png differ diff --git a/graphics/pokemon/unown/u/overworld.png b/graphics/pokemon/unown/u/overworld.png index 2bde348541..a3b10de9cf 100644 Binary files a/graphics/pokemon/unown/u/overworld.png and b/graphics/pokemon/unown/u/overworld.png differ diff --git a/graphics/pokemon/unown/v/overworld.png b/graphics/pokemon/unown/v/overworld.png index 0bb8dba96c..c1fd90ff23 100644 Binary files a/graphics/pokemon/unown/v/overworld.png and b/graphics/pokemon/unown/v/overworld.png differ diff --git a/graphics/pokemon/unown/w/overworld.png b/graphics/pokemon/unown/w/overworld.png index d49a4cf96c..8c424c88b9 100644 Binary files a/graphics/pokemon/unown/w/overworld.png and b/graphics/pokemon/unown/w/overworld.png differ diff --git a/graphics/pokemon/unown/x/overworld.png b/graphics/pokemon/unown/x/overworld.png index e1621d278b..4de8713939 100644 Binary files a/graphics/pokemon/unown/x/overworld.png and b/graphics/pokemon/unown/x/overworld.png differ diff --git a/graphics/pokemon/unown/y/overworld.png b/graphics/pokemon/unown/y/overworld.png index d9fe25135b..4af4693cbb 100644 Binary files a/graphics/pokemon/unown/y/overworld.png and b/graphics/pokemon/unown/y/overworld.png differ diff --git a/graphics/pokemon/unown/z/overworld.png b/graphics/pokemon/unown/z/overworld.png index e2097128e7..94fab08a36 100644 Binary files a/graphics/pokemon/unown/z/overworld.png and b/graphics/pokemon/unown/z/overworld.png differ diff --git a/graphics/pokemon/veluza/front.png b/graphics/pokemon/veluza/front.png index 9a2a7643ab..de17bca7c0 100755 Binary files a/graphics/pokemon/veluza/front.png and b/graphics/pokemon/veluza/front.png differ diff --git a/graphics/pokemon/venipede/overworld.png b/graphics/pokemon/venipede/overworld.png index 9add5c858d..424d009da7 100644 Binary files a/graphics/pokemon/venipede/overworld.png and b/graphics/pokemon/venipede/overworld.png differ diff --git a/graphics/pokemon/venipede/overworld_normal.pal b/graphics/pokemon/venipede/overworld_normal.pal index 61a94495e7..a0ce6cd507 100644 --- a/graphics/pokemon/venipede/overworld_normal.pal +++ b/graphics/pokemon/venipede/overworld_normal.pal @@ -3,14 +3,14 @@ JASC-PAL 16 152 208 160 11 11 11 -124 56 72 +102 46 59 182 65 92 191 69 98 227 81 116 55 55 55 79 79 79 -26 95 77 20 140 80 +26 95 77 22 177 116 55 106 55 224 172 35 diff --git a/graphics/pokemon/venipede/overworld_shiny.pal b/graphics/pokemon/venipede/overworld_shiny.pal index 97a17fdcd9..2630f4f61f 100644 --- a/graphics/pokemon/venipede/overworld_shiny.pal +++ b/graphics/pokemon/venipede/overworld_shiny.pal @@ -3,16 +3,16 @@ JASC-PAL 16 152 208 160 11 11 11 -64 64 16 -96 72 40 -144 80 48 -55 55 55 +87 39 36 +152 96 75 +158 103 81 +193 125 98 40 40 40 -40 72 8 -80 112 0 -96 144 0 -55 106 55 -182 65 92 +74 70 71 +113 145 61 +76 105 27 +150 196 80 +80 96 40 224 172 35 0 0 0 0 0 0 diff --git a/graphics/pokemon/vulpix/overworld.png b/graphics/pokemon/vulpix/overworld.png index e8db777a00..2f28125d8b 100644 Binary files a/graphics/pokemon/vulpix/overworld.png and b/graphics/pokemon/vulpix/overworld.png differ diff --git a/graphics/pokemon/wattrel/back.png b/graphics/pokemon/wattrel/back.png index 2a5bc640b5..5df11376f3 100755 Binary files a/graphics/pokemon/wattrel/back.png and b/graphics/pokemon/wattrel/back.png differ diff --git a/graphics/pokemon/wattrel/front.png b/graphics/pokemon/wattrel/front.png index 72981aa44e..c2527bab8b 100755 Binary files a/graphics/pokemon/wattrel/front.png and b/graphics/pokemon/wattrel/front.png differ diff --git a/graphics/pokemon/weezing/galarian/overworld.png b/graphics/pokemon/weezing/galarian/overworld.png index 883a3637de..869fd482d1 100644 Binary files a/graphics/pokemon/weezing/galarian/overworld.png and b/graphics/pokemon/weezing/galarian/overworld.png differ diff --git a/graphics/pokemon/weezing/galarian/overworld_normal.pal b/graphics/pokemon/weezing/galarian/overworld_normal.pal index 84ad50f8bd..70db757710 100644 --- a/graphics/pokemon/weezing/galarian/overworld_normal.pal +++ b/graphics/pokemon/weezing/galarian/overworld_normal.pal @@ -1,10 +1,10 @@ JASC-PAL 0100 16 -106 44 156 -0 0 0 +152 208 160 0 0 0 148 145 148 +148 145 148 106 56 65 98 101 98 205 202 205 diff --git a/graphics/pokemon/weezing/galarian/overworld_shiny.pal b/graphics/pokemon/weezing/galarian/overworld_shiny.pal index 84ad50f8bd..009cae37fb 100644 --- a/graphics/pokemon/weezing/galarian/overworld_shiny.pal +++ b/graphics/pokemon/weezing/galarian/overworld_shiny.pal @@ -3,17 +3,17 @@ JASC-PAL 16 106 44 156 0 0 0 -0 0 0 148 145 148 +192 144 128 106 56 65 -98 101 98 +112 80 72 205 202 205 57 165 65 82 190 90 -57 60 57 +48 32 24 238 234 255 106 198 115 115 113 115 -164 161 131 +171 170 151 230 226 230 -123 125 123 +168 120 104 diff --git a/graphics/pokemon/woobat/overworld.png b/graphics/pokemon/woobat/overworld.png index 2035262ed4..1d14a5c43d 100644 Binary files a/graphics/pokemon/woobat/overworld.png and b/graphics/pokemon/woobat/overworld.png differ diff --git a/graphics/pokemon/woobat/overworld_shiny.pal b/graphics/pokemon/woobat/overworld_shiny.pal index 9f71bce45f..5f72b7825a 100644 --- a/graphics/pokemon/woobat/overworld_shiny.pal +++ b/graphics/pokemon/woobat/overworld_shiny.pal @@ -2,7 +2,7 @@ JASC-PAL 0100 16 152 208 160 -16 56 64 +24 64 16 192 232 160 0 0 0 120 184 56 @@ -11,7 +11,7 @@ JASC-PAL 192 104 120 136 72 80 240 168 176 -72 104 120 +72 120 74 252 188 219 0 0 0 0 0 0 diff --git a/graphics/pokemon/yamask/galarian/back.png b/graphics/pokemon/yamask/galarian/back.png index 06f46eae0b..ddc858a8d2 100644 Binary files a/graphics/pokemon/yamask/galarian/back.png and b/graphics/pokemon/yamask/galarian/back.png differ diff --git a/graphics/pokemon/yamask/galarian/overworld.png b/graphics/pokemon/yamask/galarian/overworld.png index 718654dd38..54276f9a04 100644 Binary files a/graphics/pokemon/yamask/galarian/overworld.png and b/graphics/pokemon/yamask/galarian/overworld.png differ diff --git a/graphics/pokemon/yamask/galarian/overworld_normal.pal b/graphics/pokemon/yamask/galarian/overworld_normal.pal index 0e81179680..af4005de75 100644 --- a/graphics/pokemon/yamask/galarian/overworld_normal.pal +++ b/graphics/pokemon/yamask/galarian/overworld_normal.pal @@ -6,14 +6,14 @@ JASC-PAL 24 24 24 56 56 56 159 83 188 -87 43 104 +98 48 117 77 71 72 128 128 128 235 93 91 194 184 185 136 126 127 179 56 54 -12 12 12 -13 13 13 -14 14 14 -15 15 15 +255 255 255 +255 255 255 +255 255 255 +255 255 255 diff --git a/graphics/pokemon/yamask/galarian/overworld_shiny.pal b/graphics/pokemon/yamask/galarian/overworld_shiny.pal index 0e81179680..7cc24b4ab8 100644 --- a/graphics/pokemon/yamask/galarian/overworld_shiny.pal +++ b/graphics/pokemon/yamask/galarian/overworld_shiny.pal @@ -3,17 +3,17 @@ JASC-PAL 16 140 78 78 0 0 0 -24 24 24 -56 56 56 -159 83 188 -87 43 104 +40 40 72 +72 72 128 +24 216 152 +24 128 88 77 71 72 128 128 128 -235 93 91 +209 105 192 194 184 185 136 126 127 -179 56 54 -12 12 12 -13 13 13 -14 14 14 -15 15 15 +173 55 152 +255 255 255 +255 255 255 +255 255 255 +255 255 255 diff --git a/graphics/pokemon/yamask/galarian/shiny.pal b/graphics/pokemon/yamask/galarian/shiny.pal index 7ab1ad8cb2..276ff7ab14 100644 --- a/graphics/pokemon/yamask/galarian/shiny.pal +++ b/graphics/pokemon/yamask/galarian/shiny.pal @@ -8,10 +8,10 @@ JASC-PAL 24 128 88 24 216 152 16 64 48 -200 64 72 +173 55 152 192 184 184 224 216 216 -208 96 104 +209 105 192 144 120 136 0 0 0 0 0 0 diff --git a/graphics/pokemon/zacian/crowned_sword/overworld.png b/graphics/pokemon/zacian/crowned_sword/overworld.png index b8069ecd51..887fa22ebd 100644 Binary files a/graphics/pokemon/zacian/crowned_sword/overworld.png and b/graphics/pokemon/zacian/crowned_sword/overworld.png differ diff --git a/graphics/pokemon/zacian/crowned_sword/overworld_shiny.pal b/graphics/pokemon/zacian/crowned_sword/overworld_shiny.pal index 906648fada..ea9e618a26 100644 --- a/graphics/pokemon/zacian/crowned_sword/overworld_shiny.pal +++ b/graphics/pokemon/zacian/crowned_sword/overworld_shiny.pal @@ -2,18 +2,18 @@ JASC-PAL 0100 16 131 129 131 -57 109 164 +40 136 160 197 145 65 -98 93 24 +48 88 176 16 36 41 -213 210 98 -213 76 49 -164 56 32 -246 226 189 +224 208 152 +48 88 176 +32 64 136 +248 224 192 0 0 0 74 68 16 -74 133 197 +102 193 209 230 226 230 -90 85 24 -32 68 106 -222 109 90 +120 78 20 +40 80 104 +64 112 240 diff --git a/graphics/pokemon/zamazenta/crowned_shield/overworld.png b/graphics/pokemon/zamazenta/crowned_shield/overworld.png index 8adba6b740..f0b482982d 100644 Binary files a/graphics/pokemon/zamazenta/crowned_shield/overworld.png and b/graphics/pokemon/zamazenta/crowned_shield/overworld.png differ diff --git a/graphics/pokemon/zamazenta/crowned_shield/overworld_normal.pal b/graphics/pokemon/zamazenta/crowned_shield/overworld_normal.pal index 54124216e5..0906c9bf94 100644 --- a/graphics/pokemon/zamazenta/crowned_shield/overworld_normal.pal +++ b/graphics/pokemon/zamazenta/crowned_shield/overworld_normal.pal @@ -6,7 +6,7 @@ JASC-PAL 16 28 57 164 153 41 148 28 32 -222 210 32 +232 48 56 205 44 57 213 210 106 74 72 16 diff --git a/graphics/pokemon/zamazenta/crowned_shield/overworld_shiny.pal b/graphics/pokemon/zamazenta/crowned_shield/overworld_shiny.pal index 54124216e5..57e6bf2744 100644 --- a/graphics/pokemon/zamazenta/crowned_shield/overworld_shiny.pal +++ b/graphics/pokemon/zamazenta/crowned_shield/overworld_shiny.pal @@ -2,18 +2,18 @@ JASC-PAL 0100 16 131 129 131 -41 64 148 +200 48 104 16 28 57 164 153 41 -148 28 32 -222 210 32 -205 44 57 -213 210 106 -74 72 16 +168 48 144 +232 80 192 +232 80 192 +224 208 152 +107 67 47 172 174 189 -24 44 98 +200 48 104 0 0 0 -32 48 115 +160 40 64 148 157 172 213 214 222 -205 194 57 +192 152 96 diff --git a/graphics/pokemon/zapdos/galarian/overworld.png b/graphics/pokemon/zapdos/galarian/overworld.png index 648884dbe6..47321a67f4 100644 Binary files a/graphics/pokemon/zapdos/galarian/overworld.png and b/graphics/pokemon/zapdos/galarian/overworld.png differ diff --git a/graphics/pokemon/zapdos/galarian/overworld_shiny.pal b/graphics/pokemon/zapdos/galarian/overworld_shiny.pal index be143c0a1f..be66a806cf 100644 --- a/graphics/pokemon/zapdos/galarian/overworld_shiny.pal +++ b/graphics/pokemon/zapdos/galarian/overworld_shiny.pal @@ -11,9 +11,9 @@ JASC-PAL 32 32 32 255 255 255 255 255 255 -0 0 0 -0 0 0 -0 0 0 +248 136 16 +112 48 24 +216 112 48 0 0 0 0 0 0 0 0 0 diff --git a/graphics/pokemon/zebstrika/overworld.png b/graphics/pokemon/zebstrika/overworld.png index fbe6fa8f56..36f7228a62 100644 Binary files a/graphics/pokemon/zebstrika/overworld.png and b/graphics/pokemon/zebstrika/overworld.png differ diff --git a/graphics/pokemon/zebstrika/overworld_normal.pal b/graphics/pokemon/zebstrika/overworld_normal.pal index fa9c14b6c0..653eafbda3 100644 --- a/graphics/pokemon/zebstrika/overworld_normal.pal +++ b/graphics/pokemon/zebstrika/overworld_normal.pal @@ -3,7 +3,7 @@ JASC-PAL 16 152 208 160 57 65 65 -57 65 65 +29 41 41 244 245 247 204 204 204 7 7 7 @@ -13,7 +13,7 @@ JASC-PAL 57 65 65 112 112 112 116 168 95 -7 7 7 -7 7 7 +248 224 0 +0 168 216 7 7 7 0 0 0 diff --git a/graphics/pokemon/zebstrika/overworld_shiny.pal b/graphics/pokemon/zebstrika/overworld_shiny.pal index 27178df2c1..4f52aeaad0 100644 --- a/graphics/pokemon/zebstrika/overworld_shiny.pal +++ b/graphics/pokemon/zebstrika/overworld_shiny.pal @@ -11,9 +11,9 @@ JASC-PAL 0 0 0 164 164 164 30 109 89 -116 116 116 +104 98 115 134 216 33 -0 0 0 -0 0 0 +248 224 0 +0 192 88 0 0 0 0 0 0 diff --git a/graphics/pokemon/zigzagoon/galarian/overworld.png b/graphics/pokemon/zigzagoon/galarian/overworld.png index 2785e862ab..d351cbdc90 100644 Binary files a/graphics/pokemon/zigzagoon/galarian/overworld.png and b/graphics/pokemon/zigzagoon/galarian/overworld.png differ diff --git a/graphics/pokemon/zigzagoon/galarian/overworld_shiny.pal b/graphics/pokemon/zigzagoon/galarian/overworld_shiny.pal index 6b74af8455..0277759a9e 100644 --- a/graphics/pokemon/zigzagoon/galarian/overworld_shiny.pal +++ b/graphics/pokemon/zigzagoon/galarian/overworld_shiny.pal @@ -4,16 +4,16 @@ JASC-PAL 52 87 191 31 43 44 36 36 36 -52 52 52 -96 101 106 -62 64 66 +82 9 36 +200 24 88 +144 8 48 163 164 163 245 245 246 0 0 0 178 179 178 -113 119 125 -238 150 178 -217 74 127 -110 59 81 +140 17 62 +152 248 240 +16 232 208 +46 79 75 64 72 80 168 184 208 diff --git a/graphics/pokemon/zorua/hisuian/overworld.png b/graphics/pokemon/zorua/hisuian/overworld.png index 9d98e3fd7a..1bc82dd88a 100644 Binary files a/graphics/pokemon/zorua/hisuian/overworld.png and b/graphics/pokemon/zorua/hisuian/overworld.png differ diff --git a/graphics/types/battle_icons1.pal b/graphics/types/battle_icons1.pal new file mode 100644 index 0000000000..972dfd02af --- /dev/null +++ b/graphics/types/battle_icons1.pal @@ -0,0 +1,15 @@ +JASC-PAL +0100 +12 +120 152 128 +49 49 49 +255 255 255 +164 82 57 +172 189 32 +184 160 90 +213 180 90 +98 98 180 +180 90 164 +172 164 148 +172 172 197 +152 172 246 diff --git a/graphics/types/battle_icons1.png b/graphics/types/battle_icons1.png new file mode 100644 index 0000000000..c47b07f117 Binary files /dev/null and b/graphics/types/battle_icons1.png differ diff --git a/graphics/types/battle_icons2.pal b/graphics/types/battle_icons2.pal new file mode 100644 index 0000000000..bddf49ad95 --- /dev/null +++ b/graphics/types/battle_icons2.pal @@ -0,0 +1,15 @@ +JASC-PAL +0100 +12 +120 152 128 +49 49 49 +255 255 255 +240 82 48 +120 200 80 +248 197 49 +80 120 136 +123 98 230 +248 115 164 +57 156 255 +90 205 230 +246 180 246 diff --git a/graphics/types/battle_icons2.png b/graphics/types/battle_icons2.png new file mode 100644 index 0000000000..44aa4f8954 Binary files /dev/null and b/graphics/types/battle_icons2.png differ diff --git a/include/battle.h b/include/battle.h index 3d2b05349f..ab0d356d95 100644 --- a/include/battle.h +++ b/include/battle.h @@ -42,7 +42,7 @@ // Used to exclude moves learned temporarily by Transform or Mimic #define MOVE_IS_PERMANENT(battler, moveSlot) \ (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) \ - && !(gDisableStructs[battler].mimickedMoves & gBitTable[moveSlot])) + && !(gDisableStructs[battler].mimickedMoves & (1u << moveSlot))) // Battle Actions // These determine what each battler will do in a turn @@ -600,12 +600,34 @@ struct LostItem u16 stolen:1; }; -#if HQ_RANDOM == TRUE struct BattleVideo { u32 battleTypeFlags; rng_value_t rngSeed; }; -#endif + +enum BattleIntroStates +{ + BATTLE_INTRO_STATE_GET_MON_DATA, + BATTLE_INTRO_STATE_LOOP_BATTLER_DATA, + BATTLE_INTRO_STATE_PREPARE_BG_SLIDE, + BATTLE_INTRO_STATE_WAIT_FOR_BG_SLIDE, + BATTLE_INTRO_STATE_DRAW_SPRITES, + BATTLE_INTRO_STATE_DRAW_PARTY_SUMMARY, + BATTLE_INTRO_STATE_WAIT_FOR_PARTY_SUMMARY, + BATTLE_INTRO_STATE_INTRO_TEXT, + BATTLE_INTRO_STATE_WAIT_FOR_INTRO_TEXT, + BATTLE_INTRO_STATE_TRAINER_SEND_OUT_TEXT, + BATTLE_INTRO_STATE_WAIT_FOR_TRAINER_SEND_OUT_TEXT, + BATTLE_INTRO_STATE_TRAINER_1_SEND_OUT_ANIM, + BATTLE_INTRO_STATE_TRAINER_2_SEND_OUT_ANIM, + BATTLE_INTRO_STATE_WAIT_FOR_TRAINER_2_SEND_OUT_ANIM, + BATTLE_INTRO_STATE_WAIT_FOR_WILD_BATTLE_TEXT, + BATTLE_INTRO_STATE_PRINT_PLAYER_SEND_OUT_TEXT, + BATTLE_INTRO_STATE_WAIT_FOR_PLAYER_SEND_OUT_TEXT, + BATTLE_INTRO_STATE_PRINT_PLAYER_1_SEND_OUT_TEXT, + BATTLE_INTRO_STATE_PRINT_PLAYER_2_SEND_OUT_TEXT, + BATTLE_INTRO_STATE_SET_DEX_AND_BATTLE_VARS +}; struct BattleStruct { @@ -676,18 +698,14 @@ struct BattleStruct u16 chosenItem[MAX_BATTLERS_COUNT]; u16 choicedMove[MAX_BATTLERS_COUNT]; u16 changedItems[MAX_BATTLERS_COUNT]; + u8 canPickupItem; u8 switchInBattlerCounter; u8 arenaTurnCounter; u8 turnSideTracker; u16 lastTakenMoveFrom[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT]; // a 2-D array [target][attacker] union { struct LinkBattlerHeader linkBattlerHeader; - - #if HQ_RANDOM == FALSE - u32 battleVideo[2]; - #else struct BattleVideo battleVideo; - #endif } multiBuffer; u8 wishPerishSongState; u8 wishPerishSongBattlerId; @@ -725,7 +743,7 @@ struct BattleStruct struct BattleGimmickData gimmick; const u8 *trainerSlideMsg; bool8 trainerSlideLowHpMsgDone; - u8 introState; + enum BattleIntroStates introState:8; u8 ateBerry[2]; // array id determined by side, each party pokemon as bit u8 stolenStats[NUM_BATTLE_STATS]; // hp byte is used for which stats to raise, other inform about by how many stages u8 lastMoveFailed; // as bits for each battler, for the sake of Stomping Tantrum @@ -763,7 +781,6 @@ struct BattleStruct bool8 effectsBeforeUsingMoveDone:1; // Mega Evo and Focus Punch/Shell Trap effects. u8 targetsDone[MAX_BATTLERS_COUNT]; // Each battler as a bit. u16 overwrittenAbilities[MAX_BATTLERS_COUNT]; // abilities overwritten during battle (keep separate from battle history in case of switching) - bool8 allowedToChangeFormInWeather[PARTY_SIZE][NUM_BATTLE_SIDES]; // For each party member and side, used by Ice Face. u8 battleBondTransformed[NUM_BATTLE_SIDES]; // Bitfield for each party. u8 storedHealingWish:4; // Each battler as a bit. u8 storedLunarDance:4; // Each battler as a bit. @@ -800,6 +817,7 @@ struct BattleStruct u8 distortedTypeMatchups; u8 categoryOverride; // for Z-Moves and Max Moves u32 stellarBoostFlags[NUM_BATTLE_SIDES]; // stored as a bitfield of flags for all types for each side + u8 fickleBeamBoosted:1; }; // The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider, @@ -818,8 +836,8 @@ STATIC_ASSERT(sizeof(((struct BattleStruct *)0)->palaceFlags) * 8 >= MAX_BATTLER #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 & gBitTable[gBattlerTarget])) -#define BATTLER_TURN_DAMAGED(battlerId) ((gSpecialStatuses[battlerId].physicalDmg != 0 || gSpecialStatuses[battlerId].specialDmg != 0) || (gBattleStruct->enduredDamage & gBitTable[battler])) +#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))) #define IS_BATTLER_OF_TYPE(battlerId, type)((GetBattlerType(battlerId, 0, FALSE) == type || GetBattlerType(battlerId, 1, FALSE) == type || (GetBattlerType(battlerId, 2, FALSE) != TYPE_MYSTERY && GetBattlerType(battlerId, 2, FALSE) == type))) #define IS_BATTLER_OF_BASE_TYPE(battlerId, type)((GetBattlerType(battlerId, 0, TRUE) == type || GetBattlerType(battlerId, 1, TRUE) == type || (GetBattlerType(battlerId, 2, TRUE) != TYPE_MYSTERY && GetBattlerType(battlerId, 2, TRUE) == type))) @@ -1131,6 +1149,13 @@ static inline u32 GetBattlerSide(u32 battler) return GetBattlerPosition(battler) & BIT_SIDE; } +static inline struct Pokemon* GetBattlerData(u32 battlerId) +{ + u32 index = gBattlerPartyIndexes[battlerId]; + + return (GetBattlerSide(battlerId) == B_SIDE_OPPONENT) ? &gEnemyParty[index] : &gPlayerParty[index]; +} + static inline struct Pokemon *GetSideParty(u32 side) { return (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; @@ -1141,4 +1166,9 @@ static inline struct Pokemon *GetBattlerParty(u32 battler) return GetSideParty(GetBattlerSide(battler)); } +static inline bool32 IsDoubleBattle(void) +{ + return gBattleTypeFlags & BATTLE_TYPE_DOUBLE; +} + #endif // GUARD_BATTLE_H diff --git a/include/battle_anim.h b/include/battle_anim.h index ce9749685e..351dbbd454 100644 --- a/include/battle_anim.h +++ b/include/battle_anim.h @@ -194,7 +194,6 @@ u8 GetBattlerSpriteCoord(u8 battlerId, u8 attributeId); bool8 IsBattlerSpritePresent(u8 battlerId); void ClearBattleAnimBg(u32 bgId); u8 GetAnimBattlerSpriteId(u8 wantedBattler); -bool8 IsDoubleBattle(void); u8 GetBattleBgPaletteNum(void); u8 GetBattlerSpriteBGPriorityRank(u8 battlerId); void StoreSpriteCallbackInData6(struct Sprite *sprite, void (*spriteCallback)(struct Sprite *)); @@ -253,6 +252,7 @@ void AnimParticleBurst(struct Sprite *); void AnimPowerAbsorptionOrb(struct Sprite *sprite); void AnimNeedleArmSpike(struct Sprite *); void AnimTask_CompressTargetHorizontally(u8 taskId); +void AnimTask_CompressTargetHorizontallyFast(u8 taskId); void AnimSporeParticle(struct Sprite *sprite); void AnimAbsorptionOrb(struct Sprite *sprite); void AnimPetalDanceSmallFlower(struct Sprite *sprite); diff --git a/include/battle_controllers.h b/include/battle_controllers.h index 71a7691448..5e92cac763 100644 --- a/include/battle_controllers.h +++ b/include/battle_controllers.h @@ -310,6 +310,13 @@ void ActionSelectionDestroyCursorAt(u8 cursorPos); void InitMoveSelectionsVarsAndStrings(u32 battler); void MoveSelectionCreateCursorAt(u8 cursorPos, u8 arg1); void MoveSelectionDestroyCursorAt(u8 cursorPosition); +void PlayerHandleChooseMove(u32 battler); +void HandleInputChooseMove(u32 battler); +void HandleInputChooseTarget(u32 battler); +void HandleInputShowEntireFieldTargets(u32 battler); +void HandleInputShowTargets(u32 battler); +void HandleMoveSwitching(u32 battler); +void HandleChooseMoveAfterDma3(u32 battler); // recorded player controller void SetControllerToRecordedPlayer(u32 battler); diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 0c9f72c276..cd35e1de82 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -295,6 +295,7 @@ extern const u8 BattleScript_WeakArmorActivates[]; extern const u8 BattleScript_FellStingerRaisesStat[]; extern const u8 BattleScript_SnowWarningActivatesHail[]; extern const u8 BattleScript_SnowWarningActivatesSnow[]; +extern const u8 BattleScript_PickupActivates[]; extern const u8 BattleScript_HarvestActivates[]; extern const u8 BattleScript_ImposterActivates[]; extern const u8 BattleScript_SelectingNotAllowedMoveAssaultVest[]; @@ -843,5 +844,7 @@ extern const u8 BattleScript_EffectUpperHand[]; extern const u8 BattleScript_EffectTidyUp[]; extern const u8 BattleScript_EffectSpicyExtract[]; extern const u8 BattleScript_DamageToQuarterTargetHP[]; +extern const u8 BattleScript_EffectFickleBeam[]; +extern const u8 BattleScript_FickleBeamDoubled[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/battle_util.h b/include/battle_util.h index e11e8890c3..ff1b5ded04 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -231,6 +231,8 @@ bool32 TryRoomService(u32 battler); void BufferStatChange(u32 battler, u8 statId, u8 stringId); bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 checkTarget); u16 GetUsedHeldItem(u32 battler); +bool32 PickupHasValidTarget(u32 battler); +bool32 CantPickupItem(u32 battler); bool32 IsBattlerWeatherAffected(u32 battler, u32 weatherFlags); u32 GetBattlerMoveTargetType(u32 battler, u32 move); bool32 CanTargetBattler(u32 battlerAtk, u32 battlerDef, u16 move); diff --git a/include/config/battle.h b/include/config/battle.h index d867a223d9..ebe979824c 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -110,7 +110,7 @@ #define B_BURN_HIT_THAW GEN_LATEST // In Gen6+, damaging moves with a chance of burn will thaw the target, regardless if they're fire-type moves or not. #define B_HEALING_WISH_SWITCH GEN_LATEST // In Gen5+, the mon receiving Healing Wish is sent out at the end of the turn. // Additionally, in gen8+ the Healing Wish's effect will be stored until the user switches into a statused or hurt mon. -#define B_DEFOG_CLEARS_TERRAIN GEN_LATEST // In Gen8+, Defog also clears active Terrain. +#define B_DEFOG_EFFECT_CLEARING GEN_LATEST // In Gen6+, Defog clears Spikes, Toxic Spikes, Stealth Rock and Sticky Web from both sides. In Gen8+, Defog also clears active Terrain. #define B_STOCKPILE_RAISES_DEFS GEN_LATEST // In Gen4+, Stockpile also raises Defense and Sp. Defense stats. Once Spit Up / Swallow is used, these stat changes are lost. #define B_TRANSFORM_SHINY GEN_LATEST // In Gen4+, Transform will copy the shiny state of the opponent instead of maintaining its own shiny state. #define B_TRANSFORM_FORM_CHANGES GEN_LATEST // In Gen5+, Transformed Pokemon cannot change forms. @@ -251,26 +251,31 @@ #define B_TRY_CATCH_TRAINER_BALL GEN_LATEST // In Gen4+, trying to catch a Trainer's Pokémon does not consume the Poké Ball. // Animation Settings -#define B_NEW_SWORD_PARTICLE TRUE // If set to TRUE, it updates Swords Dance's particle. -#define B_NEW_LEECH_SEED_PARTICLE TRUE // If set to TRUE, it updates Leech Seed's animation particle. -#define B_NEW_HORN_ATTACK_PARTICLE TRUE // If set to TRUE, it updates Horn Attack's horn particle. -#define B_NEW_ROCKS_PARTICLE TRUE // If set to TRUE, it updates rock particles. -#define B_NEW_LEAF_PARTICLE TRUE // If set to TRUE, it updates leaf particle. -#define B_NEW_EMBER_PARTICLES TRUE // If set to TRUE, it updates Ember's fire particle. -#define B_NEW_MEAN_LOOK_PARTICLE TRUE // If set to TRUE, it updates Mean Look's eye particle. -#define B_NEW_TEETH_PARTICLE TRUE // If set to TRUE, it updates Bite/Crunch teeth particle. -#define B_NEW_HANDS_FEET_PARTICLE TRUE // If set to TRUE, it updates chop/kick/punch particles. -#define B_NEW_SPIKES_PARTICLE TRUE // If set to TRUE, it updates Spikes particle. -#define B_NEW_FLY_BUBBLE_PARTICLE TRUE // If set to TRUE, it updates Fly's 'bubble' particle. -#define B_NEW_CURSE_NAIL_PARTICLE TRUE // If set to TRUE, it updates Curse's nail. -#define B_NEW_BATON_PASS_BALL_PARTICLE TRUE // If set to TRUE, it updates Baton Pass' Poké Ball sprite. -#define B_NEW_MORNING_SUN_STAR_PARTICLE TRUE // If set to TRUE, it updates Morning Sun's star particles. -#define B_NEW_IMPACT_PALETTE TRUE // If set to TRUE, it updates the basic 'hit' palette. -#define B_NEW_SURF_PARTICLE_PALETTE TRUE // If set to TRUE, it updates Surf's wave palette. +#define B_NEW_SWORD_PARTICLE FALSE // If set to TRUE, it updates Swords Dance's particle. +#define B_NEW_LEECH_SEED_PARTICLE FALSE // If set to TRUE, it updates Leech Seed's animation particle. +#define B_NEW_HORN_ATTACK_PARTICLE FALSE // If set to TRUE, it updates Horn Attack's horn particle. +#define B_NEW_ROCKS_PARTICLE FALSE // If set to TRUE, it updates rock particles. +#define B_NEW_LEAF_PARTICLE FALSE // If set to TRUE, it updates leaf particle. +#define B_NEW_EMBER_PARTICLES FALSE // If set to TRUE, it updates Ember's fire particle. +#define B_NEW_MEAN_LOOK_PARTICLE FALSE // If set to TRUE, it updates Mean Look's eye particle. +#define B_NEW_TEETH_PARTICLE FALSE // If set to TRUE, it updates Bite/Crunch teeth particle. +#define B_NEW_HANDS_FEET_PARTICLE FALSE // If set to TRUE, it updates chop/kick/punch particles. +#define B_NEW_SPIKES_PARTICLE FALSE // If set to TRUE, it updates Spikes particle. +#define B_NEW_FLY_BUBBLE_PARTICLE FALSE // If set to TRUE, it updates Fly's 'bubble' particle. +#define B_NEW_CURSE_NAIL_PARTICLE FALSE // If set to TRUE, it updates Curse's nail. +#define B_NEW_BATON_PASS_BALL_PARTICLE FALSE // If set to TRUE, it updates Baton Pass' Poké Ball sprite. +#define B_NEW_MORNING_SUN_STAR_PARTICLE FALSE // If set to TRUE, it updates Morning Sun's star particles. +#define B_NEW_IMPACT_PALETTE FALSE // If set to TRUE, it updates the basic 'hit' palette. +#define B_NEW_SURF_PARTICLE_PALETTE FALSE // If set to TRUE, it updates Surf's wave palette. // Poké Ball animation and sounds #define B_ENEMY_THROW_BALLS GEN_LATEST // In GEN_6+, enemy Trainers throw Poké Balls into battle instead of them just appearing on the ground and opening. #define B_ENEMY_THROW_BALLS_SOUND GEN_LATEST // In GEN_5+, enemy Trainer's Poké Balls make a sound when thrown to send out a Pokémon. This can only be used when B_ENEMY_THROW_BALLS is set to GEN_6 or later. #define B_PLAYER_THROW_BALLS_SOUND GEN_LATEST // In GEN_5+, the player's Poké Balls make a sound when thrown to send out a Pokémon. +#define SHOW_TYPES_NEVER 0 +#define SHOW_TYPES_ALWAYS 1 +#define SHOW_TYPES_CAUGHT 2 +#define B_SHOW_TYPES SHOW_TYPES_NEVER // When defined as SHOW_TYPES_ALWAYS, after selecting "Fight" in battle, the types of all Pokemon are revealed. Whe defined as SHOW_TYPES_OWN, types are only revealed if the player owns the mon in question. + #endif // GUARD_CONFIG_BATTLE_H diff --git a/include/config/item.h b/include/config/item.h index 644a73ade6..272848e82e 100644 --- a/include/config/item.h +++ b/include/config/item.h @@ -19,6 +19,8 @@ #define I_BERRY_PRICE GEN_7 // Since Berries have become unplantable (Gen8+), their price has gone up. #define I_POWER_ITEM_BOOST GEN_LATEST // In Gen7+, Power Items grant 8 EVs instead of 4 EVs. #define I_PREMIER_BALL_BONUS GEN_LATEST // In LGPE onwards (Gen8+ here), you are given a Premier Ball for every 10 Poké Balls of any type and in the same purchase. Previously, it only applied to regular Poké Balls and only 1 could be obtained per purchase. +#define I_ROTOM_CATALOG_THUNDER_SHOCK GEN_LATEST // In Gen9+, reverting Rotom to its base form will teach it Thunder Shock even if it knows another move. +#define I_REPEL_INCLUDE_FAINTED GEN_LATEST // In Gen1 and Gen6+, Repels always use the level of the first member of the party to check which wild Pokémon to prevent encounters with, even if that member is fainted. In Gen2-5, it only uses the level of the first non-fainted Pokémon. // TM config #define I_REUSABLE_TMS FALSE // In Gen5-8, TMs are reusable. Setting this to TRUE will make all vanilla TMs reusable, though they can also be cherry-picked by setting their importance to 1. diff --git a/include/config/overworld.h b/include/config/overworld.h index b47cef5c50..63479f1831 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -33,6 +33,7 @@ #define OW_BERRY_GROWTH_RATE GEN_3 // Presets for how long each Berry plant takes to grow. #define OW_BERRY_YIELD_RATE GEN_3 // Presets for how many Berries each plant can yield. #define OW_BERRY_DRAIN_RATE GEN_6_ORAS // If OW_BERRY_MOISTURE is enabled, this setting changes how fast the soil dries out. GEN_4 uses a Berry-dependent drain rate, GEN_6_XY dries out in 24 hours (4 hours with the relevant Mulch) and GEN_6_ORAS dries out in 4 hours. Other values are illegal. +#define OW_BERRY_IMMORTAL FALSE // If enabled, once a Berry tree has grown a Berry, the tree will not disappear until picked by the player. // Overworld Pokémon #define OW_POKEMON_OBJECT_EVENTS TRUE // Adds Object Event fields for every species. Can be used for NPCs using the OBJ_EVENT_GFX_SPECIES macro (eg. OBJ_EVENT_GFX_SPECIES(BULBASAUR)) diff --git a/include/constants/battle.h b/include/constants/battle.h index 1f11adbd5f..f9800ef4b3 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -89,7 +89,6 @@ #define BATTLE_TWO_VS_ONE_OPPONENT ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gTrainerBattleOpponent_B == 0xFFFF)) #define BATTLE_TYPE_HAS_AI (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER | BATTLE_TYPE_INGAME_PARTNER) - // Battle Outcome defines #define B_OUTCOME_WON 1 #define B_OUTCOME_LOST 2 @@ -138,7 +137,7 @@ #define STATUS2_WRAPPED (1 << 13) #define STATUS2_POWDER (1 << 14) #define STATUS2_INFATUATION (1 << 16 | 1 << 17 | 1 << 18 | 1 << 19) // 4 bits, one for every battler -#define STATUS2_INFATUATED_WITH(battler) (gBitTable[battler] << 16) +#define STATUS2_INFATUATED_WITH(battler) (1u << (battler + 16)) #define STATUS2_DEFENSE_CURL (1 << 20) #define STATUS2_TRANSFORMED (1 << 21) #define STATUS2_RECHARGE (1 << 22) @@ -218,8 +217,8 @@ #define HITMARKER_OBEYS (1 << 25) #define HITMARKER_NEVER_SET (1 << 26) // Cleared as part of a large group. Never set or checked #define HITMARKER_CHARGING (1 << 27) -#define HITMARKER_FAINTED(battler) (gBitTable[battler] << 28) -#define HITMARKER_FAINTED2(battler) ((1 << 28) << battler) +#define HITMARKER_FAINTED(battler) (1u << (battler + 28)) +#define HITMARKER_FAINTED2(battler) HITMARKER_FAINTED(battler) #define HITMARKER_STRING_PRINTED (1 << 29) // Per-side statuses that affect an entire party diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index 389cd7e127..54573a4868 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -412,6 +412,10 @@ #define ANIM_TAG_TERA_CRYSTAL (ANIM_SPRITES_START + 398) #define ANIM_TAG_TERA_SHATTER (ANIM_SPRITES_START + 399) #define ANIM_TAG_DREEPY_SHINY (ANIM_SPRITES_START + 400) +#define ANIM_TAG_BLOOD_MOON (ANIM_SPRITES_START + 401) +#define ANIM_TAG_BEAM (ANIM_SPRITES_START + 402) +#define ANIM_TAG_RED_EXPLOSION (ANIM_SPRITES_START + 403) +#define ANIM_TAG_PURPLE_CHAIN (ANIM_SPRITES_START + 404) // battlers #define ANIM_ATTACKER 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 1e6e2d86d7..9529e026c1 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -712,8 +712,9 @@ #define STRINGID_FOGISDEEP 710 #define STRINGID_FOGLIFTED 711 #define STRINGID_PKMNMADESHELLGLEAM 712 +#define STRINGID_FICKLEBEAMDOUBLED 713 -#define BATTLESTRINGS_COUNT 713 +#define BATTLESTRINGS_COUNT 714 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, diff --git a/include/constants/event_objects.h b/include/constants/event_objects.h index e2ac7f7920..fccc206638 100644 --- a/include/constants/event_objects.h +++ b/include/constants/event_objects.h @@ -271,7 +271,7 @@ #define OBJ_EVENT_GFX_VAR_F (OBJ_EVENT_GFX_VARS + 0xF) #define OBJ_EVENT_GFX_MON_BASE 0x200 // 512 -#define OBJ_EVENT_GFX_SPECIES_BITS 11 +#define OBJ_EVENT_GFX_SPECIES_BITS 12 // This will need to be updated when NUM_SPECIES is > ~3.5k #define OBJ_EVENT_GFX_SPECIES_MASK ((1 << OBJ_EVENT_GFX_SPECIES_BITS) - 1) // Used to call a specific species' follower graphics. Useful for static encounters. diff --git a/include/data.h b/include/data.h index 69c1a19a3c..88111eb5c0 100644 --- a/include/data.h +++ b/include/data.h @@ -110,7 +110,9 @@ struct TypeInfo u16 maxMove; u16 teraTypeRGBValue; // Most values pulled from the Tera type icon palette. u16 damageCategory:2; // Used for B_PHYSICAL_SPECIAL_SPLIT <= GEN_3 - u16 padding:14; + u16 useSecondTypeIconPalette:1; + u16 isSpecialCaseType:1; + u16 padding:12; const u32 *const paletteTMHM; //u16 enhanceItem; //u16 berry; diff --git a/include/global.fieldmap.h b/include/global.fieldmap.h index c606eef8d3..29249712b6 100644 --- a/include/global.fieldmap.h +++ b/include/global.fieldmap.h @@ -130,7 +130,7 @@ struct MapEvents struct MapConnection { u8 direction; - u32 offset; + s32 offset; u8 mapGroup; u8 mapNum; }; diff --git a/include/graphics.h b/include/graphics.h index 01de060b79..1ec04f0056 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -2724,6 +2724,8 @@ extern const u32 gBattleAnimSpritePal_AuraSphere[]; extern const u32 gBattleAnimSpritePal_AvalancheRocks[]; extern const u32 gBattleAnimSpriteGfx_NewPokeball[]; extern const u32 gBattleAnimSpritePal_NewPokeball[]; +extern const u32 gBattleAnimSpriteGfx_Beam[]; +extern const u32 gBattleAnimSpritePal_Beam[]; extern const u32 gBattleAnimSpriteGfx_BerryEaten[]; extern const u32 gBattleAnimSpritePal_BerryEaten[]; extern const u32 gBattleAnimSpriteGfx_BerryNormal[]; @@ -2732,6 +2734,8 @@ extern const u32 gBattleAnimSpriteGfx_BigRock[]; extern const u32 gBattleAnimSpritePal_BigRock[]; extern const u32 gBattleAnimSpriteGfx_BlacephalonHead[]; extern const u32 gBattleAnimSpritePal_BlacephalonHead[]; +extern const u32 gBattleAnimSpriteGfx_BloodMoon[]; +extern const u32 gBattleAnimSpritePal_BloodMoon[]; extern const u32 gBattleAnimSpritePal_BlueFlare[]; extern const u32 gBattleAnimSpriteGfx_Branch[]; extern const u32 gBattleAnimSpritePal_Branch[]; @@ -2825,12 +2829,16 @@ extern const u32 gBattleAnimSpriteGfx_PoisonColumn[]; extern const u32 gBattleAnimSpritePal_PoisonColumn[]; extern const u32 gBattleAnimSpriteGfx_PowerTrick[]; extern const u32 gBattleAnimSpritePal_PowerTrick[]; +extern const u32 gBattleAnimSpriteGfx_PurpleChain[]; +extern const u32 gBattleAnimSpritePal_PurpleChain[]; extern const u32 gBattleAnimSpriteGfx_PurpleDrake[]; extern const u32 gBattleAnimSpritePal_PurpleDrake[]; extern const u32 gBattleAnimSpriteGfx_QuickGuard[]; extern const u32 gBattleAnimSpritePal_QuickGuard[]; extern const u32 gBattleAnimSpriteGfx_RazorShell[]; extern const u32 gBattleAnimSpritePal_RazorShell[]; +extern const u32 gBattleAnimSpriteGfx_RedExplosion[]; +extern const u32 gBattleAnimSpritePal_RedExplosion[]; extern const u32 gBattleAnimSpriteGfx_RocksSmall[]; extern const u32 gBattleAnimSpriteGfx_NewRocks[]; extern const u32 gBattleAnimSpritePal_NewRocks[]; @@ -3363,4 +3371,9 @@ extern const u8 gMailTilemap_Retro[]; extern const u8 gMonMarkingsMenu_Gfx[]; extern const u16 gMonMarkingsMenu_Pal[]; +extern const u32 gBattleIcons_Gfx1[]; +extern const u32 gBattleIcons_Gfx2[]; +extern const u32 gBattleIcons_Pal1[]; +extern const u32 gBattleIcons_Pal2[]; + #endif //GUARD_GRAPHICS_H diff --git a/include/pokemon.h b/include/pokemon.h index 8337890935..dcdbf43dec 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -441,7 +441,7 @@ struct SpeciesInfo /*0xC4*/ u32 dexForceRequired:1; // This species will be taken into account for Pokédex ratings even if they have the "isMythical" flag set. u32 tmIlliterate:1; // This species will be unable to learn the universal moves. u32 isFrontierBanned:1; // This species is not allowed to participate in Battle Frontier facilities. - u32 padding4:12; + u32 padding4:11; // Move Data /* 0x80 */ const struct LevelUpMove *levelUpLearnset; /* 0x84 */ const u16 *teachableLearnset; @@ -880,7 +880,6 @@ const u8 *GetMoveName(u16 moveId); const u8 *GetMoveAnimationScript(u16 moveId); void UpdateDaysPassedSinceFormChange(u16 days); void TrySetDayLimitToFormChange(struct Pokemon *mon); -u8 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler); -u8 CalculateHiddenPowerType(struct Pokemon *mon); +u32 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler); #endif // GUARD_POKEMON_H diff --git a/include/random.h b/include/random.h index cd7e26b589..b5ce987f39 100644 --- a/include/random.h +++ b/include/random.h @@ -6,25 +6,21 @@ #define ISO_RANDOMIZE1(val)(1103515245 * (val) + 24691) #define ISO_RANDOMIZE2(val)(1103515245 * (val) + 12345) -/* Some functions have been added to support HQ_RANDOM. +/* Some functions have been added to support Expansion's RNG implementation. * -* If using HQ_RANDOM, you cannot call Random() in interrupt handlers safely. -* AdvanceRandom() is provided to handle burning numbers in the VBlank handler -* if you choose to do that, and can be used regardless of HQ_RANDOM setting. +* LocalRandom(*val) provides a higher-quality replacement for uses of +* ISO_RANDOMIZE in vanilla Emerald. You can use LocalRandomSeed(u32) to +* create a local state. +* +* It is no longer possible to call Random() in interrupt handlers safely. +* AdvanceRandom() is provided to handle burning numbers in VBlank handlers. * If you need to use random numbers in the VBlank handler, a local state * should be used instead. * -* LocalRandom(*val) allows you to have local random states that are the same -* type as the global states regardless of HQ_RANDOM setting, which is useful -* if you want to be able to set them from or assign them to gRngValue. -* LocalRandomSeed(u32) returns a properly seeded rng_value_t. -* -* Random2_32() was added to HQ_RANDOM because the output of the generator is -* always 32 bits and Random()/Random2() are just wrappers in that mode. It is -* also available in non-HQ mode for consistency. +* Random2_32() was added, even though it is not used directly, because the +* underlying RNG always outputs 32 bits. */ -#if HQ_RANDOM == TRUE struct Sfc32State { u32 a; u32 b; @@ -70,40 +66,6 @@ static inline u16 Random2(void) } void AdvanceRandom(void); -#else -typedef u32 rng_value_t; - -#define RNG_VALUE_EMPTY 0 - -//Returns a 16-bit pseudorandom number -u16 Random(void); -u16 Random2(void); - -//Sets the initial seed value of the pseudorandom number generator -void SeedRng(u16 seed); -void SeedRng2(u16 seed); - -//Returns a 32-bit pseudorandom number -#define Random32() (Random() | (Random() << 16)) -#define Random2_32() (Random2() | (Random2() << 16)) - -static inline u16 LocalRandom(rng_value_t *val) -{ - *val = ISO_RANDOMIZE1(*val); - return *val >> 16; -} - -static inline void AdvanceRandom(void) -{ - Random(); -} - -static inline rng_value_t LocalRandomSeed(u32 seed) -{ - return seed; -} - -#endif extern rng_value_t gRngValue; extern rng_value_t gRng2Value; @@ -173,12 +135,14 @@ enum RandomTag RNG_G_MAX_BEFUDDLE, RNG_G_MAX_REPLENISH, RNG_G_MAX_SNOOZE, + RNG_HARVEST, RNG_HITS, RNG_HOLD_EFFECT_FLINCH, RNG_INFATUATION, RNG_LOADED_DICE, RNG_METRONOME, RNG_PARALYSIS, + RNG_PICKUP, RNG_POISON_POINT, RNG_POISON_TOUCH, RNG_RAMPAGE_TURNS, diff --git a/include/strings.h b/include/strings.h index 7ad99aad56..80df986993 100644 --- a/include/strings.h +++ b/include/strings.h @@ -986,23 +986,6 @@ extern const u8 gText_SomeonesPC[]; extern const u8 gText_PlayersPC[]; extern const u8 gText_WhichPCShouldBeAccessed[]; -extern const u8 gText_PokenavMatchCall_Strategy[]; -extern const u8 gText_PokenavMatchCall_TrainerPokemon[]; -extern const u8 gText_PokenavMatchCall_SelfIntroduction[]; -extern const u8 gText_Pokenav_ClearButtonList[]; -extern const u8 gText_PokenavMap_ZoomedOutButtons[]; -extern const u8 gText_PokenavMap_ZoomedInButtons[]; -extern const u8 gText_PokenavCondition_MonListButtons[]; -extern const u8 gText_PokenavCondition_MonStatusButtons[]; -extern const u8 gText_PokenavCondition_MarkingButtons[]; -extern const u8 gText_PokenavMatchCall_TrainerListButtons[]; -extern const u8 gText_PokenavMatchCall_CallMenuButtons[]; -extern const u8 gText_PokenavMatchCall_CheckTrainerButtons[]; -extern const u8 gText_PokenavRibbons_MonListButtons[]; -extern const u8 gText_PokenavRibbons_RibbonListButtons[]; -extern const u8 gText_PokenavRibbons_RibbonCheckButtons[]; -extern const u8 gText_Number2[]; - extern const u8 gText_Petalburg[]; extern const u8 gText_Slateport[]; extern const u8 gText_Enter2[]; @@ -2443,43 +2426,6 @@ extern const u8 MatchCall_Text_Phoebe[]; extern const u8 MatchCall_Text_Glacia[]; extern const u8 MatchCall_Text_Drake[]; extern const u8 MatchCall_Text_Wallace[]; -extern const u8 gText_MrStoneMatchCallDesc[]; -extern const u8 gText_MrStoneMatchCallName[]; -extern const u8 gText_StevenMatchCallDesc[]; -extern const u8 gText_StevenMatchCallName[]; -extern const u8 gText_MayBrendanMatchCallDesc[]; -extern const u8 gText_WallyMatchCallDesc[]; -extern const u8 gText_NormanMatchCallDesc[]; -extern const u8 gText_NormanMatchCallName[]; -extern const u8 gText_MomMatchCallDesc[]; -extern const u8 gText_MomMatchCallName[]; -extern const u8 gText_ScottMatchCallDesc[]; -extern const u8 gText_ScottMatchCallName[]; -extern const u8 gText_RoxanneMatchCallDesc[]; -extern const u8 gText_BrawlyMatchCallDesc[]; -extern const u8 gText_WattsonMatchCallDesc[]; -extern const u8 gText_FlanneryMatchCallDesc[]; -extern const u8 gText_WinonaMatchCallDesc[]; -extern const u8 gText_TateLizaMatchCallDesc[]; -extern const u8 gText_JuanMatchCallDesc[]; -extern const u8 gText_EliteFourMatchCallDesc[]; -extern const u8 gText_ChampionMatchCallDesc[]; -extern const u8 gText_ProfBirchMatchCallDesc[]; -extern const u8 gText_ProfBirchMatchCallName[]; -extern const u8 gText_MatchCallSteven_Strategy[]; -extern const u8 gText_MatchCallSteven_Pokemon[]; -extern const u8 gText_MatchCallSteven_Intro1_BeforeMeteorFallsBattle[]; -extern const u8 gText_MatchCallSteven_Intro2_BeforeMeteorFallsBattle[]; -extern const u8 gText_MatchCallSteven_Intro1_AfterMeteorFallsBattle[]; -extern const u8 gText_MatchCallSteven_Intro2_AfterMeteorFallsBattle[]; -extern const u8 gText_MatchCallBrendan_Strategy[]; -extern const u8 gText_MatchCallBrendan_Pokemon[]; -extern const u8 gText_MatchCallBrendan_Intro1[]; -extern const u8 gText_MatchCallBrendan_Intro2[]; -extern const u8 gText_MatchCallMay_Strategy[]; -extern const u8 gText_MatchCallMay_Pokemon[]; -extern const u8 gText_MatchCallMay_Intro1[]; -extern const u8 gText_MatchCallMay_Intro2[]; // Contest Link extern const u8 gText_ColorDarkGray[]; @@ -2897,37 +2843,6 @@ extern const u8 gText_CutenessContest[]; extern const u8 gText_SmartnessContest[]; extern const u8 gText_ToughnessContest[]; -// PokéNav Match Call -extern const u8 gText_CallCantBeMadeHere[]; -extern const u8 gText_NumberRegistered[]; -extern const u8 gText_NumberOfBattles[]; -extern const u8 gText_Unknown[]; -extern const u8 gText_TrainerCloseBy[]; -extern const u8 gText_Call[]; -extern const u8 gText_Check[]; -extern const u8 gText_Cancel6[]; - -// PokéNav Menu Handler -extern const u8 gText_CheckMapOfHoenn[]; -extern const u8 gText_CheckPokemonInDetail[]; -extern const u8 gText_CallRegisteredTrainer[]; -extern const u8 gText_CheckObtainedRibbons[]; -extern const u8 gText_PutAwayPokenav[]; -extern const u8 gText_CheckPartyPokemonInDetail[]; -extern const u8 gText_CheckAllPokemonInDetail[]; -extern const u8 gText_ReturnToPokenavMenu[]; -extern const u8 gText_FindCoolPokemon[]; -extern const u8 gText_FindBeautifulPokemon[]; -extern const u8 gText_FindCutePokemon[]; -extern const u8 gText_FindSmartPokemon[]; -extern const u8 gText_FindToughPokemon[]; -extern const u8 gText_ReturnToConditionMenu[]; -extern const u8 gText_NoRibbonWinners[]; - -// PokéNav -extern const u8 gText_NumberIndex[]; -extern const u8 gText_RibbonsF700[]; - // use_pokeblock extern const u8 gText_Coolness[]; extern const u8 gText_Toughness[]; diff --git a/include/test/battle.h b/include/test/battle.h index a44e813f82..865afe8e0b 100644 --- a/include/test/battle.h +++ b/include/test/battle.h @@ -328,7 +328,7 @@ * * MOVE(battler, move | moveSlot:, [gimmick:], [hit:], [criticalHit:], [target:], [allowed:], [WITH_RNG(tag, value]) * Used when the battler chooses Fight. Either the move ID or move slot - * must be specified. gimmick: GIMMICK_MEGA causes the battler to Mega + * must be specified. gimmick: GIMMICK_MEGA causes the battler to Mega * Evolve if able, hit: FALSE causes the move to miss, criticalHit: TRUE * causes the move to land a critical hit, target: is used in double * battles to choose the target (when necessary), and allowed: FALSE is diff --git a/include/tilesets.h b/include/tilesets.h index c7cc8edac9..b495b6c52c 100644 --- a/include/tilesets.h +++ b/include/tilesets.h @@ -7,4 +7,7 @@ extern const u16 gTilesetPalettes_General[][16]; extern const struct Tileset * const gTilesetPointer_SecretBase; extern const struct Tileset * const gTilesetPointer_SecretBaseRedCave; +extern const struct Tileset gTileset_Building; +extern const struct Tileset gTileset_BrendansMaysHouse; + #endif //GUARD_tilesets_H diff --git a/include/type_icons.h b/include/type_icons.h new file mode 100644 index 0000000000..1d6a312f07 --- /dev/null +++ b/include/type_icons.h @@ -0,0 +1,18 @@ +#ifndef GUARD_TYPE_ICONS_H +#define GUARD_TYPE_ICONS_H + +void LoadTypeIcons(u32); + +#define TYPE_ICON_TAG 0x2720 +#define TYPE_ICON_TAG_2 0x2721 +#define NUM_FRAMES_HIDE_TYPE_ICON 10 + +#define tMonPosition data[0] +#define tBattlerId data[1] +#define tHideIconTimer data[2] +#define tVerticalPosition data[3] + +#define TYPE_ICON_1_FRAME(monType) ((monType - 1) * 2) +#define TYPE_ICON_2_FRAME(monType) ((monType - 11) * 2) + +#endif // GUARD_TYPE_ICONS_H diff --git a/include/util.h b/include/util.h index 3c90f136a6..fcc4e37bb1 100644 --- a/include/util.h +++ b/include/util.h @@ -4,7 +4,6 @@ #include "sprite.h" extern const u8 gMiscBlank_Gfx[]; // unused in Emerald -extern const u32 gBitTable[]; u8 CreateInvisibleSpriteWithCallback(void (*)(struct Sprite *)); void StoreWordInTwoHalfwords(u16 *, u32); diff --git a/ld_script.ld b/ld_script.ld deleted file mode 100644 index a0c069c965..0000000000 --- a/ld_script.ld +++ /dev/null @@ -1,1391 +0,0 @@ -ENTRY(Start) - -gNumMusicPlayers = 4; -gMaxLines = 0; -gInitialMainCB2 = CB2_InitCopyrightScreenAfterBootup; - -MEMORY -{ - EWRAM (rwx) : ORIGIN = 0x2000000, LENGTH = 256K - IWRAM (rwx) : ORIGIN = 0x3000000, LENGTH = 32K - ROM (rx) : ORIGIN = 0x8000000, LENGTH = 32M -} - -SECTIONS { - - .ewram ORIGIN(EWRAM) : AT (__ewram_lma) - ALIGN(4) - { - __ewram_start = .; - *(.ewram*) - __ewram_end = .; - } > EWRAM - - .ewram.sbss (NOLOAD) : - ALIGN(4) - { - INCLUDE "sym_ewram.ld" - src/*.o(.sbss); - gflib/*.o(.sbss); - - *libc.a:impure.o(.data); - *libc.a:locale.o(.data); - *libc.a:mallocr.o(.data); - } > EWRAM - - .iwram ORIGIN(IWRAM) : AT (__iwram_lma) - ALIGN(4) - { - __iwram_start = .; - *(.iwram*); - __iwram_end = .; - } > IWRAM - - .iwram.bss (NOLOAD) : - ALIGN(4) - { - /* .bss starts at 0x3000000 */ - INCLUDE "sym_bss.ld" - src/*.o(.bss); - gflib/*.o(.bss); - data/*.o(.bss); - - /* .bss.code starts at 0x3001AA8 */ - src/m4a.o(.bss.code); - - /* COMMON starts at 0x30022A8 */ - INCLUDE "sym_common.ld" - *libc.a:sbrkr.o(COMMON); - } > IWRAM - - /* BEGIN ROM DATA */ - . = 0x8000000; - - .text : - ALIGN(4) - { - src/rom_header.o(.text); - src/rom_header_gf.o(.text.*); - src/rom_header_rhh.o(.text.*); - src/crt0.o(.text); - src/main.o(.text); - gflib/malloc.o(.text); - gflib/dma3_manager.o(.text); - gflib/gpu_regs.o(.text); - gflib/bg.o(.text); - gflib/blit.o(.text); - gflib/window.o(.text); - gflib/text.o(.text); - gflib/sprite.o(.text); - gflib/string_util.o(.text); - src/link.o(.text); - src/AgbRfu_LinkManager.o(.text); - src/link_rfu_3.o(.text); - src/link_rfu_2.o(.text); - src/union_room.o(.text); - src/mystery_gift_menu.o(.text); - src/union_room_player_avatar.o(.text); - src/wireless_communication_status_screen.o(.text); - src/union_room_battle.o(.text); - src/mystery_gift.o(.text); - src/mystery_gift_view.o(.text); - src/mystery_gift_server.o(.text); - src/mystery_gift_client.o(.text); - src/mystery_gift_link.o(.text); - src/wonder_news.o(.text); - src/union_room_chat.o(.text); - src/berry_crush.o(.text); - src/berry_powder.o(.text); - src/dodrio_berry_picking.o(.text); - src/pokemon_jump.o(.text); - src/minigame_countdown.o(.text); - src/rtc.o(.text); - src/main_menu.o(.text); - src/battle_controllers.o(.text); - src/decompress.o(.text); - src/digit_obj_util.o(.text); - src/battle_bg.o(.text); - src/battle_main.o(.text); - src/battle_util.o(.text); - src/battle_z_move.o(.text); - src/battle_script_commands.o(.text); - src/battle_util2.o(.text); - src/battle_controller_player.o(.text); - src/battle_gfx_sfx_util.o(.text); - src/battle_controller_opponent.o(.text); - src/battle_ai_switch_items.o(.text); - src/battle_controller_link_opponent.o(.text); - src/battle_debug.o(.text); - src/pokemon.o(.text); - src/trig.o(.text); - src/random.o(.text); - src/util.o(.text); - src/daycare.o(.text); - src/egg_hatch.o(.text); - src/battle_interface.o(.text); - src/battle_anim_smokescreen.o(.text); - src/pokeball.o(.text); - src/load_save.o(.text); - src/trade.o(.text); - src/berry_blender.o(.text); - src/play_time.o(.text); - src/new_game.o(.text); - src/overworld.o(.text); - src/fieldmap.o(.text); - src/metatile_behavior.o(.text); - src/field_camera.o(.text); - src/field_door.o(.text); - src/field_player_avatar.o(.text); - src/event_object_movement.o(.text); - src/follower_helper.o(.text); - src/field_message_box.o(.text); - src/event_object_lock.o(.text); - src/text_window.o(.text); - src/script.o(.text); - src/scrcmd.o(.text); - src/field_control_avatar.o(.text); - src/event_data.o(.text); - src/coord_event_weather.o(.text); - src/field_tasks.o(.text); - src/clock.o(.text); - src/reset_rtc_screen.o(.text); - src/start_menu.o(.text); - src/tileset_anims.o(.text); - src/palette.o(.text); - src/sound.o(.text); - src/battle_anim.o(.text); - src/battle_anim_mons.o(.text); - src/task.o(.text); - src/reshow_battle_screen.o(.text); - src/battle_anim_status_effects.o(.text); - src/title_screen.o(.text); - src/field_weather.o(.text); - src/field_weather_effect.o(.text); - src/field_screen_effect.o(.text); - src/battle_setup.o(.text); - src/cable_club.o(.text); - src/trainer_see.o(.text); - src/wild_encounter.o(.text); - src/field_effect.o(.text); - src/scanline_effect.o(.text); - src/option_menu.o(.text); - src/pokedex.o(.text); - src/trainer_card.o(.text); - src/frontier_pass.o(.text); - src/pokemon_storage_system.o(.text); - src/pokemon_icon.o(.text); - src/script_movement.o(.text); - src/fldeff_cut.o(.text); - src/mail_data.o(.text); - src/map_name_popup.o(.text); - src/item_menu_icons.o(.text); - src/battle_anim_mon_movement.o(.text); - src/item.o(.text); - src/contest.o(.text); - src/shop.o(.text); - src/fldeff_escalator.o(.text); - src/berry.o(.text); - src/script_menu.o(.text); - src/naming_screen.o(.text); - src/money.o(.text); - src/contest_effect.o(.text); - src/record_mixing.o(.text); - src/secret_base.o(.text); - src/tv.o(.text); - src/contest_util.o(.text); - src/script_pokemon_util.o(.text); - src/field_poison.o(.text); - src/pokemon_size_record.o(.text); - src/fldeff_misc.o(.text); - src/field_special_scene.o(.text); - src/rotating_gate.o(.text); - src/safari_zone.o(.text); - src/contest_link.o(.text); - src/item_use.o(.text); - src/battle_anim_effects_1.o(.text); - src/battle_anim_effects_2.o(.text); - src/battle_anim_water.o(.text); - src/battle_anim_fire.o(.text); - src/battle_anim_electric.o(.text); - src/battle_anim_ice.o(.text); - src/battle_anim_fight.o(.text); - src/battle_anim_poison.o(.text); - src/battle_anim_flying.o(.text); - src/battle_anim_psychic.o(.text); - src/battle_anim_bug.o(.text); - src/battle_anim_rock.o(.text); - src/battle_anim_ghost.o(.text); - src/battle_anim_dragon.o(.text); - src/battle_anim_dark.o(.text); - src/battle_anim_ground.o(.text); - src/battle_anim_normal.o(.text); - src/battle_anim_utility_funcs.o(.text); - src/battle_anim_new.o(.text); - src/battle_intro.o(.text); - src/bike.o(.text); - src/easy_chat.o(.text); - src/mon_markings.o(.text); - src/mauville_old_man.o(.text); - src/mail.o(.text); - src/menu_helpers.o(.text); - src/dewford_trend.o(.text); - src/heal_location.o(.text); - src/region_map.o(.text); - src/image_processing_effects.o(.text); - src/decoration.o(.text); - src/slot_machine.o(.text); - src/contest_painting.o(.text); - src/battle_ai_main.o(.text); - src/battle_ai_util.o(.text); - src/trader.o(.text); - src/starter_choose.o(.text); - src/wallclock.o(.text); - src/fldeff_rocksmash.o(.text); - src/fldeff_dig.o(.text); - src/pokeblock.o(.text); - src/fldeff_flash.o(.text); - src/post_battle_event_funcs.o(.text); - src/time_events.o(.text); - src/birch_pc.o(.text); - src/hof_pc.o(.text); - src/field_specials.o(.text); - src/battle_records.o(.text); - src/pokedex_area_screen.o(.text); - src/evolution_scene.o(.text); - src/roulette.o(.text); - src/pokedex_cry_screen.o(.text); - src/coins.o(.text); - src/landmark.o(.text); - src/fldeff_strength.o(.text); - src/battle_transition.o(.text); - src/battle_controller_link_partner.o(.text); - src/battle_message.o(.text); - src/cable_car.o(.text); - src/math_util.o(.text); - src/palette_util.o(.text); - src/confetti_util.o(.text); - src/save.o(.text); - src/mystery_event_script.o(.text); - src/field_effect_helpers.o(.text); - src/contest_ai.o(.text); - src/battle_anim_sound_tasks.o(.text); - src/battle_controller_safari.o(.text); - src/fldeff_sweetscent.o(.text); - src/battle_anim_effects_3.o(.text); - src/move_relearner.o(.text); - src/fldeff_softboiled.o(.text); - src/decoration_inventory.o(.text); - src/roamer.o(.text); - src/battle_tower.o(.text); - src/use_pokeblock.o(.text); - src/battle_controller_wally.o(.text); - src/player_pc.o(.text); - src/intro.o(.text); - src/reload_save.o(.text); - src/field_region_map.o(.text); - src/battle_anim_throw.o(.text); - src/hall_of_fame.o(.text); - src/credits.o(.text); - src/lottery_corner.o(.text); - src/diploma.o(.text); - src/berry_tag_screen.o(.text); - src/mystery_event_menu.o(.text); - src/save_failed_screen.o(.text); - src/braille_puzzles.o(.text); - src/pokeblock_feed.o(.text); - src/clear_save_data_screen.o(.text); - src/intro_credits_graphics.o(.text); - src/evolution_graphics.o(.text); - src/bard_music.o(.text); - src/fldeff_teleport.o(.text); - src/battle_tv.o(.text); - src/pokemon_animation.o(.text); - src/recorded_battle.o(.text); - src/battle_controller_recorded_opponent.o(.text); - src/battle_controller_recorded_player.o(.text); - src/trainer_pokemon_sprites.o(.text); - src/lilycove_lady.o(.text); - src/battle_dome.o(.text); - src/battle_palace.o(.text); - src/match_call.o(.text); - src/menu.o(.text); - src/battle_factory_screen.o(.text); - src/apprentice.o(.text); - src/frontier_util.o(.text); - src/battle_arena.o(.text); - src/battle_factory.o(.text); - src/battle_pike.o(.text); - src/rotating_tile_puzzle.o(.text); - src/battle_pyramid.o(.text); - src/item_menu.o(.text); - src/list_menu.o(.text); - src/dynamic_placeholder_text_util.o(.text); - src/save_location.o(.text); - src/item_icon.o(.text); - src/party_menu.o(.text); - src/battle_tent.o(.text); - src/braille.o(.text); - src/multiboot.o(.text); - src/berry_fix_graphics.o(.text); - src/battle_controller_player_partner.o(.text); - src/mirage_tower.o(.text); - src/berry_fix_program.o(.text); - src/pokemon_summary_screen.o(.text); - src/pokedex_area_region_map.o(.text); - src/battle_pyramid_bag.o(.text); - src/pokenav.o(.text); - src/pokenav_main_menu.o(.text); - src/pokenav_list.o(.text); - src/pokenav_menu_handler.o(.text); - src/pokenav_menu_handler_gfx.o(.text); - src/pokenav_match_call_list.o(.text); - src/pokenav_match_call_gfx.o(.text); - src/pokenav_region_map.o(.text); - src/pokenav_conditions.o(.text); - src/pokenav_conditions_gfx.o(.text); - src/pokenav_conditions_search_results.o(.text); - src/pokenav_ribbons_list.o(.text); - src/pokenav_ribbons_summary.o(.text); - src/pokenav_match_call_data.o(.text); - src/menu_specialized.o(.text); - src/ereader_helpers.o(.text); - src/faraway_island.o(.text); - src/ereader_screen.o(.text); - src/trainer_hill.o(.text); - src/rayquaza_scene.o(.text); - src/walda_phrase.o(.text); - src/contest_link_util.o(.text); - src/gym_leader_rematch.o(.text); - src/battle_transition_frontier.o(.text); - src/international_string_util.o(.text); - src/pokemon_sprite_visualizer.o(.text); - src/expansion_intro.o(.text); - } > ROM =0 - - script_data : - ALIGN(4) - { - data/event_scripts.o(script_data); - data/battle_anim_scripts.o(script_data); - data/battle_scripts_1.o(script_data); - data/field_effect_scripts.o(script_data); - data/battle_scripts_2.o(script_data); - data/contest_ai_scripts.o(script_data); - data/mystery_event_script_cmd_table.o(script_data); - } > ROM =0 - - lib_text : - ALIGN(4) - { - src/libgcnmultiboot.o(.text); - src/m4a_1.o(.text); - src/m4a.o(.text); - src/agb_flash.o(.text); - src/agb_flash_1m.o(.text); - src/agb_flash_mx.o(.text); - src/siirtc.o(.text); - src/librfu_stwi.o(.text); - src/librfu_intr.o(.text); - src/librfu_rfu.o(.text); - src/librfu_sio32id.o(.text); - src/libisagbprn.o(.text); - *libagbsyscall.a:ArcTan2.o(.text); - *libagbsyscall.a:BgAffineSet.o(.text); - *libagbsyscall.a:CpuFastSet.o(.text); - *libagbsyscall.a:CpuSet.o(.text); - *libagbsyscall.a:Div.o(.text); - *libagbsyscall.a:LZ77UnCompVram.o(.text); - *libagbsyscall.a:LZ77UnCompWram.o(.text); - *libagbsyscall.a:MultiBoot.o(.text); - *libagbsyscall.a:ObjAffineSet.o(.text); - *libagbsyscall.a:RLUnCompVram.o(.text); - *libagbsyscall.a:RLUnCompWram.o(.text); - *libagbsyscall.a:RegisterRamReset.o(.text); - *libagbsyscall.a:SoftReset.o(.text); - *libagbsyscall.a:Sqrt.o(.text); - *libagbsyscall.a:VBlankIntrWait.o(.text); - *libgcc.a:_call_via_rX.o(.text); - *libgcc.a:_divdi3.o(.text); - *libgcc.a:_divsi3.o(.text); - *libgcc.a:_dvmd_tls.o(.text); - *libgcc.a:_fixunsdfsi.o(.text); - *libgcc.a:_fixunssfsi.o(.text); - *libgcc.a:_modsi3.o(.text); - *libgcc.a:_muldi3.o(.text); - *libgcc.a:_udivdi3.o(.text); - *libgcc.a:_udivsi3.o(.text); - *libgcc.a:_umodsi3.o(.text); - *libgcc.a:dp-bit.o(.text); - *libgcc.a:fp-bit.o(.text); - *libgcc.a:_lshrdi3.o(.text); - *libgcc.a:_negdi2.o(.text); - *libc.a:memcpy.o(.text); - *libc.a:memset.o(.text); - *libc.a:strcmp.o(.text); - *libc.a:strcpy.o(.text); - *libc.a:impure.o(.text); - *libc.a:vsprintf.o(.text); - *libc.a:vfprintf.o(.text); - *libc.a:wsetup.o(.text); - *libc.a:dtoa.o(.text); - *libc.a:fflush.o(.text); - *libc.a:findfp.o(.text); - *libc.a:freer.o(.text); - *libc.a:mtrim.o(.text); - *libc.a:fvwrite.o(.text); - *libc.a:fwalk.o(.text); - *libc.a:locale.o(.text); - *libc.a:makebuf.o(.text); - *libc.a:mallocr.o(.text); - *libc.a:mbtowc_r.o(.text); - *libc.a:memchr.o(.text); - *libc.a:memmove.o(.text); - *libc.a:mlock.o(.text); - *libc.a:mprec.o(.text); - *libc.a:s_isinf.o(.text); - *libc.a:s_isnan.o(.text); - *libc.a:sbrkr.o(.text); - *libc.a:stdio.o(.text); - *libc.a:strlen.o(.text); - *libc.a:syscalls.o(.text); - *libc.a:writer.o(.text); - *libc.a:callocr.o(.text); - *libc.a:closer.o(.text); - *libc.a:errno.o(.text); - *libc.a:fstatr.o(.text); - *libc.a:libcfunc.o(.text); - *libc.a:lseekr.o(.text); - *libc.a:readr.o(.text); - } > ROM =0 - - .rodata : - ALIGN(4) - { - src/rom_header.o(.rodata); - src/rom_header_gf.o(.rodata); - src/main.o(.rodata); - gflib/bg.o(.rodata); - gflib/window.o(.rodata); - gflib/text.o(.rodata); - gflib/sprite.o(.rodata); - gflib/io_reg.o(.rodata); - gflib/string_util.o(.rodata); - src/link.o(.rodata); - src/link.o(.rodata.str1.4); - src/AgbRfu_LinkManager.o(.rodata); - src/link_rfu_3.o(.rodata); - src/link_rfu_2.o(.rodata); - src/link_rfu_2.o(.rodata.str1.4); - src/union_room.o(.rodata); - src/mystery_gift_menu.o(.rodata); - src/union_room_player_avatar.o(.rodata); - src/wireless_communication_status_screen.o(.rodata); - src/union_room_battle.o(.rodata); - src/mystery_gift.o(.rodata); - src/mystery_gift_view.o(.rodata); - src/mystery_gift_server.o(.rodata); - src/mystery_gift_client.o(.rodata); - src/mystery_gift_scripts.o(.rodata); - src/wonder_news.o(.rodata); - src/union_room_chat.o(.rodata); - src/berry_crush.o(.rodata); - src/berry_powder.o(.rodata); - src/dodrio_berry_picking.o(.rodata); - src/pokemon_jump.o(.rodata); - src/minigame_countdown.o(.rodata); - src/rtc.o(.rodata); - src/main_menu.o(.rodata); - src/battle_controllers.o(.rodata); - src/digit_obj_util.o(.rodata); - src/data.o(.rodata); - src/battle_bg.o(.rodata); - src/battle_main.o(.rodata); - src/battle_util.o(.rodata); - src/battle_z_move.o(.rodata); - src/battle_script_commands.o(.rodata); - src/battle_controller_player.o(.rodata); - src/battle_anim_smokescreen.o(.rodata); - src/battle_controller_opponent.o(.rodata); - src/battle_ai_switch_items.o(.rodata); - src/battle_controller_link_opponent.o(.rodata); - src/battle_debug.o(.rodata); - src/pokemon.o(.rodata); - src/trig.o(.rodata); - src/util.o(.rodata); - src/daycare.o(.rodata); - src/egg_hatch.o(.rodata); - src/battle_gfx_sfx_util.o(.rodata); - src/battle_interface.o(.rodata); - src/pokeball.o(.rodata); - src/trade.o(.rodata); - src/berry_blender.o(.rodata); - src/new_game.o(.rodata); - src/overworld.o(.rodata); - src/tilesets.o(.rodata); - data/maps.o(.rodata); - src/fieldmap.o(.rodata); - src/metatile_behavior.o(.rodata); - src/field_door.o(.rodata); - src/field_player_avatar.o(.rodata); - src/event_object_movement.o(.rodata); - src/follower_helper.o(.rodata); - src/text_window.o(.rodata); - src/scrcmd.o(.rodata); - src/field_control_avatar.o(.rodata); - src/coord_event_weather.o(.rodata); - src/field_tasks.o(.rodata); - src/reset_rtc_screen.o(.rodata); - src/start_menu.o(.rodata); - src/tileset_anims.o(.rodata); - src/palette.o(.rodata); - src/sound.o(.rodata); - src/battle_anim.o(.rodata); - src/battle_anim_mons.o(.rodata); - data/map_events.o(.rodata); - src/reshow_battle_screen.o(.rodata); - src/battle_anim_status_effects.o(.rodata); - src/title_screen.o(.rodata); - src/field_weather.o(.rodata); - src/field_weather_effect.o(.rodata); - src/field_screen_effect.o(.rodata); - src/battle_setup.o(.rodata); - src/cable_club.o(.rodata); - src/trainer_see.o(.rodata); - src/wild_encounter.o(.rodata); - src/field_effect.o(.rodata); - src/scanline_effect.o(.rodata); - src/option_menu.o(.rodata); - src/pokedex.o(.rodata); - src/trainer_card.o(.rodata); - src/frontier_pass.o(.rodata); - src/pokemon_storage_system.o(.rodata); - src/pokemon_icon.o(.rodata); - src/fldeff_cut.o(.rodata); - src/map_name_popup.o(.rodata); - src/item_menu_icons.o(.rodata); - src/battle_anim_mon_movement.o(.rodata); - src/item.o(.rodata); - src/contest.o(.rodata); - src/shop.o(.rodata); - src/fldeff_escalator.o(.rodata); - src/berry.o(.rodata); - src/script_menu.o(.rodata); - src/naming_screen.o(.rodata); - src/money.o(.rodata); - src/contest_effect.o(.rodata); - src/record_mixing.o(.rodata); - src/secret_base.o(.rodata); - src/tv.o(.rodata); - src/contest_util.o(.rodata); - src/script_pokemon_util.o(.rodata); - src/pokemon_size_record.o(.rodata) - src/fldeff_misc.o(.rodata); - src/field_special_scene.o(.rodata); - src/rotating_gate.o(.rodata); - src/contest_link.o(.rodata); - src/item_use.o(.rodata); - src/battle_anim_effects_1.o(.rodata); - src/battle_anim_effects_2.o(.rodata); - src/battle_anim_water.o(.rodata); - src/battle_anim_fire.o(.rodata); - src/battle_anim_electric.o(.rodata); - src/battle_anim_ice.o(.rodata); - src/battle_anim_fight.o(.rodata); - src/battle_anim_poison.o(.rodata); - src/battle_anim_flying.o(.rodata); - src/battle_anim_psychic.o(.rodata); - src/battle_anim_bug.o(.rodata); - src/battle_anim_rock.o(.rodata); - src/battle_anim_ghost.o(.rodata); - src/battle_anim_dragon.o(.rodata); - src/battle_anim_dark.o(.rodata); - src/battle_anim_ground.o(.rodata); - src/battle_anim_normal.o(.rodata); - src/battle_anim_utility_funcs.o(.rodata); - src/battle_anim_new.o(.rodata); - src/battle_intro.o(.rodata); - src/bike.o(.rodata); - src/easy_chat.o(.rodata); - src/mon_markings.o(.rodata); - src/mauville_old_man.o(.rodata); - src/mail.o(.rodata); - src/menu_helpers.o(.rodata); - src/heal_location.o(.rodata); - src/region_map.o(.rodata); - src/image_processing_effects.o(.rodata); - src/decoration.o(.rodata); - src/slot_machine.o(.rodata); - src/contest_painting.o(.rodata); - src/battle_ai_main.o(.rodata); - src/battle_ai_util.o(.rodata); - src/trader.o(.rodata); - src/starter_choose.o(.rodata); - src/wallclock.o(.rodata); - src/pokeblock.o(.rodata); - src/fldeff_flash.o(.rodata); - src/time_events.o(.rodata); - src/field_specials.o(.rodata); - src/battle_records.o(.rodata); - src/pokedex_area_screen.o(.rodata); - src/evolution_scene.o(.rodata); - src/roulette.o(.rodata); - src/pokedex_cry_screen.o(.rodata); - src/landmark.o(.rodata); - src/battle_transition.o(.rodata); - src/battle_controller_link_partner.o(.rodata); - src/battle_message.o(.rodata); - src/cable_car.o(.rodata); - src/save.o(.rodata); - src/field_effect_helpers.o(.rodata); - src/contest_ai.o(.rodata); - src/battle_anim_sound_tasks.o(.rodata); - src/battle_controller_safari.o(.rodata); - src/battle_anim_effects_3.o(.rodata); - src/move_relearner.o(.rodata); - src/roamer.o(.rodata); - src/battle_tower.o(.rodata); - src/use_pokeblock.o(.rodata); - src/battle_controller_wally.o(.rodata); - src/player_pc.o(.rodata); - src/intro.o(.rodata); - src/field_region_map.o(.rodata); - src/battle_anim_throw.o(.rodata); - src/hall_of_fame.o(.rodata); - src/credits.o(.rodata); - src/lottery_corner.o(.rodata); - src/diploma.o(.rodata); - src/strings.o(.rodata); - src/berry_tag_screen.o(.rodata); - src/mystery_event_menu.o(.rodata); - src/save_failed_screen.o(.rodata); - src/braille_puzzles.o(.rodata); - src/pokeblock_feed.o(.rodata); - src/clear_save_data_screen.o(.rodata); - src/intro_credits_graphics.o(.rodata); - src/evolution_graphics.o(.rodata); - src/bard_music.o(.rodata); - src/battle_tv.o(.rodata); - src/pokemon_animation.o(.rodata); - src/battle_controller_recorded_opponent.o(.rodata); - src/battle_controller_recorded_player.o(.rodata); - src/trainer_pokemon_sprites.o(.rodata); - src/lilycove_lady.o(.rodata); - src/battle_dome.o(.rodata); - src/battle_palace.o(.rodata); - src/match_call.o(.rodata); - src/menu.o(.rodata); - src/battle_factory_screen.o(.rodata); - src/apprentice.o(.rodata); - src/frontier_util.o(.rodata); - src/battle_arena.o(.rodata); - src/battle_factory.o(.rodata); - src/battle_pike.o(.rodata); - src/rotating_tile_puzzle.o(.rodata); - src/battle_pyramid.o(.rodata); - src/item_menu.o(.rodata); - src/list_menu.o(.rodata); - src/save_location.o(.rodata); - src/item_icon.o(.rodata); - src/party_menu.o(.rodata); - src/battle_tent.o(.rodata); - src/braille.o(.rodata); - src/multiboot.o(.rodata); - src/berry_fix_graphics.o(.rodata); - src/battle_controller_player_partner.o(.rodata); - src/mirage_tower.o(.rodata); - src/berry_fix_program.o(.rodata); - src/pokemon_summary_screen.o(.rodata); - src/pokedex_area_region_map.o(.rodata); - src/battle_pyramid_bag.o(.rodata); - src/pokenav.o(.rodata); - src/pokenav_main_menu.o(.rodata); - src/pokenav_list.o(.rodata); - src/pokenav_menu_handler.o(.rodata); - src/pokenav_menu_handler_gfx.o(.rodata); - src/pokenav_match_call_list.o(.rodata); - src/pokenav_match_call_gfx.o(.rodata); - src/pokenav_region_map.o(.rodata); - src/pokenav_conditions_gfx.o(.rodata); - src/pokenav_conditions_search_results.o(.rodata); - src/pokenav_ribbons_list.o(.rodata); - src/pokenav_ribbons_summary.o(.rodata); - src/pokenav_match_call_data.o(.rodata); - src/menu_specialized.o(.rodata); - src/ereader_helpers.o(.rodata); - src/faraway_island.o(.rodata); - src/ereader_screen.o(.rodata); - src/trainer_hill.o(.rodata); - src/rayquaza_scene.o(.rodata); - src/walda_phrase.o(.rodata); - src/gym_leader_rematch.o(.rodata); - src/battle_transition_frontier.o(.rodata); - src/text_input_strings.o(.rodata); - src/fonts.o(.rodata); - src/international_string_util.o(.rodata); - src/mystery_event_msg.o(.rodata); - data/mystery_gift.o(.rodata); - src/m4a_tables.o(.rodata); - data/sound_data.o(.rodata); - src/pokemon_sprite_visualizer.o(.rodata); - src/expansion_intro.o(.rodata); - } > ROM =0 - - song_data : - ALIGN(4) - { - sound/songs/midi/mus_dummy.o(.rodata); - sound/songs/midi/se_use_item.o(.rodata); - sound/songs/midi/se_pc_login.o(.rodata); - sound/songs/midi/se_pc_off.o(.rodata); - sound/songs/midi/se_pc_on.o(.rodata); - sound/songs/midi/se_select.o(.rodata); - sound/songs/se_win_open.o(.rodata); - sound/songs/se_wall_hit.o(.rodata); - sound/songs/midi/se_door.o(.rodata); - sound/songs/midi/se_exit.o(.rodata); - sound/songs/midi/se_ledge.o(.rodata); - sound/songs/midi/se_bike_bell.o(.rodata); - sound/songs/midi/se_not_effective.o(.rodata); - sound/songs/midi/se_effective.o(.rodata); - sound/songs/midi/se_super_effective.o(.rodata); - sound/songs/midi/se_ball_open.o(.rodata); - sound/songs/midi/se_faint.o(.rodata); - sound/songs/midi/se_flee.o(.rodata); - sound/songs/midi/se_sliding_door.o(.rodata); - sound/songs/midi/se_ship.o(.rodata); - sound/songs/midi/se_bang.o(.rodata); - sound/songs/midi/se_pin.o(.rodata); - sound/songs/midi/se_boo.o(.rodata); - sound/songs/midi/se_ball.o(.rodata); - sound/songs/midi/se_contest_place.o(.rodata); - sound/songs/midi/se_a.o(.rodata); - sound/songs/midi/se_i.o(.rodata); - sound/songs/midi/se_u.o(.rodata); - sound/songs/midi/se_e.o(.rodata); - sound/songs/midi/se_o.o(.rodata); - sound/songs/midi/se_n.o(.rodata); - sound/songs/midi/se_success.o(.rodata); - sound/songs/midi/se_failure.o(.rodata); - sound/songs/midi/se_exp.o(.rodata); - sound/songs/midi/se_bike_hop.o(.rodata); - sound/songs/midi/se_switch.o(.rodata); - sound/songs/midi/se_click.o(.rodata); - sound/songs/midi/se_fu_zaku.o(.rodata); - sound/songs/midi/se_contest_condition_lose.o(.rodata); - sound/songs/midi/se_lavaridge_fall_warp.o(.rodata); - sound/songs/midi/se_ice_stairs.o(.rodata); - sound/songs/midi/se_ice_break.o(.rodata); - sound/songs/midi/se_ice_crack.o(.rodata); - sound/songs/midi/se_fall.o(.rodata); - sound/songs/midi/se_unlock.o(.rodata); - sound/songs/midi/se_warp_in.o(.rodata); - sound/songs/midi/se_warp_out.o(.rodata); - sound/songs/midi/se_repel.o(.rodata); - sound/songs/midi/se_rotating_gate.o(.rodata); - sound/songs/midi/se_truck_move.o(.rodata); - sound/songs/midi/se_truck_stop.o(.rodata); - sound/songs/midi/se_truck_unload.o(.rodata); - sound/songs/midi/se_truck_door.o(.rodata); - sound/songs/midi/se_berry_blender.o(.rodata); - sound/songs/midi/se_card.o(.rodata); - sound/songs/midi/se_save.o(.rodata); - sound/songs/midi/se_ball_bounce_1.o(.rodata); - sound/songs/midi/se_ball_bounce_2.o(.rodata); - sound/songs/midi/se_ball_bounce_3.o(.rodata); - sound/songs/midi/se_ball_bounce_4.o(.rodata); - sound/songs/midi/se_ball_trade.o(.rodata); - sound/songs/midi/se_ball_throw.o(.rodata); - sound/songs/midi/se_note_c.o(.rodata); - sound/songs/midi/se_note_d.o(.rodata); - sound/songs/midi/se_note_e.o(.rodata); - sound/songs/midi/se_note_f.o(.rodata); - sound/songs/midi/se_note_g.o(.rodata); - sound/songs/midi/se_note_a.o(.rodata); - sound/songs/midi/se_note_b.o(.rodata); - sound/songs/midi/se_note_c_high.o(.rodata); - sound/songs/midi/se_puddle.o(.rodata); - sound/songs/midi/se_bridge_walk.o(.rodata); - sound/songs/midi/se_itemfinder.o(.rodata); - sound/songs/midi/se_ding_dong.o(.rodata); - sound/songs/midi/se_balloon_red.o(.rodata); - sound/songs/midi/se_balloon_blue.o(.rodata); - sound/songs/midi/se_balloon_yellow.o(.rodata); - sound/songs/midi/se_breakable_door.o(.rodata); - sound/songs/midi/se_mud_ball.o(.rodata); - sound/songs/midi/se_field_poison.o(.rodata); - sound/songs/midi/se_escalator.o(.rodata); - sound/songs/midi/se_thunderstorm.o(.rodata); - sound/songs/midi/se_thunderstorm_stop.o(.rodata); - sound/songs/midi/se_downpour.o(.rodata); - sound/songs/midi/se_downpour_stop.o(.rodata); - sound/songs/midi/se_rain.o(.rodata); - sound/songs/midi/se_rain_stop.o(.rodata); - sound/songs/midi/se_thunder.o(.rodata); - sound/songs/midi/se_thunder2.o(.rodata); - sound/songs/midi/se_elevator.o(.rodata); - sound/songs/midi/se_low_health.o(.rodata); - sound/songs/midi/se_exp_max.o(.rodata); - sound/songs/midi/se_roulette_ball.o(.rodata); - sound/songs/midi/se_roulette_ball2.o(.rodata); - sound/songs/midi/se_taillow_wing_flap.o(.rodata); - sound/songs/midi/se_shop.o(.rodata); - sound/songs/midi/se_contest_heart.o(.rodata); - sound/songs/midi/se_contest_curtain_rise.o(.rodata); - sound/songs/midi/se_contest_curtain_fall.o(.rodata); - sound/songs/midi/se_contest_icon_change.o(.rodata); - sound/songs/midi/se_contest_icon_clear.o(.rodata); - sound/songs/midi/se_contest_mons_turn.o(.rodata); - sound/songs/midi/se_shiny.o(.rodata); - sound/songs/midi/se_intro_blast.o(.rodata); - sound/songs/midi/se_mugshot.o(.rodata); - sound/songs/midi/se_applause.o(.rodata); - sound/songs/midi/se_vend.o(.rodata); - sound/songs/midi/se_orb.o(.rodata); - sound/songs/se_dex_scroll.o(.rodata); - sound/songs/se_dex_page.o(.rodata); - sound/songs/midi/se_pokenav_on.o(.rodata); - sound/songs/midi/se_pokenav_off.o(.rodata); - sound/songs/midi/se_dex_search.o(.rodata); - sound/songs/midi/se_egg_hatch.o(.rodata); - sound/songs/midi/se_ball_tray_enter.o(.rodata); - sound/songs/midi/se_ball_tray_ball.o(.rodata); - sound/songs/midi/se_ball_tray_exit.o(.rodata); - sound/songs/midi/se_glass_flute.o(.rodata); - sound/songs/se_m_thunderbolt.o(.rodata); - sound/songs/se_m_thunderbolt2.o(.rodata); - sound/songs/se_m_harden.o(.rodata); - sound/songs/se_m_nightmare.o(.rodata); - sound/songs/se_m_vital_throw.o(.rodata); - sound/songs/se_m_vital_throw2.o(.rodata); - sound/songs/se_m_bubble.o(.rodata); - sound/songs/se_m_bubble2.o(.rodata); - sound/songs/se_m_bubble3.o(.rodata); - sound/songs/se_m_rain_dance.o(.rodata); - sound/songs/midi/se_m_cut.o(.rodata); - sound/songs/se_m_string_shot.o(.rodata); - sound/songs/se_m_string_shot2.o(.rodata); - sound/songs/se_m_rock_throw.o(.rodata); - sound/songs/midi/se_m_gust.o(.rodata); - sound/songs/midi/se_m_gust2.o(.rodata); - sound/songs/midi/se_m_double_slap.o(.rodata); - sound/songs/se_m_double_team.o(.rodata); - sound/songs/midi/se_m_razor_wind.o(.rodata); - sound/songs/se_m_icy_wind.o(.rodata); - sound/songs/se_m_thunder_wave.o(.rodata); - sound/songs/midi/se_m_comet_punch.o(.rodata); - sound/songs/midi/se_m_mega_kick.o(.rodata); - sound/songs/midi/se_m_mega_kick2.o(.rodata); - sound/songs/se_m_crabhammer.o(.rodata); - sound/songs/midi/se_m_jump_kick.o(.rodata); - sound/songs/se_m_flame_wheel.o(.rodata); - sound/songs/se_m_flame_wheel2.o(.rodata); - sound/songs/se_m_flamethrower.o(.rodata); - sound/songs/midi/se_m_fire_punch.o(.rodata); - sound/songs/se_m_toxic.o(.rodata); - sound/songs/se_m_sacred_fire.o(.rodata); - sound/songs/se_m_sacred_fire2.o(.rodata); - sound/songs/se_m_ember.o(.rodata); - sound/songs/midi/se_m_take_down.o(.rodata); - sound/songs/se_m_blizzard.o(.rodata); - sound/songs/se_m_blizzard2.o(.rodata); - sound/songs/midi/se_m_scratch.o(.rodata); - sound/songs/midi/se_m_vicegrip.o(.rodata); - sound/songs/midi/se_m_wing_attack.o(.rodata); - sound/songs/midi/se_m_fly.o(.rodata); - sound/songs/midi/se_m_sand_attack.o(.rodata); - sound/songs/midi/se_m_razor_wind2.o(.rodata); - sound/songs/se_m_bite.o(.rodata); - sound/songs/midi/se_m_headbutt.o(.rodata); - sound/songs/se_m_surf.o(.rodata); - sound/songs/se_m_hydro_pump.o(.rodata); - sound/songs/se_m_whirlpool.o(.rodata); - sound/songs/midi/se_m_horn_attack.o(.rodata); - sound/songs/midi/se_m_tail_whip.o(.rodata); - sound/songs/se_m_mist.o(.rodata); - sound/songs/se_m_poison_powder.o(.rodata); - sound/songs/midi/se_m_bind.o(.rodata); - sound/songs/se_m_dragon_rage.o(.rodata); - sound/songs/se_m_sing.o(.rodata); - sound/songs/se_m_perish_song.o(.rodata); - sound/songs/midi/se_m_pay_day.o(.rodata); - sound/songs/se_m_dig.o(.rodata); - sound/songs/se_m_dizzy_punch.o(.rodata); - sound/songs/se_m_self_destruct.o(.rodata); - sound/songs/se_m_explosion.o(.rodata); - sound/songs/se_m_absorb_2.o(.rodata); - sound/songs/se_m_absorb.o(.rodata); - sound/songs/se_m_screech.o(.rodata); - sound/songs/se_m_bubble_beam.o(.rodata); - sound/songs/se_m_bubble_beam2.o(.rodata); - sound/songs/se_m_supersonic.o(.rodata); - sound/songs/se_m_belly_drum.o(.rodata); - sound/songs/se_m_metronome.o(.rodata); - sound/songs/se_m_bonemerang.o(.rodata); - sound/songs/se_m_lick.o(.rodata); - sound/songs/se_m_psybeam.o(.rodata); - sound/songs/se_m_faint_attack.o(.rodata); - sound/songs/midi/se_m_swords_dance.o(.rodata); - sound/songs/midi/se_m_leer.o(.rodata); - sound/songs/se_m_swagger.o(.rodata); - sound/songs/se_m_swagger2.o(.rodata); - sound/songs/se_m_heal_bell.o(.rodata); - sound/songs/se_m_confuse_ray.o(.rodata); - sound/songs/se_m_snore.o(.rodata); - sound/songs/se_m_brick_break.o(.rodata); - sound/songs/se_m_giga_drain.o(.rodata); - sound/songs/se_m_psybeam2.o(.rodata); - sound/songs/se_m_solar_beam.o(.rodata); - sound/songs/se_m_petal_dance.o(.rodata); - sound/songs/se_m_teleport.o(.rodata); - sound/songs/se_m_minimize.o(.rodata); - sound/songs/se_m_sketch.o(.rodata); - sound/songs/se_m_swift.o(.rodata); - sound/songs/se_m_reflect.o(.rodata); - sound/songs/se_m_barrier.o(.rodata); - sound/songs/se_m_detect.o(.rodata); - sound/songs/se_m_lock_on.o(.rodata); - sound/songs/se_m_moonlight.o(.rodata); - sound/songs/se_m_charm.o(.rodata); - sound/songs/se_m_charge.o(.rodata); - sound/songs/se_m_strength.o(.rodata); - sound/songs/se_m_hyper_beam.o(.rodata); - sound/songs/se_m_waterfall.o(.rodata); - sound/songs/se_m_reversal.o(.rodata); - sound/songs/se_m_acid_armor.o(.rodata); - sound/songs/se_m_sandstorm.o(.rodata); - sound/songs/se_m_tri_attack.o(.rodata); - sound/songs/se_m_tri_attack2.o(.rodata); - sound/songs/se_m_encore.o(.rodata); - sound/songs/se_m_encore2.o(.rodata); - sound/songs/se_m_baton_pass.o(.rodata); - sound/songs/se_m_milk_drink.o(.rodata); - sound/songs/se_m_attract.o(.rodata); - sound/songs/se_m_attract2.o(.rodata); - sound/songs/se_m_morning_sun.o(.rodata); - sound/songs/se_m_flatter.o(.rodata); - sound/songs/se_m_sand_tomb.o(.rodata); - sound/songs/se_m_grasswhistle.o(.rodata); - sound/songs/se_m_spit_up.o(.rodata); - sound/songs/se_m_dive.o(.rodata); - sound/songs/se_m_earthquake.o(.rodata); - sound/songs/se_m_twister.o(.rodata); - sound/songs/se_m_sweet_scent.o(.rodata); - sound/songs/se_m_yawn.o(.rodata); - sound/songs/se_m_sky_uppercut.o(.rodata); - sound/songs/se_m_stat_increase.o(.rodata); - sound/songs/se_m_heat_wave.o(.rodata); - sound/songs/se_m_uproar.o(.rodata); - sound/songs/se_m_hail.o(.rodata); - sound/songs/se_m_cosmic_power.o(.rodata); - sound/songs/se_m_teeter_dance.o(.rodata); - sound/songs/se_m_stat_decrease.o(.rodata); - sound/songs/se_m_haze.o(.rodata); - sound/songs/se_m_hyper_beam2.o(.rodata); - sound/songs/midi/se_rg_door.o(.rodata); - sound/songs/midi/se_rg_card_flip.o(.rodata); - sound/songs/midi/se_rg_card_flipping.o(.rodata); - sound/songs/midi/se_rg_card_open.o(.rodata); - sound/songs/midi/se_rg_bag_cursor.o(.rodata); - sound/songs/midi/se_rg_bag_pocket.o(.rodata); - sound/songs/midi/se_rg_ball_click.o(.rodata); - sound/songs/midi/se_rg_shop.o(.rodata); - sound/songs/midi/se_rg_ss_anne_horn.o(.rodata); - sound/songs/midi/se_rg_help_open.o(.rodata); - sound/songs/midi/se_rg_help_close.o(.rodata); - sound/songs/midi/se_rg_help_error.o(.rodata); - sound/songs/midi/se_rg_deoxys_move.o(.rodata); - sound/songs/midi/se_rg_poke_jump_success.o(.rodata); - sound/songs/midi/se_rg_poke_jump_failure.o(.rodata); - sound/songs/midi/se_pokenav_call.o(.rodata); - sound/songs/midi/se_pokenav_hang_up.o(.rodata); - sound/songs/midi/se_arena_timeup1.o(.rodata); - sound/songs/midi/se_arena_timeup2.o(.rodata); - sound/songs/midi/se_pike_curtain_close.o(.rodata); - sound/songs/midi/se_pike_curtain_open.o(.rodata); - sound/songs/midi/se_sudowoodo_shake.o(.rodata); - sound/songs/midi/mus_littleroot_test.o(.rodata); - sound/songs/midi/mus_gsc_route38.o(.rodata); - sound/songs/midi/mus_caught.o(.rodata); - sound/songs/midi/mus_victory_wild.o(.rodata); - sound/songs/midi/mus_victory_gym_leader.o(.rodata); - sound/songs/midi/mus_victory_league.o(.rodata); - sound/songs/midi/mus_c_comm_center.o(.rodata); - sound/songs/midi/mus_gsc_pewter.o(.rodata); - sound/songs/midi/mus_c_vs_legend_beast.o(.rodata); - sound/songs/midi/mus_route101.o(.rodata); - sound/songs/midi/mus_route110.o(.rodata); - sound/songs/midi/mus_route120.o(.rodata); - sound/songs/midi/mus_petalburg.o(.rodata); - sound/songs/midi/mus_oldale.o(.rodata); - sound/songs/midi/mus_gym.o(.rodata); - sound/songs/midi/mus_surf.o(.rodata); - sound/songs/midi/mus_petalburg_woods.o(.rodata); - sound/songs/midi/mus_level_up.o(.rodata); - sound/songs/midi/mus_heal.o(.rodata); - sound/songs/midi/mus_obtain_badge.o(.rodata); - sound/songs/midi/mus_obtain_item.o(.rodata); - sound/songs/midi/mus_evolved.o(.rodata); - sound/songs/midi/mus_obtain_tmhm.o(.rodata); - sound/songs/midi/mus_lilycove_museum.o(.rodata); - sound/songs/midi/mus_route122.o(.rodata); - sound/songs/midi/mus_oceanic_museum.o(.rodata); - sound/songs/midi/mus_evolution_intro.o(.rodata); - sound/songs/midi/mus_evolution.o(.rodata); - sound/songs/midi/mus_move_deleted.o(.rodata); - sound/songs/midi/mus_encounter_girl.o(.rodata); - sound/songs/midi/mus_encounter_male.o(.rodata); - sound/songs/midi/mus_abandoned_ship.o(.rodata); - sound/songs/midi/mus_fortree.o(.rodata); - sound/songs/midi/mus_birch_lab.o(.rodata); - sound/songs/midi/mus_b_tower_rs.o(.rodata); - sound/songs/midi/mus_encounter_swimmer.o(.rodata); - sound/songs/midi/mus_cave_of_origin.o(.rodata); - sound/songs/midi/mus_obtain_berry.o(.rodata); - sound/songs/midi/mus_awaken_legend.o(.rodata); - sound/songs/midi/mus_slots_jackpot.o(.rodata); - sound/songs/midi/mus_slots_win.o(.rodata); - sound/songs/midi/mus_too_bad.o(.rodata); - sound/songs/midi/mus_roulette.o(.rodata); - sound/songs/midi/mus_link_contest_p1.o(.rodata); - sound/songs/midi/mus_link_contest_p2.o(.rodata); - sound/songs/midi/mus_link_contest_p3.o(.rodata); - sound/songs/midi/mus_link_contest_p4.o(.rodata); - sound/songs/midi/mus_encounter_rich.o(.rodata); - sound/songs/midi/mus_verdanturf.o(.rodata); - sound/songs/midi/mus_rustboro.o(.rodata); - sound/songs/midi/mus_poke_center.o(.rodata); - sound/songs/midi/mus_route104.o(.rodata); - sound/songs/midi/mus_route119.o(.rodata); - sound/songs/midi/mus_cycling.o(.rodata); - sound/songs/midi/mus_poke_mart.o(.rodata); - sound/songs/midi/mus_littleroot.o(.rodata); - sound/songs/midi/mus_mt_chimney.o(.rodata); - sound/songs/midi/mus_encounter_female.o(.rodata); - sound/songs/midi/mus_lilycove.o(.rodata); - sound/songs/midi/mus_route111.o(.rodata); - sound/songs/midi/mus_help.o(.rodata); - sound/songs/midi/mus_underwater.o(.rodata); - sound/songs/midi/mus_victory_trainer.o(.rodata); - sound/songs/midi/mus_title.o(.rodata); - sound/songs/midi/mus_intro.o(.rodata); - sound/songs/midi/mus_encounter_may.o(.rodata); - sound/songs/midi/mus_encounter_intense.o(.rodata); - sound/songs/midi/mus_encounter_cool.o(.rodata); - sound/songs/midi/mus_route113.o(.rodata); - sound/songs/midi/mus_encounter_aqua.o(.rodata); - sound/songs/midi/mus_follow_me.o(.rodata); - sound/songs/midi/mus_encounter_brendan.o(.rodata); - sound/songs/midi/mus_ever_grande.o(.rodata); - sound/songs/midi/mus_encounter_suspicious.o(.rodata); - sound/songs/midi/mus_victory_aqua_magma.o(.rodata); - sound/songs/midi/mus_cable_car.o(.rodata); - sound/songs/midi/mus_game_corner.o(.rodata); - sound/songs/midi/mus_dewford.o(.rodata); - sound/songs/midi/mus_safari_zone.o(.rodata); - sound/songs/midi/mus_victory_road.o(.rodata); - sound/songs/midi/mus_aqua_magma_hideout.o(.rodata); - sound/songs/midi/mus_sailing.o(.rodata); - sound/songs/midi/mus_mt_pyre.o(.rodata); - sound/songs/midi/mus_slateport.o(.rodata); - sound/songs/midi/mus_mt_pyre_exterior.o(.rodata); - sound/songs/midi/mus_school.o(.rodata); - sound/songs/midi/mus_hall_of_fame.o(.rodata); - sound/songs/midi/mus_fallarbor.o(.rodata); - sound/songs/midi/mus_sealed_chamber.o(.rodata); - sound/songs/midi/mus_contest_winner.o(.rodata); - sound/songs/midi/mus_contest.o(.rodata); - sound/songs/midi/mus_encounter_magma.o(.rodata); - sound/songs/midi/mus_intro_battle.o(.rodata); - sound/songs/midi/mus_abnormal_weather.o(.rodata); - sound/songs/midi/mus_weather_groudon.o(.rodata); - sound/songs/midi/mus_sootopolis.o(.rodata); - sound/songs/midi/mus_contest_results.o(.rodata); - sound/songs/midi/mus_hall_of_fame_room.o(.rodata); - sound/songs/midi/mus_trick_house.o(.rodata); - sound/songs/midi/mus_encounter_twins.o(.rodata); - sound/songs/midi/mus_encounter_elite_four.o(.rodata); - sound/songs/midi/mus_encounter_hiker.o(.rodata); - sound/songs/midi/mus_contest_lobby.o(.rodata); - sound/songs/midi/mus_encounter_interviewer.o(.rodata); - sound/songs/midi/mus_encounter_champion.o(.rodata); - sound/songs/midi/mus_credits.o(.rodata); - sound/songs/midi/mus_end.o(.rodata); - sound/songs/midi/mus_b_frontier.o(.rodata); - sound/songs/midi/mus_b_arena.o(.rodata); - sound/songs/midi/mus_obtain_b_points.o(.rodata); - sound/songs/midi/mus_register_match_call.o(.rodata); - sound/songs/midi/mus_b_pyramid.o(.rodata); - sound/songs/midi/mus_b_pyramid_top.o(.rodata); - sound/songs/midi/mus_b_palace.o(.rodata); - sound/songs/midi/mus_rayquaza_appears.o(.rodata); - sound/songs/midi/mus_b_tower.o(.rodata); - sound/songs/midi/mus_obtain_symbol.o(.rodata); - sound/songs/midi/mus_b_dome.o(.rodata); - sound/songs/midi/mus_b_pike.o(.rodata); - sound/songs/midi/mus_b_factory.o(.rodata); - sound/songs/midi/mus_vs_rayquaza.o(.rodata); - sound/songs/midi/mus_vs_frontier_brain.o(.rodata); - sound/songs/midi/mus_vs_mew.o(.rodata); - sound/songs/midi/mus_b_dome_lobby.o(.rodata); - sound/songs/midi/mus_vs_wild.o(.rodata); - sound/songs/midi/mus_vs_aqua_magma.o(.rodata); - sound/songs/midi/mus_vs_trainer.o(.rodata); - sound/songs/midi/mus_vs_gym_leader.o(.rodata); - sound/songs/midi/mus_vs_champion.o(.rodata); - sound/songs/midi/mus_vs_regi.o(.rodata); - sound/songs/midi/mus_vs_kyogre_groudon.o(.rodata); - sound/songs/midi/mus_vs_rival.o(.rodata); - sound/songs/midi/mus_vs_elite_four.o(.rodata); - sound/songs/midi/mus_vs_aqua_magma_leader.o(.rodata); - sound/songs/midi/mus_rg_follow_me.o(.rodata); - sound/songs/midi/mus_rg_game_corner.o(.rodata); - sound/songs/midi/mus_rg_rocket_hideout.o(.rodata); - sound/songs/midi/mus_rg_gym.o(.rodata); - sound/songs/midi/mus_rg_jigglypuff.o(.rodata); - sound/songs/midi/mus_rg_intro_fight.o(.rodata); - sound/songs/midi/mus_rg_title.o(.rodata); - sound/songs/midi/mus_rg_cinnabar.o(.rodata); - sound/songs/midi/mus_rg_lavender.o(.rodata); - sound/songs/midi/mus_rg_heal.o(.rodata); - sound/songs/midi/mus_rg_cycling.o(.rodata); - sound/songs/midi/mus_rg_encounter_rocket.o(.rodata); - sound/songs/midi/mus_rg_encounter_girl.o(.rodata); - sound/songs/midi/mus_rg_encounter_boy.o(.rodata); - sound/songs/midi/mus_rg_hall_of_fame.o(.rodata); - sound/songs/midi/mus_rg_viridian_forest.o(.rodata); - sound/songs/midi/mus_rg_mt_moon.o(.rodata); - sound/songs/midi/mus_rg_poke_mansion.o(.rodata); - sound/songs/midi/mus_rg_credits.o(.rodata); - sound/songs/midi/mus_rg_route1.o(.rodata); - sound/songs/midi/mus_rg_route24.o(.rodata); - sound/songs/midi/mus_rg_route3.o(.rodata); - sound/songs/midi/mus_rg_route11.o(.rodata); - sound/songs/midi/mus_rg_victory_road.o(.rodata); - sound/songs/midi/mus_rg_vs_gym_leader.o(.rodata); - sound/songs/midi/mus_rg_vs_trainer.o(.rodata); - sound/songs/midi/mus_rg_vs_wild.o(.rodata); - sound/songs/midi/mus_rg_vs_champion.o(.rodata); - sound/songs/midi/mus_rg_pallet.o(.rodata); - sound/songs/midi/mus_rg_oak_lab.o(.rodata); - sound/songs/midi/mus_rg_oak.o(.rodata); - sound/songs/midi/mus_rg_poke_center.o(.rodata); - sound/songs/midi/mus_rg_ss_anne.o(.rodata); - sound/songs/midi/mus_rg_surf.o(.rodata); - sound/songs/midi/mus_rg_poke_tower.o(.rodata); - sound/songs/midi/mus_rg_silph.o(.rodata); - sound/songs/midi/mus_rg_fuchsia.o(.rodata); - sound/songs/midi/mus_rg_celadon.o(.rodata); - sound/songs/midi/mus_rg_victory_trainer.o(.rodata); - sound/songs/midi/mus_rg_victory_wild.o(.rodata); - sound/songs/midi/mus_rg_victory_gym_leader.o(.rodata); - sound/songs/midi/mus_rg_vermillion.o(.rodata); - sound/songs/midi/mus_rg_pewter.o(.rodata); - sound/songs/midi/mus_rg_encounter_rival.o(.rodata); - sound/songs/midi/mus_rg_rival_exit.o(.rodata); - sound/songs/midi/mus_rg_dex_rating.o(.rodata); - sound/songs/midi/mus_rg_obtain_key_item.o(.rodata); - sound/songs/midi/mus_rg_caught_intro.o(.rodata); - sound/songs/midi/mus_rg_photo.o(.rodata); - sound/songs/midi/mus_rg_game_freak.o(.rodata); - sound/songs/midi/mus_rg_caught.o(.rodata); - sound/songs/midi/mus_rg_new_game_instruct.o(.rodata); - sound/songs/midi/mus_rg_new_game_intro.o(.rodata); - sound/songs/midi/mus_rg_new_game_exit.o(.rodata); - sound/songs/midi/mus_rg_poke_jump.o(.rodata); - sound/songs/midi/mus_rg_union_room.o(.rodata); - sound/songs/midi/mus_rg_net_center.o(.rodata); - sound/songs/midi/mus_rg_mystery_gift.o(.rodata); - sound/songs/midi/mus_rg_berry_pick.o(.rodata); - sound/songs/midi/mus_rg_sevii_cave.o(.rodata); - sound/songs/midi/mus_rg_teachy_tv_show.o(.rodata); - sound/songs/midi/mus_rg_sevii_route.o(.rodata); - sound/songs/midi/mus_rg_sevii_dungeon.o(.rodata); - sound/songs/midi/mus_rg_sevii_123.o(.rodata); - sound/songs/midi/mus_rg_sevii_45.o(.rodata); - sound/songs/midi/mus_rg_sevii_67.o(.rodata); - sound/songs/midi/mus_rg_poke_flute.o(.rodata); - sound/songs/midi/mus_rg_vs_deoxys.o(.rodata); - sound/songs/midi/mus_rg_vs_mewtwo.o(.rodata); - sound/songs/midi/mus_rg_vs_legend.o(.rodata); - sound/songs/midi/mus_rg_encounter_gym_leader.o(.rodata); - sound/songs/midi/mus_rg_encounter_deoxys.o(.rodata); - sound/songs/midi/mus_rg_trainer_tower.o(.rodata); - sound/songs/midi/mus_rg_slow_pallet.o(.rodata); - sound/songs/midi/mus_rg_teachy_tv_menu.o(.rodata); - sound/songs/midi/ph_trap_blend.o(.rodata); - sound/songs/midi/ph_trap_held.o(.rodata); - sound/songs/midi/ph_trap_solo.o(.rodata); - sound/songs/midi/ph_face_blend.o(.rodata); - sound/songs/midi/ph_face_held.o(.rodata); - sound/songs/midi/ph_face_solo.o(.rodata); - sound/songs/midi/ph_cloth_blend.o(.rodata); - sound/songs/midi/ph_cloth_held.o(.rodata); - sound/songs/midi/ph_cloth_solo.o(.rodata); - sound/songs/midi/ph_dress_blend.o(.rodata); - sound/songs/midi/ph_dress_held.o(.rodata); - sound/songs/midi/ph_dress_solo.o(.rodata); - sound/songs/midi/ph_fleece_blend.o(.rodata); - sound/songs/midi/ph_fleece_held.o(.rodata); - sound/songs/midi/ph_fleece_solo.o(.rodata); - sound/songs/midi/ph_kit_blend.o(.rodata); - sound/songs/midi/ph_kit_held.o(.rodata); - sound/songs/midi/ph_kit_solo.o(.rodata); - sound/songs/midi/ph_price_blend.o(.rodata); - sound/songs/midi/ph_price_held.o(.rodata); - sound/songs/midi/ph_price_solo.o(.rodata); - sound/songs/midi/ph_lot_blend.o(.rodata); - sound/songs/midi/ph_lot_held.o(.rodata); - sound/songs/midi/ph_lot_solo.o(.rodata); - sound/songs/midi/ph_goat_blend.o(.rodata); - sound/songs/midi/ph_goat_held.o(.rodata); - sound/songs/midi/ph_goat_solo.o(.rodata); - sound/songs/midi/ph_thought_blend.o(.rodata); - sound/songs/midi/ph_thought_held.o(.rodata); - sound/songs/midi/ph_thought_solo.o(.rodata); - sound/songs/midi/ph_choice_blend.o(.rodata); - sound/songs/midi/ph_choice_held.o(.rodata); - sound/songs/midi/ph_choice_solo.o(.rodata); - sound/songs/midi/ph_mouth_blend.o(.rodata); - sound/songs/midi/ph_mouth_held.o(.rodata); - sound/songs/midi/ph_mouth_solo.o(.rodata); - sound/songs/midi/ph_foot_blend.o(.rodata); - sound/songs/midi/ph_foot_held.o(.rodata); - sound/songs/midi/ph_foot_solo.o(.rodata); - sound/songs/midi/ph_goose_blend.o(.rodata); - sound/songs/midi/ph_goose_held.o(.rodata); - sound/songs/midi/ph_goose_solo.o(.rodata); - sound/songs/midi/ph_strut_blend.o(.rodata); - sound/songs/midi/ph_strut_held.o(.rodata); - sound/songs/midi/ph_strut_solo.o(.rodata); - sound/songs/midi/ph_cure_blend.o(.rodata); - sound/songs/midi/ph_cure_held.o(.rodata); - sound/songs/midi/ph_cure_solo.o(.rodata); - sound/songs/midi/ph_nurse_blend.o(.rodata); - sound/songs/midi/ph_nurse_held.o(.rodata); - sound/songs/midi/ph_nurse_solo.o(.rodata); - } > ROM =0 - - lib_rodata : - SUBALIGN(4) - { - src/m4a.o(.rodata); - src/agb_flash.o(.rodata); - src/agb_flash_1m.o(.rodata); - src/agb_flash_mx.o(.rodata); - src/agb_flash_le.o(.rodata); - src/siirtc.o(.rodata); - src/librfu_rfu.o(.rodata); - src/librfu_sio32id.o(.rodata); - *libgcc.a:_divdi3.o(.rodata); - *libgcc.a:_udivdi3.o(.rodata); - *libc.a:memcpy.o(.rodata); - *libc.a:memset.o(.rodata); - *libc.a:strcmp.o(.rodata); - *libc.a:strcpy.o(.rodata); - *libc.a:impure.o(.rodata); - *libc.a:vsprintf.o(.rodata); - *libc.a:vfprintf.o(.rodata); - *libc.a:wsetup.o(.rodata); - *libc.a:dtoa.o(.rodata); - *libc.a:fflush.o(.rodata); - *libc.a:findfp.o(.rodata); - *libc.a:freer.o(.rodata); - *libc.a:mtrim.o(.rodata); - *libc.a:fvwrite.o(.rodata); - *libc.a:fwalk.o(.rodata); - *libc.a:locale.o(.rodata); - *libc.a:makebuf.o(.rodata); - *libc.a:mallocr.o(.rodata); - *libc.a:mbtowc_r.o(.rodata); - *libc.a:memchr.o(.rodata); - *libc.a:memmove.o(.rodata); - *libc.a:mlock.o(.rodata); - *libc.a:mprec.o(.rodata); - *libc.a:s_isinf.o(.rodata); - *libc.a:s_isnan.o(.rodata); - *libc.a:sbrkr.o(.rodata); - *libc.a:stdio.o(.rodata); - *libc.a:strlen.o(.rodata); - *libc.a:syscalls.o(.rodata); - *libc.a:writer.o(.rodata); - *libc.a:callocr.o(.rodata); - *libc.a:closer.o(.rodata); - *libc.a:errno.o(.rodata); - *libc.a:fstatr.o(.rodata); - *libc.a:libcfunc.o(.rodata); - *libc.a:lseekr.o(.rodata); - *libc.a:readr.o(.rodata); - src/libisagbprn.o(.rodata); - } > ROM =0 - - multiboot_data : - ALIGN(4) - { - data/multiboot_ereader.o(.rodata); - data/multiboot_berry_glitch_fix.o(.rodata); - data/multiboot_pokemon_colosseum.o(.rodata); - } > ROM =0 - - gfx_data : - ALIGN(4) - { - src/graphics.o(.rodata); - } > ROM =0 - - extra : - ALIGN(4) - { - src/*.o(.text); - gflib/*.o(.text); - src/*.o(.rodata); - gflib/*.o(.rodata); - data/*.o(.rodata); - } > ROM = 0 - - .data.iwram : - ALIGN(4) - { - __iwram_lma = .; - . = . + (__iwram_end - __iwram_start); - } > ROM = 0 - - .data.ewram : - ALIGN(4) - { - __ewram_lma = .; - . = . + (__ewram_end - __ewram_start); - } > ROM = 0 - - __rom_end = .; - - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - - /* Discard everything not specifically mentioned above. */ - /DISCARD/ : - { - *(*); - } -} diff --git a/migration_scripts/1.8/item_ball_refactor.py b/migration_scripts/1.8/item_ball_refactor.py index f121978ec8..83d6f9f167 100755 --- a/migration_scripts/1.8/item_ball_refactor.py +++ b/migration_scripts/1.8/item_ball_refactor.py @@ -81,5 +81,5 @@ for file in pories_to_check: raw = re.sub("script %s[ \n]*\{[ \n]*finditem\((.*)\)[ \n]*\}[ \n]*" % unused, "", raw) with open(file, "w") as f2: f2.write(raw) - + print("Done!") diff --git a/migration_scripts/1.9/battle_anim_moves_refactor.py b/migration_scripts/1.9/battle_anim_moves_refactor.py index 116d3964c0..a7adac98ff 100644 --- a/migration_scripts/1.9/battle_anim_moves_refactor.py +++ b/migration_scripts/1.9/battle_anim_moves_refactor.py @@ -37,7 +37,7 @@ for line in lines: comment_split = line.split('//') if move and IsCommaMissing(comment_split[0]): line = comment_split[0].removesuffix('\n') + ',' + line[len(comment_split[0]):-1] + '\n' - + moves_info_lines.append(line) diff --git a/spritesheet_rules.mk b/spritesheet_rules.mk index 03e6b8a3b1..c10c9081f4 100644 --- a/spritesheet_rules.mk +++ b/spritesheet_rules.mk @@ -731,7 +731,7 @@ $(FLDEFFGFXDIR)/secret_power_tree.4bpp: %.4bpp: %.png $(FLDEFFGFXDIR)/record_mix_lights.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 4 -mheight 1 - + $(POKEMONGFXDIR)/question_mark/overworld.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 4 -mheight 4 diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 68c7bc770f..55b38f7ad7 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -174,7 +174,7 @@ static u32 GetAiFlags(u16 trainerId) flags = GetTrainerAIFlagsFromId(trainerId); } - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { flags |= AI_FLAG_DOUBLE_BATTLE; } @@ -224,7 +224,7 @@ void BattleAI_SetupFlags(void) { AI_THINKING_STRUCT->aiFlags[B_POSITION_PLAYER_RIGHT] = GetAiFlags(gPartnerTrainerId - TRAINER_PARTNER(PARTNER_NONE)); } - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsAiVsAiBattle()) + else if (IsDoubleBattle() && IsAiVsAiBattle()) { AI_THINKING_STRUCT->aiFlags[B_POSITION_PLAYER_RIGHT] = AI_THINKING_STRUCT->aiFlags[B_POSITION_PLAYER_LEFT]; } @@ -262,7 +262,7 @@ void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler) // Ignore moves that aren't possible to use. for (i = 0; i < MAX_MON_MOVES; i++) { - if (gBitTable[i] & moveLimitations) + if ((1u << i) & moveLimitations) SET_SCORE(battler, i, 0); } @@ -275,7 +275,7 @@ u32 BattleAI_ChooseMoveOrAction(void) { u32 ret; - if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + if (!IsDoubleBattle()) ret = ChooseMoveOrAction_Singles(sBattler_AI); else ret = ChooseMoveOrAction_Doubles(sBattler_AI); @@ -323,7 +323,7 @@ void Ai_InitPartyStruct(void) // Save first 2 or 4(in doubles) mons CopyBattlerDataToAIParty(B_POSITION_PLAYER_LEFT, B_SIDE_PLAYER); - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) CopyBattlerDataToAIParty(B_POSITION_PLAYER_RIGHT, B_SIDE_PLAYER); // If player's partner is AI, save opponent mons @@ -446,7 +446,7 @@ static void SetBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u3 if (move != 0 && move != 0xFFFF //&& gMovesInfo[move].power != 0 /* we want to get effectiveness and accuracy of status moves */ - && !(aiData->moveLimitations[battlerAtk] & gBitTable[i])) + && !(aiData->moveLimitations[battlerAtk] & (1u << i))) { if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_RISKY) dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, TRUE, weather, DMG_ROLL_HIGHEST); @@ -506,12 +506,12 @@ static bool32 AI_SwitchMonIfSuitable(u32 battler, bool32 doubleBattle) if (doubleBattle) { u32 partner = BATTLE_PARTNER(battler); - if (AI_DATA->shouldSwitchMon & gBitTable[partner] && AI_DATA->monToSwitchId[partner] == monToSwitchId) + if (AI_DATA->shouldSwitchMon & (1u << partner) && AI_DATA->monToSwitchId[partner] == monToSwitchId) { return FALSE; } } - AI_DATA->shouldSwitchMon |= gBitTable[battler]; + AI_DATA->shouldSwitchMon |= 1 << battler; AI_DATA->monToSwitchId[battler] = monToSwitchId; return TRUE; } @@ -1739,6 +1739,14 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_HIT_ESCAPE: break; + case EFFECT_CHILLY_RECEPTION: + if (CountUsablePartyMons(battlerAtk) == 0) + ADJUST_SCORE(-10); + else if (weather & (B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY) || IsMoveEffectWeather(aiData->partnerMove)) + ADJUST_SCORE(-8); + else if (weather & B_WEATHER_HAIL) + ADJUST_SCORE(-2); // mainly to prevent looping between hail and snow + break; case EFFECT_BELLY_DRUM: case EFFECT_FILLET_AWAY: if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY) @@ -2050,7 +2058,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } /*if (AI_THINKING_STRUCT->aiFlags[battlerAtk] == AI_SCRIPT_CHECK_BAD_MOVE //Only basic AI - && IS_DOUBLE_BATTLE) //Make the regular AI know how to use Protect minimally in Doubles + && IsDoubleBattle()) //Make the regular AI know how to use Protect minimally in Doubles { u8 shouldProtect = ShouldProtect(battlerAtk, battlerDef, move); if (shouldProtect == USE_PROTECT || shouldProtect == PROTECT_FROM_FOES) @@ -2773,6 +2781,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_SNOWSCAPE: case EFFECT_RAIN_DANCE: case EFFECT_SANDSTORM: + case EFFECT_CHILLY_RECEPTION: if (IsMoveEffectWeather(move)) ADJUST_SCORE(-10); break; @@ -2852,6 +2861,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_SNOWSCAPE: + case EFFECT_CHILLY_RECEPTION: if (IsBattlerAlive(battlerAtkPartner) && ShouldSetSnow(battlerAtkPartner, atkPartnerAbility, atkPartnerHoldEffect)) { @@ -3621,6 +3631,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) //fallthrough case EFFECT_HIT_ESCAPE: case EFFECT_PARTING_SHOT: + case EFFECT_CHILLY_RECEPTION: if (!IsDoubleBattle()) { switch (ShouldPivot(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, movesetIndex)) @@ -4056,7 +4067,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); // Force 'em out next turn break; default: - if (move != MOVE_BESTOW && aiData->items[battlerAtk] == ITEM_NONE) + if (gMovesInfo[gCurrentMove].effect != EFFECT_BESTOW && aiData->items[battlerAtk] == ITEM_NONE) { switch (aiData->holdEffects[battlerDef]) { @@ -4879,6 +4890,7 @@ static s32 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score case EFFECT_SANDSTORM: case EFFECT_HAIL: case EFFECT_SNOWSCAPE: + case EFFECT_CHILLY_RECEPTION: case EFFECT_GEOMANCY: case EFFECT_VICTORY_DANCE: ADJUST_SCORE(DECENT_EFFECT); diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index ef35a95f59..e2d0d85a3c 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -40,7 +40,7 @@ static void InitializeSwitchinCandidate(struct Pokemon *mon) static bool32 IsAceMon(u32 battler, u32 monPartyId) { if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_ACE_POKEMON - && !(gBattleStruct->forcedSwitch & gBitTable[battler]) + && !(gBattleStruct->forcedSwitch & (1u << battler)) && monPartyId == CalculateEnemyPartyCount()-1) return TRUE; return FALSE; @@ -82,7 +82,7 @@ static bool32 HasBadOdds(u32 battler, bool32 emitResult) return FALSE; // Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) return FALSE; opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battler)); @@ -218,9 +218,9 @@ static bool32 HasBadOdds(u32 battler, bool32 emitResult) static bool32 ShouldSwitchIfAllBadMoves(u32 battler, bool32 emitResult) { - if (AI_DATA->shouldSwitchMon & gBitTable[battler]) + if (AI_DATA->shouldSwitchMon & (1u << battler)) { - AI_DATA->shouldSwitchMon &= ~(gBitTable[battler]); + AI_DATA->shouldSwitchMon &= ~(1u << battler); gBattleStruct->AI_monToSwitchIntoId[battler] = AI_DATA->monToSwitchId[battler]; if (emitResult) BtlController_EmitTwoReturnValues(battler, BUFFER_B, B_ACTION_SWITCH, 0); @@ -242,7 +242,7 @@ static bool32 ShouldSwitchIfWonderGuard(u32 battler, bool32 emitResult) struct Pokemon *party = NULL; u16 move; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) return FALSE; opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battler)); @@ -318,10 +318,10 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler, bool32 emitResult) if (IS_MOVE_STATUS(gLastLandedMoves[battler])) return FALSE; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { battlerIn1 = battler; - if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))]) + if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler))))) battlerIn2 = battler; else battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler))); @@ -690,7 +690,7 @@ static bool32 HasSuperEffectiveMoveAgainstOpponents(u32 battler, bool32 noRng) u32 opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battler)); u32 opposingBattler = GetBattlerAtPosition(opposingPosition); - if (!(gAbsentBattlerFlags & gBitTable[opposingBattler])) + if (!(gAbsentBattlerFlags & (1u << opposingBattler))) { for (i = 0; i < MAX_MON_MOVES; i++) { @@ -707,12 +707,12 @@ static bool32 HasSuperEffectiveMoveAgainstOpponents(u32 battler, bool32 noRng) } } } - if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + if (!IsDoubleBattle()) return FALSE; opposingBattler = GetBattlerAtPosition(BATTLE_PARTNER(opposingPosition)); - if (!(gAbsentBattlerFlags & gBitTable[opposingBattler])) + if (!(gAbsentBattlerFlags & (1u << opposingBattler))) { for (i = 0; i < MAX_MON_MOVES; i++) { @@ -765,10 +765,10 @@ static bool32 FindMonWithFlagsAndSuperEffective(u32 battler, u16 flags, u32 modu if (IS_MOVE_STATUS(gLastLandedMoves[battler])) return FALSE; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { battlerIn1 = battler; - if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))]) + if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler))))) battlerIn2 = battler; else battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler))); @@ -846,10 +846,10 @@ static bool32 CanMonSurviveHazardSwitchin(u32 battler) // Battler will faint to hazards, check to see if another mon can clear them if (hazardDamage > battlerHp) { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { battlerIn1 = battler; - if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))]) + if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler))))) battlerIn2 = battler; else battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler))); @@ -881,7 +881,9 @@ static bool32 CanMonSurviveHazardSwitchin(u32 battler) for (j = 0; j < MAX_MON_MOVES; j++) { aiMove = GetMonData(&party[i], MON_DATA_MOVE1 + j, NULL); - if (aiMove == MOVE_RAPID_SPIN || aiMove == MOVE_DEFOG || aiMove == MOVE_MORTAL_SPIN || aiMove == MOVE_TIDY_UP) + if (MoveHasAdditionalEffectSelf(aiMove, MOVE_EFFECT_RAPID_SPIN) + || (B_DEFOG_EFFECT_CLEARING >= GEN_6 && gMovesInfo[aiMove].effect == EFFECT_DEFOG) + || gMovesInfo[aiMove].effect == EFFECT_TIDY_UP) { // Have a mon that can clear the hazards, so switching out is okay return TRUE; @@ -1023,10 +1025,10 @@ bool32 ShouldSwitch(u32 battler, bool32 emitResult) availableToSwitch = 0; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { battlerIn1 = battler; - if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))]) + if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler))))) battlerIn2 = battler; else battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler))); @@ -1140,7 +1142,7 @@ void AI_TrySwitchOrUseItem(u32 battler) s32 monToSwitchId = AI_DATA->mostSuitableMonId[battler]; if (monToSwitchId == PARTY_SIZE) { - if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + if (!IsDoubleBattle()) { battlerIn1 = GetBattlerAtPosition(battlerPosition); battlerIn2 = battlerIn1; @@ -1195,14 +1197,14 @@ static u32 GetBestMonBatonPass(struct Pokemon *party, int firstId, int lastId, u for (i = firstId; i < lastId; i++) { - if (invalidMons & gBitTable[i]) + if (invalidMons & (1u << i)) continue; for (j = 0; j < MAX_MON_MOVES; j++) { if (GetMonData(&party[i], MON_DATA_MOVE1 + j, NULL) == MOVE_BATON_PASS) { - bits |= gBitTable[i]; + bits |= 1u << i; break; } } @@ -1213,7 +1215,7 @@ static u32 GetBestMonBatonPass(struct Pokemon *party, int firstId, int lastId, u do { i = (Random() % (lastId - firstId)) + firstId; - } while (!(bits & gBitTable[i])); + } while (!(bits & (1 << i))); return i; } @@ -1231,7 +1233,7 @@ static u32 GetBestMonTypeMatchup(struct Pokemon *party, int firstId, int lastId, // Find the mon whose type is the most suitable defensively. for (i = firstId; i < lastId; i++) { - if (!(gBitTable[i] & invalidMons) && !(gBitTable[i] & bits)) + if (!((1u << i) & invalidMons) && !((1u << i) & bits)) { u16 species = GetMonData(&party[i], MON_DATA_SPECIES); uq4_12_t typeEffectiveness = UQ_4_12(1.0); @@ -1271,7 +1273,7 @@ static u32 GetBestMonTypeMatchup(struct Pokemon *party, int firstId, int lastId, if (i != MAX_MON_MOVES) return bestMonId; // Has both the typing and at least one super effective move. - bits |= gBitTable[bestMonId]; // Sorry buddy, we want something better. + bits |= (1u << bestMonId); // Sorry buddy, we want something better. } else { @@ -1293,7 +1295,7 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva // If we couldn't find the best mon in terms of typing, find the one that deals most damage. for (i = firstId; i < lastId; i++) { - if (gBitTable[i] & invalidMons) + if ((1 << (i)) & invalidMons) continue; InitializeSwitchinCandidate(&party[i]); for (j = 0; j < MAX_MON_MOVES; j++) @@ -1564,9 +1566,9 @@ static u32 GetSwitchinStatusDamage(u32 battler) if ((status & STATUS1_TOXIC_COUNTER) != STATUS1_TOXIC_TURN(15)) // not 16 turns AI_DATA->switchinCandidate.battleMon.status1 += STATUS1_TOXIC_TURN(1); statusDamage = maxHP / 16; - statusDamage *= AI_DATA->switchinCandidate.battleMon.status1 & STATUS1_TOXIC_COUNTER >> 8; if (statusDamage == 0) statusDamage = 1; + statusDamage *= AI_DATA->switchinCandidate.battleMon.status1 & STATUS1_TOXIC_COUNTER >> 8; } } @@ -1733,7 +1735,7 @@ static int GetRandomSwitchinWithBatonPass(int aliveCount, int bits, int firstId, do { return (Random() % (lastId - firstId)) + firstId; - } while (!(bits & gBitTable[currentMonId])); + } while (!(bits & (1 << (currentMonId)))); } // Catch any other cases (such as only one mon alive and it has Baton Pass) @@ -1873,7 +1875,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, // Check for Baton Pass; hitsToKO requirements mean mon can boost and BP without dying whether it's slower or not if (aiMove == MOVE_BATON_PASS && ((hitsToKOAI > hitsToKOAIThreshold + 1 && AI_DATA->switchinCandidate.battleMon.speed < playerMonSpeed) || (hitsToKOAI > hitsToKOAIThreshold && AI_DATA->switchinCandidate.battleMon.speed > playerMonSpeed))) - bits |= gBitTable[i]; + bits |= 1u << i; // Check for mon with resistance and super effective move for GetBestMonTypeMatchup if (aiMove != MOVE_NONE && gMovesInfo[aiMove].power != 0) @@ -2000,7 +2002,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, } // If ace mon is the last available Pokemon and U-Turn/Volt Switch was used - switch to the mon. if (aceMonId != PARTY_SIZE - && (gMovesInfo[gLastUsedMove].effect == EFFECT_HIT_ESCAPE || gMovesInfo[gLastUsedMove].effect == EFFECT_PARTING_SHOT || gMovesInfo[gLastUsedMove].effect == EFFECT_BATON_PASS)) + && (gMovesInfo[gLastUsedMove].effect == EFFECT_HIT_ESCAPE || gMovesInfo[gLastUsedMove].effect == EFFECT_PARTING_SHOT || gMovesInfo[gLastUsedMove].effect == EFFECT_BATON_PASS || gMovesInfo[gLastUsedMove].effect == EFFECT_CHILLY_RECEPTION)) return aceMonId; return PARTY_SIZE; @@ -2040,16 +2042,16 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd) if (gBattleTypeFlags & BATTLE_TYPE_ARENA) return gBattlerPartyIndexes[battler] + 1; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { battlerIn1 = battler; - if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))]) + if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler))))) battlerIn2 = battler; else battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler))); opposingBattler = BATTLE_OPPOSITE(battlerIn1); - if (gAbsentBattlerFlags & gBitTable[opposingBattler]) + if (gAbsentBattlerFlags & (1u << opposingBattler)) opposingBattler ^= BIT_FLANK; } else @@ -2074,7 +2076,7 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd) // Split ideal mon decision between after previous mon KO'd (prioritize offensive options) and after switching active mon out (prioritize defensive options), and expand the scope of both. // Only use better mon selection if AI_FLAG_SMART_MON_CHOICES is set for the trainer. - if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_MON_CHOICES && !(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) // Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic + if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_MON_CHOICES && !IsDoubleBattle()) // Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic { bestMonId = GetBestMonIntegrated(party, firstId, lastId, battler, opposingBattler, battlerIn1, battlerIn2, switchAfterMonKOd); return bestMonId; @@ -2095,12 +2097,12 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd) || i == gBattleStruct->monToSwitchIntoId[battlerIn2] || (GetMonAbility(&party[i]) == ABILITY_TRUANT && IsTruantMonVulnerable(battler, opposingBattler))) // While not really invalid per se, not really wise to switch into this mon.) { - invalidMons |= gBitTable[i]; + invalidMons |= 1u << i; } else if (IsAceMon(battler, i))// Save Ace Pokemon for last. { aceMonId = i; - invalidMons |= gBitTable[i]; + invalidMons |= 1u << i; } else { diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 2af88bea8c..8c1cb578ed 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -351,12 +351,12 @@ bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, u32 category) if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && GetBattleMoveCategory(moves[i]) == category - && !(unusable & gBitTable[i])) + && !(unusable & (1u << i))) { SetTypeBeforeUsingMove(moves[i], attacker); moveType = GetMoveType(moves[i]); if (CalcTypeEffectivenessMultiplier(moves[i], moveType, attacker, target, AI_DATA->abilities[target], FALSE) != 0) - usable |= gBitTable[i]; + usable |= 1u << i; } } @@ -482,7 +482,7 @@ bool32 IsDamageMoveUnusable(u32 move, u32 battlerAtk, u32 battlerDef) return TRUE; break; case EFFECT_POLTERGEIST: - if (AI_DATA->items[battlerDef] == ITEM_NONE) + if (AI_DATA->items[battlerDef] == ITEM_NONE || gFieldStatuses & STATUS_FIELD_MAGIC_ROOM || battlerDefAbility == ABILITY_KLUTZ) return TRUE; break; case EFFECT_FIRST_TURN_ONLY: @@ -576,13 +576,13 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u if (critChanceIndex > 1) // Consider crit damage only if a move has at least +2 crit chance { s32 nonCritDmg = CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower, - effectivenessMultiplier, weather, FALSE, - aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef], - aiData->abilities[battlerAtk], aiData->abilities[battlerDef]); + effectivenessMultiplier, weather, FALSE, + aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef], + aiData->abilities[battlerAtk], aiData->abilities[battlerDef]); s32 critDmg = CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower, - effectivenessMultiplier, weather, TRUE, - aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef], - aiData->abilities[battlerAtk], aiData->abilities[battlerDef]); + effectivenessMultiplier, weather, TRUE, + aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef], + aiData->abilities[battlerAtk], aiData->abilities[battlerDef]); u32 critOdds = GetCritHitOdds(critChanceIndex); // With critOdds getting closer to 1, dmg gets closer to critDmg. @@ -595,20 +595,33 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u else if (critChanceIndex == -2) // Guaranteed critical { s32 critDmg = CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower, - effectivenessMultiplier, weather, TRUE, - aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef], - aiData->abilities[battlerAtk], aiData->abilities[battlerDef]); + effectivenessMultiplier, weather, TRUE, + aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef], + aiData->abilities[battlerAtk], aiData->abilities[battlerDef]); simDamage.expected = GetDamageByRollType(critDmg, rollType); simDamage.minimum = LowestRollDmg(critDmg); } else { - s32 nonCritDmg = CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower, - effectivenessMultiplier, weather, FALSE, - aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef], - aiData->abilities[battlerAtk], aiData->abilities[battlerDef]); - + s32 nonCritDmg = 0; + if (gMovesInfo[move].effect == EFFECT_TRIPLE_KICK) + { + for (gMultiHitCounter = gMovesInfo[move].strikeCount; gMultiHitCounter > 0; gMultiHitCounter--) // The global is used to simulate actual damage done + { + nonCritDmg += CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower, + effectivenessMultiplier, weather, FALSE, + aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef], + aiData->abilities[battlerAtk], aiData->abilities[battlerDef]); + } + } + else + { + nonCritDmg = CalculateMoveDamageVars(move, battlerAtk, battlerDef, moveType, fixedBasePower, + effectivenessMultiplier, weather, FALSE, + aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef], + aiData->abilities[battlerAtk], aiData->abilities[battlerDef]); + } simDamage.expected = GetDamageByRollType(nonCritDmg, rollType); simDamage.minimum = LowestRollDmg(nonCritDmg); } @@ -1092,7 +1105,7 @@ bool32 CanTargetFaintAi(u32 battlerDef, u32 battlerAtk) for (i = 0; i < MAX_MON_MOVES; i++) { - if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(unusable & gBitTable[i]) + if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(unusable & (1u << i)) && AI_DATA->simulatedDmg[battlerDef][battlerAtk][i].expected >= gBattleMons[battlerAtk].hp) { return TRUE; @@ -1130,7 +1143,7 @@ u32 GetBestDmgMoveFromBattler(u32 battlerAtk, u32 battlerDef) for (i = 0; i < MAX_MON_MOVES; i++) { - if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(unusable & gBitTable[i]) + if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(unusable & (1u << i)) && bestDmg < AI_DATA->simulatedDmg[battlerAtk][battlerDef][i].expected) { bestDmg = AI_DATA->simulatedDmg[battlerAtk][battlerDef][i].expected; @@ -1151,7 +1164,7 @@ u32 GetBestDmgFromBattler(u32 battler, u32 battlerTarget) { if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE - && !(unusable & gBitTable[i]) + && !(unusable & (1u << i)) && bestDmg < AI_DATA->simulatedDmg[battler][battlerTarget][i].expected) { bestDmg = AI_DATA->simulatedDmg[battler][battlerTarget][i].expected; @@ -1171,7 +1184,7 @@ bool32 CanAIFaintTarget(u32 battlerAtk, u32 battlerDef, u32 numHits) for (i = 0; i < MAX_MON_MOVES; i++) { - if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(moveLimitations & gBitTable[i])) + if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(moveLimitations & (1u << i))) { // Use the pre-calculated value in simulatedDmg instead of re-calculating it dmg = AI_DATA->simulatedDmg[battlerAtk][battlerDef][i].expected; @@ -1216,7 +1229,7 @@ bool32 CanTargetFaintAiWithMod(u32 battlerDef, u32 battlerAtk, s32 hpMod, s32 dm if (dmgMod) dmg *= dmgMod; - if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(unusable & gBitTable[i]) && dmg >= hpCheck) + if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(unusable & (1u << i)) && dmg >= hpCheck) { return TRUE; } @@ -2078,7 +2091,7 @@ bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool if (moves[i] == MOVE_NONE || moves[i] == MOVE_UNAVAILABLE) continue; - if (!(gBitTable[i] & moveLimitations)) + if (!((1u << i) & moveLimitations)) { if (ignoreStatus && IS_MOVE_STATUS(moves[i])) continue; @@ -2104,7 +2117,7 @@ bool32 HasSleepMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef) { if (moves[i] == MOVE_NONE) break; - if (!(gBitTable[i] & moveLimitations)) + if (!((1u << i) & moveLimitations)) { if (gMovesInfo[moves[i]].effect == EFFECT_SLEEP && AI_DATA->moveAccuracy[battlerAtk][battlerDef][i] < 85) @@ -2500,7 +2513,7 @@ u32 GetBattlerSecondaryDamage(u32 battlerId) bool32 BattlerWillFaintFromWeather(u32 battler, u32 ability) { if ((BattlerAffectedBySandstorm(battler, ability) || BattlerAffectedByHail(battler, ability)) - && gBattleMons[battler].hp <= gBattleMons[battler].maxHP / 16) + && gBattleMons[battler].hp <= max(1, gBattleMons[battler].maxHP / 16)) return TRUE; return FALSE; @@ -2509,7 +2522,7 @@ bool32 BattlerWillFaintFromWeather(u32 battler, u32 ability) bool32 BattlerWillFaintFromSecondaryDamage(u32 battler, u32 ability) { if (GetBattlerSecondaryDamage(battler) != 0 - && gBattleMons[battler].hp <= gBattleMons[battler].maxHP / 16) + && gBattleMons[battler].hp <= max(1, gBattleMons[battler].maxHP / 16)) return TRUE; return FALSE; } @@ -3026,7 +3039,7 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof) else party = gEnemyParty; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { battlerOnField1 = gBattlerPartyIndexes[battlerId]; battlerOnField2 = gBattlerPartyIndexes[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battlerId)))]; @@ -3249,7 +3262,8 @@ bool32 IsMoveEffectWeather(u32 move) || gMovesInfo[move].effect == EFFECT_RAIN_DANCE || gMovesInfo[move].effect == EFFECT_SANDSTORM || gMovesInfo[move].effect == EFFECT_HAIL - || gMovesInfo[move].effect == EFFECT_SNOWSCAPE)) + || gMovesInfo[move].effect == EFFECT_SNOWSCAPE + || gMovesInfo[move].effect == EFFECT_CHILLY_RECEPTION)) return TRUE; return FALSE; } @@ -3417,7 +3431,7 @@ s32 CountUsablePartyMons(u32 battlerId) else party = gEnemyParty; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { battlerOnField1 = gBattlerPartyIndexes[battlerId]; battlerOnField2 = gBattlerPartyIndexes[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battlerId)))]; @@ -3828,7 +3842,7 @@ bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u32 move) bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove) { // simple logic. just upgrades chosen move to z move if possible, unless regular move would kill opponent - if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && battlerDef == BATTLE_PARTNER(battlerAtk)) + if ((IsDoubleBattle()) && battlerDef == BATTLE_PARTNER(battlerAtk)) return FALSE; // don't use z move on partner if (HasTrainerUsedGimmick(battlerAtk, GIMMICK_Z_MOVE)) return FALSE; // can't use z move twice diff --git a/src/battle_anim_dragon.c b/src/battle_anim_dragon.c index 4191c42585..862c0ad069 100644 --- a/src/battle_anim_dragon.c +++ b/src/battle_anim_dragon.c @@ -42,35 +42,35 @@ const struct SpriteTemplate gOutrageFlameSpriteTemplate = .callback = AnimOutrageFlame, }; -static const union AnimCmd sAnim_DreepyMissileOpponent_0[] = +static const union AnimCmd sAnim_DreepyMissileOpponent_0[] = { ANIMCMD_FRAME(0, 0, .hFlip = TRUE), ANIMCMD_END, }; -const union AnimCmd *const gAnims_DreepyMissileOpponent[] = +const union AnimCmd *const gAnims_DreepyMissileOpponent[] = { sAnim_DreepyMissileOpponent_0, }; -static const union AnimCmd sAnim_DreepyMissilePlayer_0[] = +static const union AnimCmd sAnim_DreepyMissilePlayer_0[] = { ANIMCMD_FRAME(0, 0), ANIMCMD_END, }; -const union AnimCmd *const gAnims_DreepyMissilePlayer[] = +const union AnimCmd *const gAnims_DreepyMissilePlayer[] = { sAnim_DreepyMissilePlayer_0, }; -static const union AnimCmd sAnim_DreepyMissileNotDrag_0[] = +static const union AnimCmd sAnim_DreepyMissileNotDrag_0[] = { ANIMCMD_FRAME(0, 0, .hFlip = TRUE, .vFlip = TRUE), ANIMCMD_END, }; -const union AnimCmd *const gAnims_DreepyMissileOpponentNotDrag[] = +const union AnimCmd *const gAnims_DreepyMissileOpponentNotDrag[] = { sAnim_DreepyMissileNotDrag_0, }; diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index b917cdc9a5..e333d2db40 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -3101,6 +3101,17 @@ const struct SpriteTemplate gPsyshockSmokeSpriteTemplate = .callback = AnimSpriteOnMonPos, }; +const struct SpriteTemplate gChainBindingSpriteTemplate = +{ + .tileTag = ANIM_TAG_PURPLE_CHAIN, + .paletteTag = ANIM_TAG_PURPLE_CHAIN, + .oam = &gOamData_AffineNormal_ObjNormal_64x32, + .anims = sAnims_ConstrictBinding, + .images = NULL, + .affineAnims = sAffineAnims_ConstrictBinding, + .callback = AnimConstrictBinding, +}; + // functions static void AnimGrassKnot(struct Sprite *sprite) { @@ -3317,7 +3328,7 @@ static void AnimSolarBeamSmallOrb(struct Sprite *sprite) { InitSpritePosToAnimAttacker(sprite, TRUE); - if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gAnimMoveIndex == MOVE_CORE_ENFORCER) + if (IsDoubleBattle() && gAnimMoveIndex == MOVE_CORE_ENFORCER) { CoreEnforcerLoadBeamTarget(sprite); } @@ -6567,11 +6578,11 @@ void PrepareDoubleTeamAnim(u32 taskId, u32 animBattler, bool32 forAllySwitch) gSprites[spriteId].sBattlerFlank = (animBattler != ANIM_ATTACKER); else gSprites[spriteId].sBattlerFlank = (animBattler == ANIM_ATTACKER); - + // correct direction on opponent side if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) gSprites[spriteId].sBattlerFlank ^= 1; - + gSprites[spriteId].callback = AnimDoubleTeam; task->tBlendSpritesCount++; } @@ -6603,7 +6614,7 @@ static void ReloadBattlerSprites(u32 battler, struct Pokemon *party) UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], mon, HEALTHBOX_ALL); // If battler has an indicator for a gimmick, hide the sprite until the move animation finishes. UpdateIndicatorVisibilityAndType(gHealthboxSpriteIds[battler], TRUE); - + // Try to recreate shadow sprite if (gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteId < MAX_SPRITES) { @@ -7229,6 +7240,14 @@ static const union AffineAnimCmd sCompressTargetHorizontallyAffineAnimCmds[] = AFFINEANIMCMD_END, }; +static const union AffineAnimCmd sCompressTargetHorizontallyAffineAnimCmdsFast[] = +{ + AFFINEANIMCMD_FRAME(32, 0, 0, 16), //Compress + AFFINEANIMCMD_FRAME(0, 0, 0, 32), + AFFINEANIMCMD_FRAME(-32, 0, 0, 16), + AFFINEANIMCMD_END, +}; + static void AnimTask_CompressTargetStep(u8 taskId) { struct Task* task = &gTasks[taskId]; @@ -7245,6 +7264,14 @@ void AnimTask_CompressTargetHorizontally(u8 taskId) task->func = AnimTask_CompressTargetStep; } +void AnimTask_CompressTargetHorizontallyFast(u8 taskId) +{ + struct Task* task = &gTasks[taskId]; + u8 spriteId = GetAnimBattlerSpriteId(ANIM_TARGET); + PrepareAffineAnimInTaskData(task, spriteId, sCompressTargetHorizontallyAffineAnimCmdsFast); + task->func = AnimTask_CompressTargetStep; +} + void AnimTask_CreateSmallSteelBeamOrbs(u8 taskId) { if (--gTasks[taskId].data[0] == -1) diff --git a/src/battle_anim_effects_2.c b/src/battle_anim_effects_2.c index 3324d276fd..b33c0a8bb6 100755 --- a/src/battle_anim_effects_2.c +++ b/src/battle_anim_effects_2.c @@ -1726,7 +1726,7 @@ void AnimTask_AirCutterProjectile(u8 taskId) attackerX = gTasks[taskId].data[9] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X); attackerY = gTasks[taskId].data[10] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y); - if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle() && IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimTarget))) { SetAverageBattlerPositions(gBattleAnimTarget, FALSE, &targetX, &targetY); @@ -3854,7 +3854,7 @@ static void AnimPerishSongMusicNote_Step2(struct Sprite *sprite) static void AnimGuardRing(struct Sprite *sprite) { - if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) + if (IsDoubleBattle() && IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) { SetAverageBattlerPositions(gBattleAnimAttacker, FALSE, &sprite->x, &sprite->y); sprite->y += 40; diff --git a/src/battle_anim_flying.c b/src/battle_anim_flying.c index f58aa97ee2..6afe1e9f36 100644 --- a/src/battle_anim_flying.c +++ b/src/battle_anim_flying.c @@ -33,7 +33,7 @@ static void AnimSkyAttackBird_Step(struct Sprite *); static void AnimTask_AnimateGustTornadoPalette_Step(u8); static void AnimTask_LoadWindstormBackground_Step(u8 taskId); -const struct SpriteTemplate gEllipticalGustCenteredSpriteTemplate = +const struct SpriteTemplate gEllipticalGustCenteredSpriteTemplate = { .tileTag = ANIM_TAG_GUST, .paletteTag = ANIM_TAG_GUST, diff --git a/src/battle_anim_mons.c b/src/battle_anim_mons.c index 73c1e99448..e0b4820409 100644 --- a/src/battle_anim_mons.c +++ b/src/battle_anim_mons.c @@ -17,8 +17,6 @@ #include "util.h" #include "constants/battle_anim.h" -#define IS_DOUBLE_BATTLE() ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) - extern const struct OamData gOamData_AffineNormal_ObjNormal_64x64; static void AnimTranslateLinear_WithFollowup_SetCornerVecX(struct Sprite *sprite); @@ -868,11 +866,6 @@ bool8 IsBattlerSpritePresent(u8 battlerId) } } -bool8 IsDoubleBattle(void) -{ - return IS_DOUBLE_BATTLE(); -} - #define BG_ANIM_PAL_1 8 #define BG_ANIM_PAL_2 9 #define BG_ANIM_PAL_CONTEST 14 diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index f023859b59..fd821250fc 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -99,6 +99,7 @@ static void SpriteCB_GlacialLance_Step1(struct Sprite* sprite); static void SpriteCB_GlacialLance_Step2(struct Sprite* sprite); static void SpriteCB_GlacialLance(struct Sprite* sprite); static void SpriteCB_TripleArrowKick(struct Sprite* sprite); +static void AnimMakingItRain(struct Sprite *sprite); // const data // general @@ -7234,6 +7235,51 @@ const struct SpriteTemplate gBitterBladeImpactTemplate = .callback = AnimClawSlash }; +// Make It Rain +const struct SpriteTemplate gMakingItRainTemplate = +{ + .tileTag = ANIM_TAG_COIN, + .paletteTag = ANIM_TAG_COIN, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gCoinAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimMakingItRain, +}; + +const struct SpriteTemplate gRedExplosionSpriteTemplate = +{ + .tileTag = ANIM_TAG_RED_EXPLOSION, + .paletteTag = ANIM_TAG_RED_EXPLOSION, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gExplosionAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimSpriteOnMonPos, +}; + +const struct SpriteTemplate gBloodMoonOnslaughtSpriteTemplate = +{ + .tileTag = ANIM_TAG_BEAM, + .paletteTag = ANIM_TAG_BEAM, + .oam = &gOamData_AffineNormal_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sArrowRaidOnslaughtAffineAnimTable, + .callback = AnimAssistPawprint +}; + +const struct SpriteTemplate gMoonUpSpriteTemplate = +{ + .tileTag = ANIM_TAG_BLOOD_MOON, + .paletteTag = ANIM_TAG_BLOOD_MOON, + .oam = &gOamData_AffineOff_ObjNormal_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimWeatherBallUp, +}; + // functions //general void AnimTask_IsTargetPartner(u8 taskId) @@ -7250,7 +7296,7 @@ static u8 LoadBattleAnimTarget(u8 arg) { u8 battler; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { switch (gBattleAnimArgs[arg]) { @@ -7281,7 +7327,7 @@ static u8 LoadBattleAnimTarget(u8 arg) static u8 GetProperCentredCoord(u8 battler, u8 coordType) { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) return (GetBattlerSpriteCoord2(battler, coordType) + GetBattlerSpriteCoord2(BATTLE_PARTNER(battler), coordType)) / 2; return GetBattlerSpriteCoord(battler, coordType); @@ -7471,14 +7517,14 @@ static void SpriteCB_SpriteToCentreOfSide(struct Sprite *sprite) if (gBattleAnimArgs[2] == 0) //Attacker { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) InitSpritePosToAnimAttackersCentre(sprite, var); else InitSpritePosToAnimAttacker(sprite, var); } else { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) InitSpritePosToAnimTargetsCentre(sprite, var); else InitSpritePosToAnimTarget(sprite, var); @@ -7562,7 +7608,7 @@ static void SpriteCB_GrowingSuperpower(struct Sprite *sprite) static void SpriteCB_CentredSpiderWeb(struct Sprite *sprite) { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) InitSpritePosToAnimTargetsCentre(sprite, FALSE); else InitSpritePosToAnimTarget(sprite, FALSE); @@ -7576,14 +7622,14 @@ static void SpriteCB_CoreEnforcerHits(struct Sprite *sprite) if (gBattleAnimArgs[2] == 0) { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) InitSpritePosToAnimAttackersCentre(sprite, FALSE); else InitSpritePosToAnimAttacker(sprite, FALSE); } else { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) InitSpritePosToAnimTargetsCentre(sprite, FALSE); else InitSpritePosToAnimTarget(sprite, FALSE); @@ -7595,7 +7641,7 @@ static void SpriteCB_CoreEnforcerHits(struct Sprite *sprite) static void SpriteCB_CoreEnforcerBeam(struct Sprite *sprite) { - if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + if (!IsDoubleBattle()) { AnimSolarBeamBigOrb(sprite); } @@ -7867,14 +7913,14 @@ void SpriteCB_RandomCentredHits(struct Sprite *sprite) if (gBattleAnimArgs[0] == 0) { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) InitSpritePosToAnimAttackersCentre(sprite, FALSE); else InitSpritePosToAnimAttacker(sprite, FALSE); } else { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) InitSpritePosToAnimTargetsCentre(sprite, FALSE); else InitSpritePosToAnimTarget(sprite, FALSE); @@ -8179,7 +8225,7 @@ static void SpriteCB_BeamUpStep(struct Sprite *sprite) static void SpriteCB_CentredElectricity(struct Sprite *sprite) { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) InitSpritePosToAnimTargetsCentre(sprite, FALSE); else InitSpritePosToAnimTarget(sprite, FALSE); @@ -9219,3 +9265,33 @@ void AnimTask_StickySyrup(u8 taskId) gBattleAnimArgs[0] = gAnimDisableStructPtr->syrupBombIsShiny; DestroyAnimVisualTask(taskId); } + +static void AnimMakingItRain(struct Sprite *sprite) +{ + if (gBattleAnimArgs[3] != 0) + SetAverageBattlerPositions(gBattleAnimTarget, FALSE, &sprite->x, &sprite->y); //coin shower on target + + sprite->x += gBattleAnimArgs[0]; + sprite->y += 14; + StartSpriteAnim(sprite, gBattleAnimArgs[1]); + AnimateSprite(sprite); + sprite->data[0] = 0; + sprite->data[1] = 0; + sprite->data[2] = 4; + sprite->data[3] = 16; + sprite->data[4] = -70; + sprite->data[5] = gBattleAnimArgs[2]; + StoreSpriteCallbackInData6(sprite, AnimFallingRock_Step); + sprite->callback = TranslateSpriteInEllipse; + sprite->callback(sprite); +} + +void AnimTask_RandomBool(u8 taskId) +{ + if (RandomPercentage(RNG_NONE, 50)) + gBattleAnimArgs[ARG_RET_ID] = TRUE; + else + gBattleAnimArgs[ARG_RET_ID] = FALSE; + + DestroyAnimVisualTask(taskId); +} diff --git a/src/battle_anim_normal.c b/src/battle_anim_normal.c index 6333cc8183..759c410946 100644 --- a/src/battle_anim_normal.c +++ b/src/battle_anim_normal.c @@ -414,7 +414,7 @@ u32 UnpackSelectedBattlePalettes(s16 selector) bool8 anim1 = (selector >> 5) & 1; bool8 anim2 = (selector >> 6) & 1; u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gAnimMoveIndex); - + switch (moveTarget) { case MOVE_TARGET_BOTH: @@ -431,7 +431,7 @@ u32 UnpackSelectedBattlePalettes(s16 selector) } break; } - + return GetBattlePalettesMask(battleBackground, attacker, target, attackerPartner, targetPartner, anim1, anim2); } diff --git a/src/battle_arena.c b/src/battle_arena.c index 26df519be0..f9a51ac652 100644 --- a/src/battle_arena.c +++ b/src/battle_arena.c @@ -386,9 +386,9 @@ void BattleArena_AddSkillPoints(u8 battler) if (gHitMarker & HITMARKER_OBEYS) { u8 *failedMoveBits = &gBattleStruct->alreadyStatusedMoveAttempt; - if (*failedMoveBits & gBitTable[battler]) + if (*failedMoveBits & (1u << battler)) { - *failedMoveBits &= ~(gBitTable[battler]); + *failedMoveBits &= ~((1u << battler)); skillPoints[battler] -= 2; } else if (gMoveResultFlags & MOVE_RESULT_NO_EFFECT) diff --git a/src/battle_controller_link_opponent.c b/src/battle_controller_link_opponent.c index 0c71d0a1da..7aeefa54b6 100644 --- a/src/battle_controller_link_opponent.c +++ b/src/battle_controller_link_opponent.c @@ -118,7 +118,7 @@ void SetControllerToLinkOpponent(u32 battler) static void LinkOpponentBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sLinkOpponentBufferCommands)) sLinkOpponentBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -376,7 +376,7 @@ static void LinkOpponentBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } diff --git a/src/battle_controller_link_partner.c b/src/battle_controller_link_partner.c index e5fb49bebf..283b492a91 100644 --- a/src/battle_controller_link_partner.c +++ b/src/battle_controller_link_partner.c @@ -117,7 +117,7 @@ void SetControllerToLinkPartner(u32 battler) static void LinkPartnerBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sLinkPartnerBufferCommands)) sLinkPartnerBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -202,7 +202,7 @@ static void LinkPartnerBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index a5dc6f3af1..275aa623b6 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -132,7 +132,7 @@ void SetControllerToOpponent(u32 battler) static void OpponentBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sOpponentBufferCommands)) sOpponentBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -390,7 +390,7 @@ static void OpponentBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } @@ -549,7 +549,7 @@ static void OpponentHandleChooseMove(u32 battler) if (GetBattlerMoveTargetType(battler, chosenMove) & MOVE_TARGET_BOTH) { gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); - if (gAbsentBattlerFlags & gBitTable[gBattlerTarget]) + if (gAbsentBattlerFlags & (1u << gBattlerTarget)) gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); } // If opponent can and should use a gimmick (considering trainer data), do it @@ -581,7 +581,7 @@ static void OpponentHandleChooseMove(u32 battler) if (GetBattlerMoveTargetType(battler, move) & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, (chosenMoveId) | (battler << 8)); - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + else if (IsDoubleBattle()) { do { target = GetBattlerAtPosition(Random() & 2); @@ -653,7 +653,7 @@ static void OpponentHandleChoosePokemon(u32 battler) { s32 battler1, battler2, firstId, lastId; - if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + if (!IsDoubleBattle()) { battler2 = battler1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); } diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 5dae29563d..52507157e7 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -44,6 +44,7 @@ #include "level_caps.h" #include "menu.h" #include "pokemon_summary_screen.h" +#include "type_icons.h" static void PlayerBufferExecCompleted(u32 battler); static void PlayerHandleLoadMonSprite(u32 battler); @@ -59,7 +60,6 @@ static void PlayerHandlePrintString(u32 battler); static void PlayerHandlePrintSelectionString(u32 battler); static void PlayerHandleChooseAction(u32 battler); static void PlayerHandleYesNoBox(u32 battler); -static void PlayerHandleChooseMove(u32 battler); static void PlayerHandleChooseItem(u32 battler); static void PlayerHandleChoosePokemon(u32 battler); static void PlayerHandleCmd23(u32 battler); @@ -81,14 +81,11 @@ static void PlayerHandleEndLinkBattle(u32 battler); static void PlayerHandleBattleDebug(u32 battler); static void PlayerBufferRunCommand(u32 battler); -static void HandleInputChooseTarget(u32 battler); -static void HandleInputChooseMove(u32 battler); static void MoveSelectionDisplayPpNumber(u32 battler); static void MoveSelectionDisplayPpString(u32 battler); static void MoveSelectionDisplayMoveType(u32 battler); static void MoveSelectionDisplayMoveNames(u32 battler); static void MoveSelectionDisplayMoveDescription(u32 battler); -static void HandleMoveSwitching(u32 battler); static void SwitchIn_HandleSoundAndEnd(u32 battler); static void WaitForMonSelection(u32 battler); static void CompleteWhenChoseItem(u32 battler); @@ -183,13 +180,13 @@ static void PlayerBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } static void PlayerBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sPlayerBufferCommands)) sPlayerBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -382,9 +379,9 @@ static void HandleInputChooseAction(u32 battler) } else if (JOY_NEW(B_BUTTON) || gPlayerDpadHoldFrames > 59) { - if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle() && GetBattlerPosition(battler) == B_POSITION_PLAYER_RIGHT - && !(gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)]) + && !(gAbsentBattlerFlags & (1u << GetBattlerAtPosition(B_POSITION_PLAYER_LEFT))) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) { // Return item to bag if partner had selected one. @@ -426,7 +423,7 @@ static void HandleInputChooseAction(u32 battler) } } -static void HandleInputChooseTarget(u32 battler) +void HandleInputChooseTarget(u32 battler) { s32 i; static const u8 identities[MAX_BATTLERS_COUNT] = {B_POSITION_PLAYER_LEFT, B_POSITION_PLAYER_RIGHT, B_POSITION_OPPONENT_RIGHT, B_POSITION_OPPONENT_LEFT}; @@ -510,7 +507,7 @@ static void HandleInputChooseTarget(u32 battler) break; } - if (gAbsentBattlerFlags & gBitTable[gMultiUsePlayerCursor] + if (gAbsentBattlerFlags & (1u << gMultiUsePlayerCursor) || !CanTargetBattler(battler, gMultiUsePlayerCursor, move)) i = 0; } while (i == 0); @@ -560,7 +557,7 @@ static void HandleInputChooseTarget(u32 battler) break; } - if (gAbsentBattlerFlags & gBitTable[gMultiUsePlayerCursor] + if (gAbsentBattlerFlags & (1u << gMultiUsePlayerCursor) || !CanTargetBattler(battler, gMultiUsePlayerCursor, move)) i = 0; } while (i == 0); @@ -596,7 +593,7 @@ static void HideShownTargets(u32 battler) } } -static void HandleInputShowEntireFieldTargets(u32 battler) +void HandleInputShowEntireFieldTargets(u32 battler) { if (JOY_HELD(DPAD_ANY) && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_L_EQUALS_A) gPlayerDpadHoldFrames++; @@ -624,7 +621,7 @@ static void HandleInputShowEntireFieldTargets(u32 battler) } } -static void HandleInputShowTargets(u32 battler) +void HandleInputShowTargets(u32 battler) { if (JOY_HELD(DPAD_ANY) && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_L_EQUALS_A) gPlayerDpadHoldFrames++; @@ -662,7 +659,7 @@ static void TryShowAsTarget(u32 battler) } } -static void HandleInputChooseMove(u32 battler) +void HandleInputChooseMove(u32 battler) { u16 moveTarget; u32 canSelectTarget = 0; @@ -756,7 +753,7 @@ static void HandleInputChooseMove(u32 battler) if (moveTarget & (MOVE_TARGET_USER | MOVE_TARGET_USER_OR_SELECTED)) gMultiUsePlayerCursor = battler; - else if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)]) + else if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT))) gMultiUsePlayerCursor = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); else gMultiUsePlayerCursor = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); @@ -968,7 +965,7 @@ static u32 UNUSED HandleMoveInputUnused(u32 battler) return var; } -static void HandleMoveSwitching(u32 battler) +void HandleMoveSwitching(u32 battler) { u8 perMovePPBonuses[MAX_MON_MOVES]; struct ChooseMoveStruct moveStruct; @@ -997,10 +994,10 @@ static void HandleMoveSwitching(u32 battler) moveInfo->maxPp[gMoveSelectionCursor[battler]] = moveInfo->maxPp[gMultiUsePlayerCursor]; moveInfo->maxPp[gMultiUsePlayerCursor] = i; - if (gDisableStructs[battler].mimickedMoves & gBitTable[gMoveSelectionCursor[battler]]) + if (gDisableStructs[battler].mimickedMoves & (1u << gMoveSelectionCursor[battler])) { - gDisableStructs[battler].mimickedMoves &= (~gBitTable[gMoveSelectionCursor[battler]]); - gDisableStructs[battler].mimickedMoves |= gBitTable[gMultiUsePlayerCursor]; + gDisableStructs[battler].mimickedMoves &= ~(1u << gMoveSelectionCursor[battler]); + gDisableStructs[battler].mimickedMoves |= 1u << gMultiUsePlayerCursor; } MoveSelectionDisplayMoveNames(battler); @@ -1757,7 +1754,7 @@ static void MoveSelectionDisplayMoveType(u32 battler) } else { - end = StringCopy(txtPtr, gTypesInfo[type].name); + end = StringCopy(txtPtr, gTypesInfo[type].name); } PrependFontIdToFit(txtPtr, end, FONT_NORMAL, WindowWidthPx(B_WIN_MOVE_TYPE) - 25); @@ -2075,7 +2072,7 @@ static void PlayerHandleYesNoBox(u32 battler) } } -static void HandleChooseMoveAfterDma3(u32 battler) +void HandleChooseMoveAfterDma3(u32 battler) { if (!IsDma3ManagerBusyWithBgCopy()) { @@ -2097,7 +2094,7 @@ static void PlayerChooseMoveInBattlePalace(u32 battler) } } -static void PlayerHandleChooseMove(u32 battler) +void PlayerHandleChooseMove(u32 battler) { if (gBattleTypeFlags & BATTLE_TYPE_PALACE) { @@ -2112,7 +2109,7 @@ static void PlayerHandleChooseMove(u32 battler) gBattleStruct->gimmick.playerSelect = FALSE; AssignUsableZMoves(battler, moveInfo->moves); - gBattleStruct->zmove.viable = (gBattleStruct->zmove.possibleZMoves[battler] & gBitTable[gMoveSelectionCursor[battler]]) != 0; + gBattleStruct->zmove.viable = (gBattleStruct->zmove.possibleZMoves[battler] & (1u << gMoveSelectionCursor[battler])) != 0; if (!IsGimmickTriggerSpriteActive()) gBattleStruct->gimmick.triggerSpriteId = 0xFF; @@ -2125,6 +2122,7 @@ static void PlayerHandleChooseMove(u32 battler) void InitMoveSelectionsVarsAndStrings(u32 battler) { + LoadTypeIcons(battler); MoveSelectionDisplayMoveNames(battler); gMultiUsePlayerCursor = 0xFF; MoveSelectionCreateCursorAt(gMoveSelectionCursor[battler], 0); diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index 2dffd4f702..47d71d87c6 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -121,7 +121,7 @@ void SetControllerToPlayerPartner(u32 battler) static void PlayerPartnerBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sPlayerPartnerBufferCommands)) sPlayerPartnerBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -274,7 +274,7 @@ static void PlayerPartnerBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } @@ -365,7 +365,7 @@ static void PlayerPartnerHandleChooseMove(u32 battler) if (gMovesInfo[moveInfo->moves[chosenMoveId]].target & MOVE_TARGET_BOTH) { gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); - if (gAbsentBattlerFlags & gBitTable[gBattlerTarget]) + if (gAbsentBattlerFlags & (1u << gBattlerTarget)) gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); } // If partner can and should use a gimmick (considering trainer data), do it diff --git a/src/battle_controller_recorded_opponent.c b/src/battle_controller_recorded_opponent.c index abadcc231c..da977fab89 100644 --- a/src/battle_controller_recorded_opponent.c +++ b/src/battle_controller_recorded_opponent.c @@ -124,7 +124,7 @@ void SetControllerToRecordedOpponent(u32 battler) static void RecordedOpponentBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sRecordedOpponentBufferCommands)) sRecordedOpponentBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -145,7 +145,7 @@ static void RecordedOpponentBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } diff --git a/src/battle_controller_recorded_player.c b/src/battle_controller_recorded_player.c index 3a9ca1ec00..2bb64f3066 100644 --- a/src/battle_controller_recorded_player.c +++ b/src/battle_controller_recorded_player.c @@ -121,7 +121,7 @@ void SetControllerToRecordedPlayer(u32 battler) static void RecordedPlayerBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sRecordedPlayerBufferCommands)) sRecordedPlayerBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -351,7 +351,7 @@ static void RecordedPlayerBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } diff --git a/src/battle_controller_safari.c b/src/battle_controller_safari.c index 39fbc63ab6..b85157f246 100644 --- a/src/battle_controller_safari.c +++ b/src/battle_controller_safari.c @@ -112,7 +112,7 @@ void SetControllerToSafari(u32 battler) static void SafariBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sSafariBufferCommands)) sSafariBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -240,7 +240,7 @@ static void SafariBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } diff --git a/src/battle_controller_wally.c b/src/battle_controller_wally.c index 7b0bb6f154..66d3932694 100644 --- a/src/battle_controller_wally.c +++ b/src/battle_controller_wally.c @@ -129,7 +129,7 @@ void SetControllerToWally(u32 battler) static void WallyBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sWallyBufferCommands)) sWallyBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -288,7 +288,7 @@ static void WallyBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~gBitTable[battler]; + gBattleControllerExecFlags &= ~(1u << battler); } } diff --git a/src/battle_controllers.c b/src/battle_controllers.c index fae42939d0..9c9c1b50ba 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -175,7 +175,7 @@ static void InitSinglePlayerBtlControllers(void) gBattlerPartyIndexes[3] = 3; } } - else if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + else if (!IsDoubleBattle()) { gBattleMainFunc = BeginBattleIntro; @@ -417,7 +417,7 @@ static void InitLinkBtlControllers(void) s32 i; u8 multiplayerId; - if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + if (!IsDoubleBattle()) { if (gBattleTypeFlags & BATTLE_TYPE_IS_MASTER) { @@ -442,7 +442,7 @@ static void InitLinkBtlControllers(void) gBattlersCount = 2; } } - else if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) && gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + else if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) && IsDoubleBattle()) { if (gBattleTypeFlags & BATTLE_TYPE_IS_MASTER) { @@ -610,7 +610,7 @@ static void InitLinkBtlControllers(void) bool32 IsValidForBattle(struct Pokemon *mon) { u32 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG); - return (species != SPECIES_NONE + return (species != SPECIES_NONE && species != SPECIES_EGG && GetMonData(mon, MON_DATA_HP) != 0 && GetMonData(mon, MON_DATA_IS_EGG) == FALSE); @@ -851,7 +851,7 @@ void TryReceiveLinkBattleData(void) DestroyTask_RfuIdle(); for (i = 0; i < GetLinkPlayerCount(); i++) { - if (GetBlockReceivedStatus() & gBitTable[i]) + if (GetBlockReceivedStatus() & (1 << (i))) { ResetBlockReceivedFlag(i); recvBuffer = (u8 *)gBlockRecvBuffer[i]; @@ -898,7 +898,7 @@ static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId) switch (gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 0]) { case 0: - if (gBattleControllerExecFlags & gBitTable[battler]) + if (gBattleControllerExecFlags & (1u << battler)) return; memcpy(gBattleResources->bufferA[battler], &gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_DATA], blockSize); @@ -917,7 +917,7 @@ static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId) break; case 2: var = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_DATA]; - gBattleControllerExecFlags &= ~(gBitTable[battler] << (var * 4)); + gBattleControllerExecFlags &= ~(1u << (battler + var * 4)); break; } diff --git a/src/battle_dome.c b/src/battle_dome.c index 67b9a1e293..49a5902787 100644 --- a/src/battle_dome.c +++ b/src/battle_dome.c @@ -2030,8 +2030,8 @@ static void InitDomeTrainers(void) rankingScores[0] += GetMonData(&gPlayerParty[trainerId], MON_DATA_SPDEF, NULL); rankingScores[0] += GetMonData(&gPlayerParty[trainerId], MON_DATA_SPEED, NULL); rankingScores[0] += GetMonData(&gPlayerParty[trainerId], MON_DATA_MAX_HP, NULL); - monTypesBits |= gBitTable[gSpeciesInfo[GetMonData(&gPlayerParty[trainerId], MON_DATA_SPECIES, NULL)].types[0]]; - monTypesBits |= gBitTable[gSpeciesInfo[GetMonData(&gPlayerParty[trainerId], MON_DATA_SPECIES, NULL)].types[1]]; + monTypesBits |= 1u << gSpeciesInfo[GetMonData(&gPlayerParty[trainerId], MON_DATA_SPECIES, NULL)].types[0]; + monTypesBits |= 1u << gSpeciesInfo[GetMonData(&gPlayerParty[trainerId], MON_DATA_SPECIES, NULL)].types[1]; } // Count the number of types in the players party, to factor into the ranking @@ -2062,8 +2062,8 @@ static void InitDomeTrainers(void) rankingScores[i] += statValues[STAT_SPDEF]; rankingScores[i] += statValues[STAT_SPEED]; rankingScores[i] += statValues[STAT_HP]; - monTypesBits |= gBitTable[gSpeciesInfo[gFacilityTrainerMons[DOME_MONS[i][j]].species].types[0]]; - monTypesBits |= gBitTable[gSpeciesInfo[gFacilityTrainerMons[DOME_MONS[i][j]].species].types[1]]; + monTypesBits |= 1u << gSpeciesInfo[gFacilityTrainerMons[DOME_MONS[i][j]].species].types[0]; + monTypesBits |= 1u << gSpeciesInfo[gFacilityTrainerMons[DOME_MONS[i][j]].species].types[1]; } for (monTypesCount = 0, j = 0; j < 32; j++) @@ -2136,7 +2136,7 @@ static void CalcDomeMonStats(const struct TrainerMon *fmon, int level, u8 ivs, i { int evs[NUM_STATS]; int i; - + for (i = 0; i < NUM_STATS; i++) { if (fmon->ev != NULL) @@ -2144,7 +2144,7 @@ static void CalcDomeMonStats(const struct TrainerMon *fmon, int level, u8 ivs, i else evs[i] = 0; } - + if (fmon->species == SPECIES_SHEDINJA) { stats[STAT_HP] = 1; @@ -2199,7 +2199,7 @@ static void CreateDomeOpponentMon(u8 monPartyId, u16 tournamentTrainerId, u8 tou u8 fixedIv = GetDomeTrainerMonIvs(tournamentTrainerId); // BUG: Using the wrong ID. As a result, all Pokémon have ivs of 3. #endif u8 level = SetFacilityPtrsGetLevel(); - + CreateFacilityMon(&gFacilityTrainerMons[DOME_MONS[tournamentTrainerId][tournamentMonId]], level, fixedIv, otId, 0, &gEnemyParty[monPartyId]); } @@ -2344,9 +2344,9 @@ static int SelectOpponentMonsFromParty(int *partyMovePoints, bool8 allowRandom) while (i != DOME_BATTLE_PARTY_SIZE) { u32 rand = Random() & FRONTIER_PARTY_SIZE; - if (rand != FRONTIER_PARTY_SIZE && !(selectedMonBits & gBitTable[rand])) + if (rand != FRONTIER_PARTY_SIZE && !(selectedMonBits & (1u << rand))) { - selectedMonBits |= gBitTable[rand]; + selectedMonBits |= 1u << rand; i++; } } @@ -2376,7 +2376,7 @@ static int SelectOpponentMonsFromParty(int *partyMovePoints, bool8 allowRandom) for (i = 0; i < DOME_BATTLE_PARTY_SIZE; i++) { - selectedMonBits |= gBitTable[partyPositions[i]]; + selectedMonBits |= 1u << partyPositions[i]; } } @@ -4446,7 +4446,7 @@ static void DisplayTrainerInfoOnCard(u8 flags, u8 trainerTourneyId) else allocatedArray[j] = 0; } - + allocatedArray[NUM_STATS] += allocatedArray[STAT_HP]; for (j = 0; j < NUM_NATURE_STATS; j++) { @@ -5802,8 +5802,8 @@ static void InitRandomTourneyTreeResults(void) statSums[i] += statValues[STAT_SPDEF]; statSums[i] += statValues[STAT_SPEED]; statSums[i] += statValues[STAT_HP]; - monTypesBits |= gBitTable[gSpeciesInfo[gFacilityTrainerMons[DOME_MONS[i][j]].species].types[0]]; - monTypesBits |= gBitTable[gSpeciesInfo[gFacilityTrainerMons[DOME_MONS[i][j]].species].types[1]]; + monTypesBits |= 1u << gSpeciesInfo[gFacilityTrainerMons[DOME_MONS[i][j]].species].types[0]; + monTypesBits |= 1u << gSpeciesInfo[gFacilityTrainerMons[DOME_MONS[i][j]].species].types[1]; } // Because GF hates temporary vars, trainerId acts like monTypesCount here. diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c index 06a26718a9..cdcf05f7db 100644 --- a/src/battle_dynamax.c +++ b/src/battle_dynamax.c @@ -76,6 +76,10 @@ bool32 CanDynamax(u32 battler) u16 species = gBattleMons[battler].species; u16 holdEffect = GetBattlerHoldEffect(battler, FALSE); + // Prevents Zigzagoon from dynamaxing in vanilla. + if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE && GetBattlerSide(battler) == B_SIDE_OPPONENT) + return FALSE; + // Check if Player has a Dynamax Band. if (!TESTING && (GetBattlerPosition(battler) == B_POSITION_PLAYER_LEFT || (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) && GetBattlerPosition(battler) == B_POSITION_PLAYER_RIGHT))) diff --git a/src/battle_factory.c b/src/battle_factory.c index 7d7ec7b3af..b5645368c2 100644 --- a/src/battle_factory.c +++ b/src/battle_factory.c @@ -406,7 +406,7 @@ static void SetPlayerAndOpponentParties(void) u8 monLevel; u16 monId; u8 ivs; - + if (gSaveBlock2Ptr->frontier.lvlMode == FRONTIER_LVL_TENT) { gFacilityTrainerMons = gSlateportBattleTentMons; @@ -428,7 +428,7 @@ static void SetPlayerAndOpponentParties(void) { monId = gSaveBlock2Ptr->frontier.rentalMons[i].monId; ivs = gSaveBlock2Ptr->frontier.rentalMons[i].ivs; - + CreateFacilityMon(&gFacilityTrainerMons[monId], monLevel, ivs, OT_ID_PLAYER_ID, FLAG_FRONTIER_MON_FACTORY, &gPlayerParty[i]); SetMonData(&gPlayerParty[i], MON_DATA_PERSONALITY, &gSaveBlock2Ptr->frontier.rentalMons[i].personality); diff --git a/src/battle_factory_screen.c b/src/battle_factory_screen.c index 5aa019c29f..f76c6a2fc8 100644 --- a/src/battle_factory_screen.c +++ b/src/battle_factory_screen.c @@ -1761,7 +1761,7 @@ static void CreateFrontierFactorySelectableMons(u8 firstMonId) ivs = GetFactoryMonFixedIV(challengeNum + 1, FALSE); else ivs = GetFactoryMonFixedIV(challengeNum, FALSE); - + CreateFacilityMon(&gFacilityTrainerMons[monId], level, ivs, otId, FLAG_FRONTIER_MON_FACTORY, &sFactorySelectScreen->mons[i + firstMonId].monData); diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index cb3349ee32..22736b7c2b 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -126,7 +126,7 @@ u16 ChooseMoveAndTargetInBattlePalace(u32 battler) // If battler is < 50% HP and not asleep, use second set of move group likelihoods // otherwise use first set - i = (gBattleStruct->palaceFlags & gBitTable[battler]) ? 2 : 0; + i = (gBattleStruct->palaceFlags & (1u << battler)) ? 2 : 0; minGroupNum = i; maxGroupNum = i + 2; // + 2 because there are two percentages per set of likelihoods @@ -150,7 +150,7 @@ u16 ChooseMoveAndTargetInBattlePalace(u32 battler) if (moveInfo->moves[i] == MOVE_NONE) break; if (selectedGroup == GetBattlePalaceMoveGroup(battler, moveInfo->moves[i]) && moveInfo->currentPp[i] != 0) - selectedMoves |= gBitTable[i]; + selectedMoves |= 1u << i; } // Pass selected moves to AI, pick one @@ -178,11 +178,11 @@ u16 ChooseMoveAndTargetInBattlePalace(u32 battler) { // Count the number of usable moves the battler has in each move group. // The totals will be stored separately in 3 groups of 4 bits each in numMovesPerGroup. - if (GetBattlePalaceMoveGroup(battler, moveInfo->moves[i]) == PALACE_MOVE_GROUP_ATTACK && !(gBitTable[i] & unusableMovesBits)) + if (GetBattlePalaceMoveGroup(battler, moveInfo->moves[i]) == PALACE_MOVE_GROUP_ATTACK && !((1u << i) & unusableMovesBits)) numMovesPerGroup += (1 << 0); - if (GetBattlePalaceMoveGroup(battler, moveInfo->moves[i]) == PALACE_MOVE_GROUP_DEFENSE && !(gBitTable[i] & unusableMovesBits)) + if (GetBattlePalaceMoveGroup(battler, moveInfo->moves[i]) == PALACE_MOVE_GROUP_DEFENSE && !((1u << i) & unusableMovesBits)) numMovesPerGroup += (1 << 4); - if (GetBattlePalaceMoveGroup(battler, moveInfo->moves[i]) == PALACE_MOVE_GROUP_SUPPORT && !(gBitTable[i] & unusableMovesBits)) + if (GetBattlePalaceMoveGroup(battler, moveInfo->moves[i]) == PALACE_MOVE_GROUP_SUPPORT && !((1u << i) & unusableMovesBits)) numMovesPerGroup += (1 << 8); } @@ -215,7 +215,7 @@ u16 ChooseMoveAndTargetInBattlePalace(u32 battler) do { i = Random() % MAX_MON_MOVES; - if (!(gBitTable[i] & unusableMovesBits)) + if (!((1u << i) & unusableMovesBits)) chosenMoveId = i; } while (chosenMoveId == -1); } @@ -241,7 +241,7 @@ u16 ChooseMoveAndTargetInBattlePalace(u32 battler) do { i = Random() % MAX_MON_MOVES; - if (!(gBitTable[i] & unusableMovesBits) && randSelectGroup == GetBattlePalaceMoveGroup(battler, moveInfo->moves[i])) + if (!((1u << i) & unusableMovesBits) && randSelectGroup == GetBattlePalaceMoveGroup(battler, moveInfo->moves[i])) chosenMoveId = i; } while (chosenMoveId == -1); } @@ -309,7 +309,7 @@ static u8 GetBattlePalaceMoveGroup(u8 battler, u16 move) static u16 GetBattlePalaceTarget(u32 battler) { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { u8 opposing1, opposing2; diff --git a/src/battle_gimmick.c b/src/battle_gimmick.c index c8ee932218..815fd5fc3e 100644 --- a/src/battle_gimmick.c +++ b/src/battle_gimmick.c @@ -45,7 +45,7 @@ bool32 IsGimmickSelected(u32 battler, enum Gimmick gimmick) { // There's no player select in tests, but some gimmicks need to test choice before they are fully activated. if (TESTING) - return (gBattleStruct->gimmick.toActivate & gBitTable[battler]) && gBattleStruct->gimmick.usableGimmick[battler] == gimmick; + return (gBattleStruct->gimmick.toActivate & (1u << battler)) && gBattleStruct->gimmick.usableGimmick[battler] == gimmick; else return gBattleStruct->gimmick.usableGimmick[battler] == gimmick && gBattleStruct->gimmick.playerSelect; } @@ -96,10 +96,10 @@ bool32 ShouldTrainerBattlerUseGimmick(u32 battler, enum Gimmick gimmick) bool32 HasTrainerUsedGimmick(u32 battler, enum Gimmick gimmick) { // Check whether partner battler has used gimmick or plans to during turn. - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE + if (IsDoubleBattle() && IsPartnerMonFromSameTrainer(battler) && (gBattleStruct->gimmick.activated[BATTLE_PARTNER(battler)][gimmick] - || ((gBattleStruct->gimmick.toActivate & gBitTable[BATTLE_PARTNER(battler)] + || ((gBattleStruct->gimmick.toActivate & (1u << BATTLE_PARTNER(battler)) && gBattleStruct->gimmick.usableGimmick[BATTLE_PARTNER(battler)] == gimmick)))) { return TRUE; @@ -115,7 +115,7 @@ bool32 HasTrainerUsedGimmick(u32 battler, enum Gimmick gimmick) void SetGimmickAsActivated(u32 battler, enum Gimmick gimmick) { gBattleStruct->gimmick.activated[battler][gimmick] = TRUE; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsPartnerMonFromSameTrainer(battler)) + if (IsDoubleBattle() && IsPartnerMonFromSameTrainer(battler)) gBattleStruct->gimmick.activated[BATTLE_PARTNER(battler)][gimmick] = TRUE; } @@ -155,7 +155,7 @@ void CreateGimmickTriggerSprite(u32 battler) if (gBattleStruct->gimmick.triggerSpriteId == 0xFF) { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) gBattleStruct->gimmick.triggerSpriteId = CreateSprite(gimmick->triggerTemplate, gSprites[gHealthboxSpriteIds[battler]].x - DOUBLES_GIMMICK_TRIGGER_POS_X_SLIDE, gSprites[gHealthboxSpriteIds[battler]].y - DOUBLES_GIMMICK_TRIGGER_POS_Y_DIFF, 0); @@ -204,7 +204,7 @@ static void SpriteCb_GimmickTrigger(struct Sprite *sprite) s32 xSlide, xPriority, xOptimal; s32 yDiff; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { xSlide = DOUBLES_GIMMICK_TRIGGER_POS_X_SLIDE; xPriority = DOUBLES_GIMMICK_TRIGGER_POS_X_PRIORITY; diff --git a/src/battle_interface.c b/src/battle_interface.c index 8d50bf95c3..4c17322b53 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -1377,7 +1377,7 @@ u8 CreatePartyStatusSummarySprites(u8 battlerId, struct HpAndStatus *partyInfo, // fainted mon gSprites[ballIconSpritesIds[i]].oam.tileNum += 3; } - else if (gBattleTypeFlags & BATTLE_TYPE_ARENA && gBattleStruct->arenaLostPlayerMons & gBitTable[j]) + else if (gBattleTypeFlags & BATTLE_TYPE_ARENA && gBattleStruct->arenaLostPlayerMons & (1u << j)) { // fainted arena mon gSprites[ballIconSpritesIds[i]].oam.tileNum += 3; @@ -1433,7 +1433,7 @@ u8 CreatePartyStatusSummarySprites(u8 battlerId, struct HpAndStatus *partyInfo, // fainted mon gSprites[ballIconSpritesIds[PARTY_SIZE - 1 - var]].oam.tileNum += 3; } - else if (gBattleTypeFlags & BATTLE_TYPE_ARENA && gBattleStruct->arenaLostOpponentMons & gBitTable[j]) + else if (gBattleTypeFlags & BATTLE_TYPE_ARENA && gBattleStruct->arenaLostOpponentMons & (1u << j)) { // fainted arena mon gSprites[ballIconSpritesIds[PARTY_SIZE - 1 - var]].oam.tileNum += 3; @@ -2718,7 +2718,7 @@ void CreateAbilityPopUp(u8 battlerId, u32 ability, bool32 isDoubleBattle) LoadSpriteSheet(&sSpriteSheet_AbilityPopUp); LoadSpritePalette(&sSpritePalette_AbilityPopUp); } - gBattleStruct->activeAbilityPopUps |= gBitTable[battlerId]; + gBattleStruct->activeAbilityPopUps |= 1u << battlerId; battlerPosition = GetBattlerPosition(battlerId); if (isDoubleBattle) @@ -2809,7 +2809,7 @@ static void SpriteCb_AbilityPopUp(struct Sprite *sprite) ||(sprite->tRightToLeft && (sprite->x -= 4) <= sprite->tOriginalX - ABILITY_POP_UP_POS_X_SLIDE) ) { - gBattleStruct->activeAbilityPopUps &= ~(gBitTable[sprite->tBattlerId]); + gBattleStruct->activeAbilityPopUps &= ~(1u << sprite->tBattlerId); DestroySprite(sprite); } } @@ -2823,7 +2823,7 @@ static void SpriteCb_AbilityPopUp(struct Sprite *sprite) void DestroyAbilityPopUp(u8 battlerId) { - if (gBattleStruct->activeAbilityPopUps & gBitTable[battlerId]) + if (gBattleStruct->activeAbilityPopUps & (1u << battlerId)) { gSprites[gBattleStruct->abilityPopUpSpriteIds[battlerId][0]].tFrames = 0; gSprites[gBattleStruct->abilityPopUpSpriteIds[battlerId][1]].tFrames = 0; diff --git a/src/battle_main.c b/src/battle_main.c index 23047107b8..d6a8d7ef0e 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -1692,15 +1692,9 @@ static void CB2_HandleStartMultiBattle(void) case 8: if (IsLinkTaskFinished()) { - #if HQ_RANDOM == TRUE struct BattleVideo *ptr = &gBattleStruct->multiBuffer.battleVideo; ptr->battleTypeFlags = gBattleTypeFlags; ptr->rngSeed = gRecordedBattleRngSeed; - #else - u32 *ptr = gBattleStruct->multiBuffer.battleVideo; - ptr[0] = gBattleTypeFlags; - ptr[1] = gRecordedBattleRngSeed; // UB: overwrites berry data - #endif SendBlock(BitmaskAllOtherLinkPlayers(), ptr, sizeof(gBattleStruct->multiBuffer.battleVideo)); gBattleCommunication[MULTIUSE_STATE]++; @@ -3114,8 +3108,6 @@ static void BattleStartClearSetData(void) gBattleStruct->itemLost[B_SIDE_PLAYER][i].originalItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM); gBattleStruct->itemLost[B_SIDE_OPPONENT][i].originalItem = GetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM); gPartyCriticalHits[i] = 0; - gBattleStruct->allowedToChangeFormInWeather[i][B_SIDE_PLAYER] = FALSE; - gBattleStruct->allowedToChangeFormInWeather[i][B_SIDE_OPPONENT] = FALSE; } gBattleStruct->swapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky @@ -3218,9 +3210,10 @@ void SwitchInClearSetData(u32 battler) gBattleStruct->lastTakenMoveFrom[battler][1] = 0; gBattleStruct->lastTakenMoveFrom[battler][2] = 0; gBattleStruct->lastTakenMoveFrom[battler][3] = 0; - gBattleStruct->lastMoveFailed &= ~(gBitTable[battler]); - gBattleStruct->palaceFlags &= ~(gBitTable[battler]); - gBattleStruct->boosterEnergyActivates &= ~(gBitTable[battler]); + gBattleStruct->lastMoveFailed &= ~(1u << battler); + gBattleStruct->palaceFlags &= ~(1u << battler); + gBattleStruct->boosterEnergyActivates &= ~(1u << battler); + gBattleStruct->canPickupItem &= ~(1u << battler); for (i = 0; i < ARRAY_COUNT(gSideTimers); i++) { @@ -3245,7 +3238,7 @@ void SwitchInClearSetData(u32 battler) // Reset damage to prevent things like red card activating if the switched-in mon is holding it gSpecialStatuses[battler].physicalDmg = 0; gSpecialStatuses[battler].specialDmg = 0; - gBattleStruct->enduredDamage &= ~gBitTable[battler]; + gBattleStruct->enduredDamage &= ~(1u << battler); // Reset G-Max Chi Strike boosts. gBattleStruct->bonusCritStages[battler] = 0; @@ -3348,8 +3341,8 @@ const u8* FaintClearSetData(u32 battler) gBattleStruct->lastTakenMoveFrom[battler][2] = 0; gBattleStruct->lastTakenMoveFrom[battler][3] = 0; - gBattleStruct->palaceFlags &= ~(gBitTable[battler]); - gBattleStruct->boosterEnergyActivates &= ~(gBitTable[battler]); + gBattleStruct->palaceFlags &= ~(1u << battler); + gBattleStruct->boosterEnergyActivates &= ~(1u << battler); for (i = 0; i < ARRAY_COUNT(gSideTimers); i++) { @@ -3426,26 +3419,25 @@ static void DoBattleIntro(void) { s32 i; u32 battler; - u8 *state = &gBattleStruct->introState; - switch (*state) + switch (gBattleStruct->introState) { - case 0: // Get Data of all battlers. + case BATTLE_INTRO_STATE_GET_MON_DATA: battler = gBattleCommunication[1]; BtlController_EmitGetMonData(battler, BUFFER_A, REQUEST_ALL_BATTLE, 0); MarkBattlerForControllerExec(battler); - (*state)++; + gBattleStruct->introState++; break; - case 1: // Loop through all battlers. + case BATTLE_INTRO_STATE_LOOP_BATTLER_DATA: if (!gBattleControllerExecFlags) { if (++gBattleCommunication[1] == gBattlersCount) - (*state)++; + gBattleStruct->introState++; else - *state = 0; + gBattleStruct->introState = BATTLE_INTRO_STATE_GET_MON_DATA; } break; - case 2: // Start graphical intro slide. + case BATTLE_INTRO_STATE_PREPARE_BG_SLIDE: if (!gBattleControllerExecFlags) { battler = GetBattlerAtPosition(0); @@ -3453,14 +3445,14 @@ static void DoBattleIntro(void) MarkBattlerForControllerExec(battler); gBattleCommunication[0] = 0; gBattleCommunication[1] = 0; - (*state)++; + gBattleStruct->introState++; } break; - case 3: // Wait for intro slide. + case BATTLE_INTRO_STATE_WAIT_FOR_BG_SLIDE: if (!gBattleControllerExecFlags) - (*state)++; + gBattleStruct->introState++; break; - case 4: // Copy battler data gotten in cases 0 and 1. Draw trainer/mon sprite. + case BATTLE_INTRO_STATE_DRAW_SPRITES: for (battler = 0; battler < gBattlersCount; battler++) { if ((gBattleTypeFlags & BATTLE_TYPE_SAFARI) && GetBattlerSide(battler) == B_SIDE_PLAYER) @@ -3540,17 +3532,17 @@ static void DoBattleIntro(void) if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { - (*state)++; + gBattleStruct->introState++; } else // Skip party summary since it is a wild battle. { if (B_FAST_INTRO == TRUE) - *state = 7; // Don't wait for sprite, print message at the same time. + gBattleStruct->introState = BATTLE_INTRO_STATE_INTRO_TEXT; // Don't wait for sprite, print message at the same time. else - *state = 6; // Wait for sprite to load. + gBattleStruct->introState++; // Wait for sprite to load. } break; - case 5: // draw party summary in trainer battles + case BATTLE_INTRO_STATE_DRAW_PARTY_SUMMARY: if (!gBattleControllerExecFlags) { struct HpAndStatus hpStatus[PARTY_SIZE]; @@ -3593,48 +3585,48 @@ static void DoBattleIntro(void) BtlController_EmitDrawPartyStatusSummary(battler, BUFFER_A, hpStatus, PARTY_SUMM_SKIP_DRAW_DELAY); MarkBattlerForControllerExec(battler); - (*state)++; + gBattleStruct->introState++; } break; - case 6: // wait for previous action to complete + case BATTLE_INTRO_STATE_WAIT_FOR_PARTY_SUMMARY: if (!gBattleControllerExecFlags) - (*state)++; + gBattleStruct->introState++; break; - case 7: // print battle intro message + case BATTLE_INTRO_STATE_INTRO_TEXT: if (!IsBattlerMarkedForControllerExec(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT))) { PrepareStringBattle(STRINGID_INTROMSG, GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)); - (*state)++; + gBattleStruct->introState++; } break; - case 8: // wait for intro message to be printed + case BATTLE_INTRO_STATE_WAIT_FOR_INTRO_TEXT: if (!IsBattlerMarkedForControllerExec(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT))) { if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { - (*state)++; + gBattleStruct->introState++; } else { if (B_FAST_INTRO == TRUE) - *state = 15; // Wait for text to be printed. + gBattleStruct->introState = BATTLE_INTRO_STATE_WAIT_FOR_WILD_BATTLE_TEXT; else - *state = 14; // Wait for text and sprite. + gBattleStruct->introState = BATTLE_INTRO_STATE_WAIT_FOR_TRAINER_2_SEND_OUT_ANIM; } } break; - case 9: // print opponent sends out + case BATTLE_INTRO_STATE_TRAINER_SEND_OUT_TEXT: if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK && !(gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER)) PrepareStringBattle(STRINGID_INTROSENDOUT, GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)); else PrepareStringBattle(STRINGID_INTROSENDOUT, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)); - (*state)++; + gBattleStruct->introState++; break; - case 10: // wait for opponent sends out text + case BATTLE_INTRO_STATE_WAIT_FOR_TRAINER_SEND_OUT_TEXT: if (!gBattleControllerExecFlags) - (*state)++; + gBattleStruct->introState++; break; - case 11: // first opponent's mon send out animation + case BATTLE_INTRO_STATE_TRAINER_1_SEND_OUT_ANIM: if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK && !(gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER)) battler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); else @@ -3642,11 +3634,9 @@ static void DoBattleIntro(void) BtlController_EmitIntroTrainerBallThrow(battler, BUFFER_A); MarkBattlerForControllerExec(battler); - (*state)++; + gBattleStruct->introState++; break; - case 12: // nothing - (*state)++; - case 13: // second opponent's mon send out + case BATTLE_INTRO_STATE_TRAINER_2_SEND_OUT_ANIM: if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS) && !BATTLE_TWO_VS_ONE_OPPONENT) { if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK && !(gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER)) @@ -3659,19 +3649,19 @@ static void DoBattleIntro(void) } if (B_FAST_INTRO == TRUE && !(gBattleTypeFlags & (BATTLE_TYPE_RECORDED | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_RECORDED_IS_MASTER | BATTLE_TYPE_LINK))) - *state = 15; // Print at the same time as trainer sends out second mon. + gBattleStruct->introState = BATTLE_INTRO_STATE_WAIT_FOR_WILD_BATTLE_TEXT; // Print at the same time as trainer sends out second mon. else - (*state)++; + gBattleStruct->introState++; break; - case 14: // wait for opponent 2 send out + case BATTLE_INTRO_STATE_WAIT_FOR_TRAINER_2_SEND_OUT_ANIM: if (!gBattleControllerExecFlags) - (*state)++; + gBattleStruct->introState++; break; - case 15: // wait for wild battle message + case BATTLE_INTRO_STATE_WAIT_FOR_WILD_BATTLE_TEXT: if (!IsBattlerMarkedForControllerExec(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT))) - (*state)++; + gBattleStruct->introState++; break; - case 16: // print player sends out + case BATTLE_INTRO_STATE_PRINT_PLAYER_SEND_OUT_TEXT: if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI)) { if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK && !(gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER)) @@ -3690,9 +3680,9 @@ static void DoBattleIntro(void) PrepareStringBattle(STRINGID_INTROSENDOUT, battler); } - (*state)++; + gBattleStruct->introState++; break; - case 17: // wait for player send out message + case BATTLE_INTRO_STATE_WAIT_FOR_PLAYER_SEND_OUT_TEXT: if (!(gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleControllerExecFlags)) { if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK && !(gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER)) @@ -3701,10 +3691,10 @@ static void DoBattleIntro(void) battler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); if (!IsBattlerMarkedForControllerExec(battler)) - (*state)++; + gBattleStruct->introState++; } break; - case 18: // player 1 send out + case BATTLE_INTRO_STATE_PRINT_PLAYER_1_SEND_OUT_TEXT: if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK && !(gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER)) battler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); else @@ -3712,9 +3702,9 @@ static void DoBattleIntro(void) BtlController_EmitIntroTrainerBallThrow(battler, BUFFER_A); MarkBattlerForControllerExec(battler); - (*state)++; + gBattleStruct->introState++; break; - case 19: // player 2 send out + case BATTLE_INTRO_STATE_PRINT_PLAYER_2_SEND_OUT_TEXT: if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER)) { if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK && !(gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER)) @@ -3725,9 +3715,9 @@ static void DoBattleIntro(void) BtlController_EmitIntroTrainerBallThrow(battler, BUFFER_A); MarkBattlerForControllerExec(battler); } - (*state)++; + gBattleStruct->introState++; break; - case 20: // set dex and battle vars + case BATTLE_INTRO_STATE_SET_DEX_AND_BATTLE_VARS: if (!gBattleControllerExecFlags) { for (battler = 0; battler < gBattlersCount; battler++) @@ -3756,7 +3746,7 @@ static void DoBattleIntro(void) gBattleStruct->startingStatus = GetTrainerStartingStatusFromId(gTrainerBattleOpponent_B); gBattleStruct->startingStatusTimer = 0; // infinite } - else if (GetTrainerStartingStatusFromId(gTrainerBattleOpponent_A)) + else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && GetTrainerStartingStatusFromId(gTrainerBattleOpponent_A)) { gBattleStruct->startingStatus = GetTrainerStartingStatusFromId(gTrainerBattleOpponent_A); gBattleStruct->startingStatusTimer = 0; // infinite @@ -3790,7 +3780,7 @@ static void TryDoEventsBeforeFirstTurn(void) struct Pokemon *party = GetBattlerParty(i); struct Pokemon *mon = &party[gBattlerPartyIndexes[i]]; if (!IsBattlerAlive(i) || gBattleMons[i].species == SPECIES_NONE || GetMonData(mon, MON_DATA_IS_EGG)) - gAbsentBattlerFlags |= gBitTable[i]; + gAbsentBattlerFlags |= 1u << i; } } @@ -3923,7 +3913,7 @@ static void TryDoEventsBeforeFirstTurn(void) gBattleMons[i].status2 &= ~STATUS2_FLINCHED; // Record party slots of player's mons that appeared in battle if (!BattlerHasAi(i)) - gBattleStruct->appearedInBattle |= gBitTable[gBattlerPartyIndexes[i]]; + gBattleStruct->appearedInBattle |= 1u << gBattlerPartyIndexes[i]; } *(&gBattleStruct->turnEffectsTracker) = 0; @@ -4039,6 +4029,11 @@ void BattleTurnPassed(void) SetAiLogicDataForTurn(AI_DATA); // get assumed abilities, hold effects, etc of all battlers gBattleMainFunc = HandleTurnActionSelectionState; + if (gSideTimers[B_SIDE_PLAYER].retaliateTimer > 0) + gSideTimers[B_SIDE_PLAYER].retaliateTimer--; + if (gSideTimers[B_SIDE_OPPONENT].retaliateTimer > 0) + gSideTimers[B_SIDE_OPPONENT].retaliateTimer--; + if (gBattleTypeFlags & BATTLE_TYPE_PALACE) BattleScriptExecute(BattleScript_PalacePrintFlavorText); else if (gBattleTypeFlags & BATTLE_TYPE_ARENA && gBattleStruct->arenaTurnCounter == 0) @@ -4136,7 +4131,7 @@ void SwitchPartyOrder(u32 battler) partyId2 = GetPartyIdFromBattlePartyId(*(gBattleStruct->monToSwitchIntoId + battler)); SwitchPartyMonSlots(partyId1, partyId2); - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { for (i = 0; i < (int)ARRAY_COUNT(gBattlePartyCurrentOrder); i++) { @@ -4195,10 +4190,10 @@ static void HandleTurnActionSelectionState(void) *(gBattleStruct->monToSwitchIntoId + battler) = PARTY_SIZE; if (gBattleTypeFlags & BATTLE_TYPE_MULTI || (position & BIT_FLANK) == B_FLANK_LEFT - || gBattleStruct->absentBattlerFlags & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(position))] + || gBattleStruct->absentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(position))) || gBattleCommunication[GetBattlerAtPosition(BATTLE_PARTNER(position))] == STATE_WAIT_ACTION_CONFIRMED) { - if (gBattleStruct->absentBattlerFlags & gBitTable[battler]) + if (gBattleStruct->absentBattlerFlags & (1u << battler)) { gChosenActionByBattler[battler] = B_ACTION_NOTHING_FAINTED; if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI)) @@ -4234,7 +4229,7 @@ static void HandleTurnActionSelectionState(void) } break; case STATE_WAIT_ACTION_CHOSEN: // Try to perform an action. - if (!(gBattleControllerExecFlags & ((gBitTable[battler]) | (0xF << 28) | (gBitTable[battler] << 4) | (gBitTable[battler] << 8) | (gBitTable[battler] << 12)))) + if (!(gBattleControllerExecFlags & (((1u << battler)) | (0xF << 28) | ((1u << battler) << 4) | ((1u << battler) << 8) | ((1u << battler) << 12)))) { RecordedBattle_SetBattlerAction(battler, gBattleResources->bufferB[battler][1]); gChosenActionByBattler[battler] = gBattleResources->bufferB[battler][1]; @@ -4277,7 +4272,7 @@ static void HandleTurnActionSelectionState(void) i); } - BtlController_EmitChooseMove(battler, BUFFER_A, (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) != 0, FALSE, &moveInfo); + BtlController_EmitChooseMove(battler, BUFFER_A, IsDoubleBattle() != 0, FALSE, &moveInfo); MarkBattlerForControllerExec(battler); } break; @@ -4386,7 +4381,7 @@ static void HandleTurnActionSelectionState(void) RecordedBattle_ClearBattlerAction(GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler))), 3); } - gBattleStruct->gimmick.toActivate &= ~(gBitTable[BATTLE_PARTNER(GetBattlerPosition(battler))]); + gBattleStruct->gimmick.toActivate &= ~((1u << BATTLE_PARTNER(GetBattlerPosition(battler)))); BtlController_EmitEndBounceEffect(battler, BUFFER_A); MarkBattlerForControllerExec(battler); return; @@ -4429,7 +4424,7 @@ static void HandleTurnActionSelectionState(void) } break; case STATE_WAIT_ACTION_CASE_CHOSEN: - if (!(gBattleControllerExecFlags & ((gBitTable[battler]) | (0xF << 28) | (gBitTable[battler] << 4) | (gBitTable[battler] << 8) | (gBitTable[battler] << 12)))) + if (!(gBattleControllerExecFlags & (((1u << battler)) | (0xF << 28) | ((1u << battler) << 4) | ((1u << battler) << 8) | ((1u << battler) << 12)))) { switch (gChosenActionByBattler[battler]) { @@ -4480,7 +4475,7 @@ static void HandleTurnActionSelectionState(void) // Check to see if any gimmicks need to be prepared. if (gBattleResources->bufferB[battler][2] & RET_GIMMICK) - gBattleStruct->gimmick.toActivate |= gBitTable[battler]; + gBattleStruct->gimmick.toActivate |= 1u << battler; // Max Move check if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX || IsGimmickSelected(battler, GIMMICK_DYNAMAX)) @@ -4559,20 +4554,20 @@ static void HandleTurnActionSelectionState(void) } break; case STATE_WAIT_ACTION_CONFIRMED_STANDBY: - if (!(gBattleControllerExecFlags & ((gBitTable[battler]) + if (!(gBattleControllerExecFlags & ((1u << battler) | (0xF << 28) - | (gBitTable[battler] << 4) - | (gBitTable[battler] << 8) - | (gBitTable[battler] << 12)))) + | (1u << (battler + 4)) + | (1u << (battler + 8)) + | (1u << (battler + 12))))) { if (AllAtActionConfirmed()) i = TRUE; else i = FALSE; - if (((gBattleTypeFlags & BATTLE_TYPE_MULTI) || !(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + if (((gBattleTypeFlags & BATTLE_TYPE_MULTI) || !IsDoubleBattle()) || (position & BIT_FLANK) != B_FLANK_LEFT - || (*(&gBattleStruct->absentBattlerFlags) & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(position))])) + || (*(&gBattleStruct->absentBattlerFlags) & (1u << GetBattlerAtPosition(BATTLE_PARTNER(position))))) { BtlController_EmitLinkStandbyMsg(battler, BUFFER_A, LINK_STANDBY_MSG_STOP_BOUNCE, i); } @@ -4585,7 +4580,7 @@ static void HandleTurnActionSelectionState(void) } break; case STATE_WAIT_ACTION_CONFIRMED: - if (!(gBattleControllerExecFlags & ((gBitTable[battler]) | (0xF << 28) | (gBitTable[battler] << 4) | (gBitTable[battler] << 8) | (gBitTable[battler] << 12)))) + if (!(gBattleControllerExecFlags & ((1u << battler) | (0xF << 28) | (1u << (battler + 4)) | (1u << (battler + 8)) | (1u << (battler + 12))))) { gBattleCommunication[ACTIONS_CONFIRMED_COUNT]++; } @@ -4599,7 +4594,7 @@ static void HandleTurnActionSelectionState(void) { gBattlerAttacker = battler; gBattlescriptCurrInstr = gSelectionBattleScripts[battler]; - if (!(gBattleControllerExecFlags & ((gBitTable[battler]) | (0xF << 28) | (gBitTable[battler] << 4) | (gBitTable[battler] << 8) | (gBitTable[battler] << 12)))) + if (!(gBattleControllerExecFlags & ((1u << battler) | (0xF << 28) | (1u << (battler + 4)) | (1u << (battler + 8)) | (1u << (battler + 12))))) { gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]](); } @@ -4607,7 +4602,7 @@ static void HandleTurnActionSelectionState(void) } break; case STATE_WAIT_SET_BEFORE_ACTION: - if (!(gBattleControllerExecFlags & ((gBitTable[battler]) | (0xF << 28) | (gBitTable[battler] << 4) | (gBitTable[battler] << 8) | (gBitTable[battler] << 12)))) + if (!(gBattleControllerExecFlags & ((1u << battler) | (0xF << 28) | (1u << (battler + 4)) | (1u << (battler + 8)) | (1u << (battler + 12))))) { gBattleCommunication[battler] = STATE_BEFORE_ACTION_CHOSEN; } @@ -4631,7 +4626,7 @@ static void HandleTurnActionSelectionState(void) { gBattlerAttacker = battler; gBattlescriptCurrInstr = gSelectionBattleScripts[battler]; - if (!(gBattleControllerExecFlags & ((gBitTable[battler]) | (0xF << 28) | (gBitTable[battler] << 4) | (gBitTable[battler] << 8) | (gBitTable[battler] << 12)))) + if (!(gBattleControllerExecFlags & ((1u << battler) | (0xF << 28) | (1u << (battler + 4)) | (1u << (battler + 8)) | (1u << (battler + 12))))) { gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]](); } @@ -4717,7 +4712,6 @@ void SwapTurnOrder(u8 id1, u8 id2) u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, u32 holdEffect) { u32 speed = gBattleMons[battler].speed; - u32 highestStat = GetHighestStatId(battler); // weather abilities if (WEATHER_HAS_EFFECT) @@ -4739,10 +4733,10 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, u32 holdEffect) speed *= 2; else if (ability == ABILITY_SLOW_START && gDisableStructs[battler].slowStartTimer != 0) speed /= 2; - else if (ability == ABILITY_PROTOSYNTHESIS && gBattleWeather & B_WEATHER_SUN && highestStat == STAT_SPEED) - speed = (speed * 150) / 100; - else if (ability == ABILITY_QUARK_DRIVE && gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && highestStat == STAT_SPEED) - speed = (speed * 150) / 100; + else if (ability == ABILITY_PROTOSYNTHESIS && (gBattleWeather & B_WEATHER_SUN || gBattleStruct->boosterEnergyActivates & (1u << battler))) + speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed; + else if (ability == ABILITY_QUARK_DRIVE && (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gBattleStruct->boosterEnergyActivates & (1u << battler))) + speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed; // stat stages speed *= gStatStageRatios[gBattleMons[battler].statStages[STAT_SPEED]][0]; @@ -5115,6 +5109,7 @@ static void TurnValuesCleanUp(bool8 var0) if (gDisableStructs[i].rechargeTimer == 0) gBattleMons[i].status2 &= ~STATUS2_RECHARGE; } + gBattleStruct->canPickupItem &= ~(1u << i); } if (gDisableStructs[i].substituteHP == 0) @@ -5155,10 +5150,10 @@ 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 & gBitTable[order[i]]) && !(gProtectStructs[order[i]].noValidMoves)) + if ((gBattleStruct->gimmick.toActivate & (1u << order[i])) && !(gProtectStructs[order[i]].noValidMoves)) { battler = gBattlerAttacker = gBattleScripting.battler = order[i]; - gBattleStruct->gimmick.toActivate &= ~(gBitTable[battler]); + gBattleStruct->gimmick.toActivate &= ~(1u << battler); if (gGimmicksInfo[gBattleStruct->gimmick.usableGimmick[battler]].ActivateGimmick != NULL) { gGimmicksInfo[gBattleStruct->gimmick.usableGimmick[battler]].ActivateGimmick(battler); @@ -5184,12 +5179,12 @@ static bool32 TryDoMoveEffectsBeforeMoves(void) SortBattlersBySpeed(battlers, FALSE); for (i = 0; i < gBattlersCount; i++) { - if (!(gBattleStruct->focusPunchBattlers & gBitTable[battlers[i]]) + if (!(gBattleStruct->focusPunchBattlers & (1u << battlers[i])) && !(gBattleMons[battlers[i]].status1 & STATUS1_SLEEP) && !(gDisableStructs[battlers[i]].truantCounter) && !(gProtectStructs[battlers[i]].noValidMoves)) { - gBattleStruct->focusPunchBattlers |= gBitTable[battlers[i]]; + gBattleStruct->focusPunchBattlers |= 1u << battlers[i]; gBattlerAttacker = battlers[i]; switch (gChosenMoveByBattler[gBattlerAttacker]) { @@ -5561,7 +5556,7 @@ static void HandleEndTurn_FinishBattle(void) bool8 changedForm = FALSE; // Appeared in battle and didn't faint - if ((gBattleStruct->appearedInBattle & gBitTable[i]) && GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0) + if ((gBattleStruct->appearedInBattle & (1u << i)) && GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0) changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE_TERRAIN); if (!changedForm) @@ -5636,15 +5631,15 @@ static void TryEvolvePokemon(void) for (i = 0; i < PARTY_SIZE; i++) { - if (!(sTriedEvolving & gBitTable[i])) + if (!(sTriedEvolving & (1u << i))) { u16 species = GetEvolutionTargetSpecies(&gPlayerParty[i], EVO_MODE_BATTLE_SPECIAL, i, NULL); bool32 evoModeNormal = TRUE; - sTriedEvolving |= gBitTable[i]; + sTriedEvolving |= 1u << i; - if (species == SPECIES_NONE && (gLeveledUpInBattle & gBitTable[i])) + if (species == SPECIES_NONE && (gLeveledUpInBattle & (1u << i))) { - gLeveledUpInBattle &= ~(gBitTable[i]); + gLeveledUpInBattle &= ~(1u << i); species = GetEvolutionTargetSpecies(&gPlayerParty[i], EVO_MODE_BATTLE_ONLY, gLeveledUpInBattle, NULL); } @@ -5742,8 +5737,10 @@ bool32 TrySetAteType(u32 move, u32 battlerAtk, u32 attackerAbility) break; case EFFECT_HIDDEN_POWER: case EFFECT_WEATHER_BALL: - case EFFECT_CHANGE_TYPE_ON_ITEM: case EFFECT_NATURAL_GIFT: + case EFFECT_CHANGE_TYPE_ON_ITEM: + case EFFECT_REVELATION_DANCE: + case EFFECT_TERRAIN_PULSE: return FALSE; } @@ -5824,16 +5821,20 @@ void SetTypeBeforeUsingMove(u32 move, u32 battlerAtk) { gBattleStruct->dynamicMoveType = ItemId_GetSecondaryId(gBattleMons[battlerAtk].item) | F_DYNAMIC_TYPE_SET; } - else if (gMovesInfo[move].effect == EFFECT_REVELATION_DANCE) + else if (gMovesInfo[move].effect == EFFECT_REVELATION_DANCE && GetActiveGimmick(battlerAtk) != GIMMICK_Z_MOVE) { if (GetActiveGimmick(battlerAtk) == GIMMICK_TERA && GetBattlerTeraType(battlerAtk) != TYPE_STELLAR) gBattleStruct->dynamicMoveType = GetBattlerTeraType(battlerAtk); - else if (gBattleMons[battlerAtk].types[0] != TYPE_MYSTERY) + else if (gBattleMons[battlerAtk].types[0] != TYPE_MYSTERY && !(gBattleResources->flags->flags[battlerAtk] & RESOURCE_FLAG_ROOST && gBattleMons[battlerAtk].types[0] == TYPE_FLYING)) gBattleStruct->dynamicMoveType = gBattleMons[battlerAtk].types[0] | F_DYNAMIC_TYPE_SET; - else if (gBattleMons[battlerAtk].types[1] != TYPE_MYSTERY) + else if (gBattleMons[battlerAtk].types[1] != TYPE_MYSTERY && !(gBattleResources->flags->flags[battlerAtk] & RESOURCE_FLAG_ROOST && gBattleMons[battlerAtk].types[1] == TYPE_FLYING)) gBattleStruct->dynamicMoveType = gBattleMons[battlerAtk].types[1] | F_DYNAMIC_TYPE_SET; + else if (gBattleResources->flags->flags[battlerAtk] & RESOURCE_FLAG_ROOST) + gBattleStruct->dynamicMoveType = (B_ROOST_PURE_FLYING >= GEN_5 ? TYPE_NORMAL : TYPE_MYSTERY) | F_DYNAMIC_TYPE_SET; else if (gBattleMons[battlerAtk].types[2] != TYPE_MYSTERY) gBattleStruct->dynamicMoveType = gBattleMons[battlerAtk].types[2] | F_DYNAMIC_TYPE_SET; + else + gBattleStruct->dynamicMoveType = TYPE_MYSTERY | F_DYNAMIC_TYPE_SET; } else if (gMovesInfo[move].effect == EFFECT_RAGING_BULL && (gBattleMons[battlerAtk].species == SPECIES_TAUROS_PALDEAN_COMBAT_BREED diff --git a/src/battle_message.c b/src/battle_message.c index 87ac5326fb..69be69a14f 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -849,9 +849,11 @@ static const u8 sText_ShedItsTail[] = _("{B_ATK_NAME_WITH_PREFIX} shed its tail\ static const u8 sText_PkmnTerastallizedInto[] = _("{B_ATK_NAME_WITH_PREFIX} terastallized\ninto the {B_BUFF1} type!"); static const u8 sText_SupersweetAromaWafts[] = _("A supersweet aroma is wafting from\nthe syrup covering {B_ATK_NAME_WITH_PREFIX}!"); static const u8 sText_TidyingUpComplete[] = _("Tidying up complete!"); +static const u8 sText_FickleBeamDoubled[] = _("{B_ATK_NAME_WITH_PREFIX} is going all\nout for this attack!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_FICKLEBEAMDOUBLED - BATTLESTRINGS_TABLE_START] = sText_FickleBeamDoubled, [STRINGID_PKMNTERASTALLIZEDINTO - BATTLESTRINGS_TABLE_START] = sText_PkmnTerastallizedInto, [STRINGID_TIDYINGUPCOMPLETE - BATTLESTRINGS_TABLE_START] = sText_TidyingUpComplete, [STRINGID_SUPERSWEETAROMAWAFTS - BATTLESTRINGS_TABLE_START] = sText_SupersweetAromaWafts, @@ -2826,7 +2828,7 @@ void BufferStringBattle(u16 stringID, u32 battler) { if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) stringPtr = sText_LegendaryPkmnAppeared; - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)]])) + else if (IsDoubleBattle() && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)]])) stringPtr = sText_TwoWildPkmnAppeared; else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL) stringPtr = sText_WildPkmnAppearedPause; @@ -2837,7 +2839,7 @@ void BufferStringBattle(u16 stringID, u32 battler) case STRINGID_INTROSENDOUT: // poke first send-out if (GetBattlerSide(battler) == B_SIDE_PLAYER) { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gPlayerParty[gBattlerPartyIndexes[BATTLE_PARTNER(battler)]])) + if (IsDoubleBattle() && IsValidForBattle(&gPlayerParty[gBattlerPartyIndexes[BATTLE_PARTNER(battler)]])) { if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) stringPtr = sText_InGamePartnerSentOutZGoN; @@ -2855,7 +2857,7 @@ void BufferStringBattle(u16 stringID, u32 battler) } else { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[BATTLE_PARTNER(battler)]])) + if (IsDoubleBattle() && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[BATTLE_PARTNER(battler)]])) { if (BATTLE_TWO_VS_ONE_OPPONENT) stringPtr = sText_Trainer1SentOutTwoPkmn; @@ -2886,7 +2888,7 @@ void BufferStringBattle(u16 stringID, u32 battler) { if (*(&gBattleStruct->hpScale) == 0) stringPtr = sText_PkmnThatsEnough; - else if (*(&gBattleStruct->hpScale) == 1 || gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + else if (*(&gBattleStruct->hpScale) == 1 || IsDoubleBattle()) stringPtr = sText_PkmnComeBack; else if (*(&gBattleStruct->hpScale) == 2) stringPtr = sText_PkmnOkComeBack; @@ -2911,7 +2913,7 @@ void BufferStringBattle(u16 stringID, u32 battler) case STRINGID_SWITCHINMON: // switch-in msg if (GetBattlerSide(gBattleScripting.battler) == B_SIDE_PLAYER) { - if (*(&gBattleStruct->hpScale) == 0 || gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (*(&gBattleStruct->hpScale) == 0 || IsDoubleBattle()) stringPtr = sText_GoPkmn2; else if (*(&gBattleStruct->hpScale) == 1) stringPtr = sText_DoItPkmn; diff --git a/src/battle_pyramid.c b/src/battle_pyramid.c index ce7a0526f2..aa3c63ef82 100644 --- a/src/battle_pyramid.c +++ b/src/battle_pyramid.c @@ -1081,7 +1081,7 @@ static void ShowPostBattleHintText(void) textIndex = sPyramidFloorTemplates[id].numTrainers; for (i = 0; i < MAX_PYRAMID_TRAINERS; i++) { - if (gBitTable[i] & gSaveBlock2Ptr->frontier.pyramidTrainerFlags) + if ((1u << i) & gSaveBlock2Ptr->frontier.pyramidTrainerFlags) textIndex--; } i = 1; @@ -1317,7 +1317,7 @@ u16 LocalIdToPyramidTrainerId(u8 localId) bool8 GetBattlePyramidTrainerFlag(u8 eventId) { - return gSaveBlock2Ptr->frontier.pyramidTrainerFlags & gBitTable[gObjectEvents[eventId].localId - 1]; + return gSaveBlock2Ptr->frontier.pyramidTrainerFlags & ((1u << gObjectEvents[eventId].localId) - 1); } void MarkApproachingPyramidTrainersAsBattled(void) @@ -1337,7 +1337,7 @@ static void MarkPyramidTrainerAsBattled(u16 trainerId) for (i = 0; i < MAX_PYRAMID_TRAINERS; i++) { if (gSaveBlock2Ptr->frontier.trainerIds[i] == trainerId) - gSaveBlock2Ptr->frontier.pyramidTrainerFlags |= gBitTable[i]; + gSaveBlock2Ptr->frontier.pyramidTrainerFlags |= 1u << i; } gObjectEvents[gSelectedObjectEvent].movementType = MOVEMENT_TYPE_WANDER_AROUND; @@ -1893,12 +1893,12 @@ static void SetPyramidObjectPositionsUniformly(u8 objType) { if (bits & 1) { - if (!(gBitTable[squareId] & gSaveBlock2Ptr->frontier.pyramidRandoms[3])) + if (!((1u << squareId) & gSaveBlock2Ptr->frontier.pyramidRandoms[3])) bits |= 2; } else { - if (gBitTable[squareId] & gSaveBlock2Ptr->frontier.pyramidRandoms[3]) + if ((1u << squareId) & gSaveBlock2Ptr->frontier.pyramidRandoms[3]) bits |= 2; } if (++squareId >= NUM_PYRAMID_FLOOR_SQUARES) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 575e1cd043..00f28a608b 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1173,7 +1173,7 @@ bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType) bool32 ShouldTeraShellDistortTypeMatchups(u32 move, u32 battlerDef) { - if (!(gBattleStruct->distortedTypeMatchups & gBitTable[battlerDef]) + if (!(gBattleStruct->distortedTypeMatchups & (1u << battlerDef)) && GetBattlerAbility(battlerDef) == ABILITY_TERA_SHELL && gBattleMons[battlerDef].species == SPECIES_TERAPAGOS_TERASTAL && !IS_MOVE_STATUS(move) @@ -1242,7 +1242,7 @@ static void Cmd_attackcanceler(void) if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_OFF && GetBattlerAbility(gBattlerAttacker) == ABILITY_PARENTAL_BOND && IsMoveAffectedByParentalBond(gCurrentMove, gBattlerAttacker) - && !(gAbsentBattlerFlags & gBitTable[gBattlerTarget]) + && !(gAbsentBattlerFlags & (1u << gBattlerTarget)) && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE) { gSpecialStatuses[gBattlerAttacker].parentalBondState = PARENTAL_BOND_1ST_HIT; @@ -1364,9 +1364,8 @@ static void Cmd_attackcanceler(void) } // Z-moves and Max Moves bypass protection, but deal reduced damage (factored in AccumulateOtherModifiers) - if ((IsZMove(gCurrentMove) - || IsMaxMove(gCurrentMove)) - && IS_BATTLER_PROTECTED(gBattlerTarget)) + if ((IsZMove(gCurrentMove) || IsMaxMove(gCurrentMove)) + && IS_BATTLER_PROTECTED(gBattlerTarget)) { BattleScriptPush(cmd->nextInstr); gBattlescriptCurrInstr = BattleScript_CouldntFullyProtect; @@ -1492,14 +1491,14 @@ static bool32 AccuracyCalcHelper(u16 move) return TRUE; } // If the attacker has the ability No Guard and they aren't targeting a Pokemon involved in a Sky Drop with the move Sky Drop, move hits. - else if (GetBattlerAbility(gBattlerAttacker) == ABILITY_NO_GUARD && (move != MOVE_SKY_DROP || gBattleStruct->skyDropTargets[gBattlerTarget] == 0xFF)) + else if (GetBattlerAbility(gBattlerAttacker) == ABILITY_NO_GUARD && (gMovesInfo[move].effect != EFFECT_SKY_DROP || gBattleStruct->skyDropTargets[gBattlerTarget] == 0xFF)) { if (!JumpIfMoveFailed(7, move)) RecordAbilityBattle(gBattlerAttacker, ABILITY_NO_GUARD); return TRUE; } // If the target has the ability No Guard and they aren't involved in a Sky Drop or the current move isn't Sky Drop, move hits. - else if (GetBattlerAbility(gBattlerTarget) == ABILITY_NO_GUARD && (move != MOVE_SKY_DROP || gBattleStruct->skyDropTargets[gBattlerTarget] == 0xFF)) + else if (GetBattlerAbility(gBattlerTarget) == ABILITY_NO_GUARD && (gMovesInfo[move].effect != EFFECT_SKY_DROP || gBattleStruct->skyDropTargets[gBattlerTarget] == 0xFF)) { if (!JumpIfMoveFailed(7, move)) RecordAbilityBattle(gBattlerTarget, ABILITY_NO_GUARD); @@ -1752,7 +1751,7 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u return; } - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && + if (IsDoubleBattle() && (moveTarget == MOVE_TARGET_BOTH || moveTarget == MOVE_TARGET_FOES_AND_ALLY)) gBattleCommunication[MISS_TYPE] = B_MSG_AVOIDED_ATK; else @@ -1848,7 +1847,7 @@ static void Cmd_ppreduce(void) if (ShouldTeraShellDistortTypeMatchups(gCurrentMove, gBattlerTarget)) { - gBattleStruct->distortedTypeMatchups |= gBitTable[gBattlerTarget]; + gBattleStruct->distortedTypeMatchups |= 1u << gBattlerTarget; gBattlerAbility = gBattlerTarget; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_TeraShellDistortingTypeMatchups; @@ -1988,7 +1987,7 @@ static void Cmd_adjustdamage(void) goto END; if (DoesDisguiseBlockMove(gBattlerTarget, gCurrentMove)) { - gBattleStruct->enduredDamage |= gBitTable[gBattlerTarget]; + gBattleStruct->enduredDamage |= 1u << gBattlerTarget; goto END; } if (GetBattlerAbility(gBattlerTarget) == ABILITY_ICE_FACE && IS_MOVE_PHYSICAL(gCurrentMove) && gBattleMons[gBattlerTarget].species == SPECIES_EISCUE) @@ -2042,7 +2041,7 @@ static void Cmd_adjustdamage(void) // Handle reducing the dmg to 1 hp. gBattleMoveDamage = gBattleMons[gBattlerTarget].hp - 1; - gBattleStruct->enduredDamage |= gBitTable[gBattlerTarget]; + gBattleStruct->enduredDamage |= 1u << gBattlerTarget; if (gProtectStructs[gBattlerTarget].endured) { @@ -2070,7 +2069,7 @@ END: gBattlescriptCurrInstr = cmd->nextInstr; if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && gBattleMoveDamage >= 1) - gSpecialStatuses[gBattlerAttacker].damagedMons |= gBitTable[gBattlerTarget]; + gSpecialStatuses[gBattlerAttacker].damagedMons |= (1 << (gBattlerTarget)); // Check gems and damage reducing berries. if (gSpecialStatuses[gBattlerTarget].berryReduced @@ -2145,7 +2144,7 @@ static void Cmd_multihitresultmessage(void) if (gSpecialStatuses[gBattlerTarget].berryReduced && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) { - gBattleStruct->ateBerry[gBattlerTarget & BIT_SIDE] |= gBitTable[gBattlerPartyIndexes[gBattlerTarget]]; + gBattleStruct->ateBerry[gBattlerTarget & BIT_SIDE] |= 1u << gBattlerPartyIndexes[gBattlerTarget]; gSpecialStatuses[gBattlerTarget].berryReduced = FALSE; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_PrintBerryReduceString; @@ -2166,7 +2165,7 @@ static void Cmd_attackanimation(void) && gCurrentMove != MOVE_SUBSTITUTE && gCurrentMove != MOVE_ALLY_SWITCH // In a wild double battle gotta use the teleport animation if two wild pokemon are alive. - && !(gCurrentMove == MOVE_TELEPORT && WILD_DOUBLE_BATTLE && GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT && IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker)))) + && !(gMovesInfo[gCurrentMove].effect == EFFECT_TELEPORT && WILD_DOUBLE_BATTLE && GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT && IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker)))) { BattleScriptPush(cmd->nextInstr); gBattlescriptCurrInstr = BattleScript_Pausex20; @@ -2498,7 +2497,7 @@ static void Cmd_resultmessage(void) if (gMoveResultFlags & MOVE_RESULT_MISSED && (!(gMoveResultFlags & MOVE_RESULT_DOESNT_AFFECT_FOE) || gBattleCommunication[MISS_TYPE] > B_MSG_AVOIDED_ATK)) { if (gBattleCommunication[MISS_TYPE] > B_MSG_AVOIDED_ATK) // Wonder Guard or Levitate - show the ability pop-up - CreateAbilityPopUp(gBattlerTarget, gBattleMons[gBattlerTarget].ability, (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) != 0); + CreateAbilityPopUp(gBattlerTarget, gBattleMons[gBattlerTarget].ability, (IsDoubleBattle()) != 0); stringId = gMissStringIds[gBattleCommunication[MISS_TYPE]]; gBattleCommunication[MSG_DISPLAY] = 1; } @@ -2606,7 +2605,7 @@ static void Cmd_resultmessage(void) if (gSpecialStatuses[gBattlerTarget].berryReduced && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) { - gBattleStruct->ateBerry[gBattlerTarget & BIT_SIDE] |= gBitTable[gBattlerPartyIndexes[gBattlerTarget]]; + gBattleStruct->ateBerry[gBattlerTarget & BIT_SIDE] |= 1u << gBattlerPartyIndexes[gBattlerTarget]; gSpecialStatuses[gBattlerTarget].berryReduced = FALSE; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_PrintBerryReduceString; @@ -3492,7 +3491,7 @@ void SetMoveEffect(bool32 primary, bool32 certain) && GetBattlerAbility(BATTLE_PARTNER(gBattlerTarget)) != ABILITY_MAGIC_GUARD) { gBattleScripting.savedBattler = BATTLE_PARTNER(gBattlerTarget); - gBattleMoveDamage = gBattleMons[BATTLE_PARTNER(gBattlerTarget)].hp / 16; + gBattleMoveDamage = gBattleMons[BATTLE_PARTNER(gBattlerTarget)].maxHP / 16; if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; gBattlescriptCurrInstr = BattleScript_MoveEffectFlameBurst; @@ -3531,7 +3530,7 @@ void SetMoveEffect(bool32 primary, bool32 certain) { bool32 byTwo = FALSE; - gBattleStruct->stolenStats[0] |= gBitTable[i]; + gBattleStruct->stolenStats[0] |= (1 << (i)); // Store by how many stages to raise the stat. gBattleStruct->stolenStats[i] = gBattleMons[gBattlerTarget].statStages[i] - DEFAULT_STAT_STAGE; while (gBattleMons[gBattlerAttacker].statStages[i] + gBattleStruct->stolenStats[i] > MAX_STAT_STAGE) @@ -3946,7 +3945,7 @@ static void Cmd_tryfaintmon(void) destinyBondBattler = gBattlerAttacker; faintScript = BattleScript_FaintTarget; } - if (!(gAbsentBattlerFlags & gBitTable[battler]) + if (!(gAbsentBattlerFlags & (1u << battler)) && !IsBattlerAlive(battler)) { gHitMarker |= HITMARKER_FAINTED(battler); @@ -4244,7 +4243,7 @@ static void Cmd_getexp(void) else { gBattleScripting.getexpState++; - gBattleStruct->givenExpMons |= gBitTable[gBattlerPartyIndexes[gBattlerFainted]]; + gBattleStruct->givenExpMons |= (1u << gBattlerPartyIndexes[gBattlerFainted]); } break; case 1: // calculate experience points to redistribute @@ -4261,25 +4260,25 @@ static void Cmd_getexp(void) { if (!IsValidForBattle(&gPlayerParty[i])) continue; - if (gBitTable[i] & sentInBits) + if ((1u << i) & sentInBits) viaSentIn++; holdEffect = GetMonHoldEffect(&gPlayerParty[i]); if (holdEffect == HOLD_EFFECT_EXP_SHARE || IsGen6ExpShareEnabled()) { - expShareBits |= gBitTable[i]; + expShareBits |= 1u << i; viaExpShare++; } } // Get order of mons getting exp: 1. all mons via sent in, 2. all mons via exp share for (i = 0; i < PARTY_SIZE; i++) { - if (gBitTable[i] & sentInBits) + if ((1u << i) & sentInBits) gBattleStruct->expGettersOrder[orderId++] = i; } for (i = 0; i < PARTY_SIZE; i++) { - if (!(gBitTable[i] & sentInBits) && gBitTable[i] & expShareBits) + if (!((1u << i) & sentInBits) && (1u << i) & expShareBits) gBattleStruct->expGettersOrder[orderId++] = i; } if (orderId < PARTY_SIZE) @@ -4331,7 +4330,7 @@ static void Cmd_getexp(void) case 2: // set exp value to the poke in expgetter_id and print message if (gBattleControllerExecFlags == 0) { - bool32 wasSentOut = ((gBattleStruct->expSentInMons & gBitTable[*expMonId]) != 0); + bool32 wasSentOut = (gBattleStruct->expSentInMons & (1u << *expMonId)) != 0; holdEffect = GetMonHoldEffect(&gPlayerParty[*expMonId]); if ((holdEffect != HOLD_EFFECT_EXP_SHARE && !wasSentOut && !IsGen6ExpShareEnabled()) @@ -4352,7 +4351,7 @@ static void Cmd_getexp(void) { // Music change in a wild battle after fainting opposing pokemon. if (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER) - && (gBattleMons[0].hp || (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && gBattleMons[2].hp)) + && (gBattleMons[0].hp || (IsDoubleBattle() && gBattleMons[2].hp)) && !IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)) && !IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)) && !gBattleStruct->wildVictorySong) @@ -4403,13 +4402,13 @@ static void Cmd_getexp(void) } // get exp getter battler - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { - if (gBattlerPartyIndexes[2] == *expMonId && !(gAbsentBattlerFlags & gBitTable[2])) + if (gBattlerPartyIndexes[2] == *expMonId && !(gAbsentBattlerFlags & 4)) gBattleStruct->expGetterBattlerId = 2; else { - if (!(gAbsentBattlerFlags & gBitTable[0])) + if (!(gAbsentBattlerFlags & 1)) gBattleStruct->expGetterBattlerId = 0; else gBattleStruct->expGetterBattlerId = 2; @@ -4475,7 +4474,7 @@ static void Cmd_getexp(void) PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff2, 3, GetMonData(&gPlayerParty[*expMonId], MON_DATA_LEVEL)); BattleScriptPushCursor(); - gLeveledUpInBattle |= gBitTable[*expMonId]; + gLeveledUpInBattle |= 1 << *expMonId; gBattlescriptCurrInstr = BattleScript_LevelUp; gBattleMoveDamage = T1_READ_32(&gBattleResources->bufferB[expBattler][2]); AdjustFriendship(&gPlayerParty[*expMonId], FRIENDSHIP_EVENT_GROW_LEVEL); @@ -4483,7 +4482,7 @@ static void Cmd_getexp(void) // update battle mon structure after level up if (gBattlerPartyIndexes[0] == *expMonId && gBattleMons[0].hp) battler = 0; - else if (gBattlerPartyIndexes[2] == *expMonId && gBattleMons[2].hp && (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + else if (gBattlerPartyIndexes[2] == *expMonId && gBattleMons[2].hp && (IsDoubleBattle())) battler = 2; if (battler != 0xFF) @@ -4548,7 +4547,7 @@ bool32 NoAliveMonsForPlayer(void) for (i = 0; i < maxI; i++) { if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) && !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG) - && (!(gBattleTypeFlags & BATTLE_TYPE_ARENA) || !(gBattleStruct->arenaLostPlayerMons & gBitTable[i]))) + && (!(gBattleTypeFlags & BATTLE_TYPE_ARENA) || !(gBattleStruct->arenaLostPlayerMons & (1u << i)))) { HP_count += GetMonData(&gPlayerParty[i], MON_DATA_HP); } @@ -4566,7 +4565,7 @@ static bool32 NoAliveMonsForOpponent(void) for (i = 0; i < PARTY_SIZE; i++) { if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES) && !GetMonData(&gEnemyParty[i], MON_DATA_IS_EGG) - && (!(gBattleTypeFlags & BATTLE_TYPE_ARENA) || !(gBattleStruct->arenaLostOpponentMons & gBitTable[i]))) + && (!(gBattleTypeFlags & BATTLE_TYPE_ARENA) || !(gBattleStruct->arenaLostOpponentMons & (1u << i)))) { HP_count += GetMonData(&gEnemyParty[i], MON_DATA_HP); } @@ -5339,7 +5338,7 @@ static bool32 TryKnockOffBattleScript(u32 battlerDef) } else { - gWishFutureKnock.knockedOffMons[side] |= gBitTable[gBattlerPartyIndexes[battlerDef]]; + gWishFutureKnock.knockedOffMons[side] |= 1u << gBattlerPartyIndexes[battlerDef]; } BattleScriptPushCursor(); @@ -5367,7 +5366,7 @@ static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent) if (i != gBattlerAttacker && !(excludeCurrent && i == gBattlerTarget) && IsBattlerAlive(i) - && !(gBattleStruct->targetsDone[gBattlerAttacker] & gBitTable[i]) + && !(gBattleStruct->targetsDone[gBattlerAttacker] & (1u << i)) && (GetBattlerSide(i) != GetBattlerSide(gBattlerAttacker) || moveTarget == MOVE_TARGET_FOES_AND_ALLY)) break; } @@ -5814,10 +5813,12 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_UPDATE_LAST_MOVES: - if (gMoveResultFlags & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE)) - gBattleStruct->lastMoveFailed |= gBitTable[gBattlerAttacker]; + if ((gMoveResultFlags & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE)) + || (gBattleMons[gBattlerAttacker].status2 & (STATUS2_FLINCHED)) + || gProtectStructs[gBattlerAttacker].prlzImmobility) + gBattleStruct->lastMoveFailed |= 1u << gBattlerAttacker; else - gBattleStruct->lastMoveFailed &= ~(gBitTable[gBattlerAttacker]); + gBattleStruct->lastMoveFailed &= ~(1u << gBattlerAttacker); // Set ShellTrap to activate after the attacker's turn if target was hit by a physical move. if (gMovesInfo[gChosenMoveByBattler[gBattlerTarget]].effect == EFFECT_SHELL_TRAP @@ -5843,7 +5844,7 @@ static void Cmd_moveend(void) } if (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove) { - gDisableStructs[gBattlerAttacker].usedMoves |= gBitTable[gCurrMovePos]; + gDisableStructs[gBattlerAttacker].usedMoves |= 1u << gCurrMovePos; gBattleStruct->lastMoveTarget[gBattlerAttacker] = gBattlerTarget; if (gHitMarker & HITMARKER_ATTACKSTRING_PRINTED) { @@ -5853,8 +5854,8 @@ static void Cmd_moveend(void) gBattleStruct->dynamax.lastUsedBaseMove = gBattleStruct->dynamax.baseMoves[gBattlerAttacker]; } } - if (!(gAbsentBattlerFlags & gBitTable[gBattlerAttacker]) - && !(gBattleStruct->absentBattlerFlags & gBitTable[gBattlerAttacker]) + if (!(gAbsentBattlerFlags & (1u << gBattlerAttacker)) + && !(gBattleStruct->absentBattlerFlags & (1u << gBattlerAttacker)) && gMovesInfo[originallyUsedMove].effect != EFFECT_BATON_PASS && gMovesInfo[originallyUsedMove].effect != EFFECT_HEALING_WISH) { @@ -5896,8 +5897,8 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_MIRROR_MOVE: // mirror move - if (!(gAbsentBattlerFlags & gBitTable[gBattlerAttacker]) - && !(gBattleStruct->absentBattlerFlags & gBitTable[gBattlerAttacker]) + if (!(gAbsentBattlerFlags & (1u << gBattlerAttacker)) + && !(gBattleStruct->absentBattlerFlags & (1u << gBattlerAttacker)) && !gMovesInfo[originallyUsedMove].mirrorMoveBanned && gHitMarker & HITMARKER_OBEYS && gBattlerAttacker != gBattlerTarget @@ -5917,9 +5918,9 @@ static void Cmd_moveend(void) && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) gProtectStructs[gBattlerAttacker].targetAffected = TRUE; - gBattleStruct->targetsDone[gBattlerAttacker] |= gBitTable[gBattlerTarget]; + gBattleStruct->targetsDone[gBattlerAttacker] |= 1u << gBattlerTarget; if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - && gBattleTypeFlags & BATTLE_TYPE_DOUBLE + && IsDoubleBattle() && !gProtectStructs[gBattlerAttacker].chargingTurn && (moveTarget == MOVE_TARGET_BOTH || moveTarget == MOVE_TARGET_FOES_AND_ALLY) @@ -5948,7 +5949,7 @@ static void Cmd_moveend(void) u8 originalBounceTarget = gBattlerAttacker; gBattleStruct->bouncedMoveIsUsed = FALSE; gBattlerAttacker = gBattleStruct->attackerBeforeBounce; - gBattleStruct->targetsDone[gBattlerAttacker] |= gBitTable[originalBounceTarget]; + gBattleStruct->targetsDone[gBattlerAttacker] |= 1u << originalBounceTarget; gBattleStruct->targetsDone[originalBounceTarget] = 0; nextTarget = GetNextTarget(moveTarget, FALSE); @@ -6051,7 +6052,7 @@ static void Cmd_moveend(void) && TARGET_TURN_DAMAGED && CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item) && !gSpecialStatuses[gBattlerAttacker].gemBoost // In base game, gems are consumed after magician would activate. - && !(gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerTarget)] & gBitTable[gBattlerPartyIndexes[gBattlerTarget]]) + && !(gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerTarget)] & (1u << gBattlerPartyIndexes[gBattlerTarget])) && !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove) && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && (GetBattlerAbility(gBattlerTarget) != ABILITY_STICKY_HOLD || !IsBattlerAlive(gBattlerTarget))) @@ -6075,9 +6076,9 @@ static void Cmd_moveend(void) u32 holdEffect; holdEffect = GetBattlerHoldEffect(i, TRUE); if (holdEffect == HOLD_EFFECT_EJECT_BUTTON) - ejectButtonBattlers |= gBitTable[i]; + ejectButtonBattlers |= 1u << i; else if (holdEffect == HOLD_EFFECT_EJECT_PACK) - ejectPackBattlers |= gBitTable[i]; + ejectPackBattlers |= 1u << i; } if (ejectButtonBattlers || ejectPackBattlers) { @@ -6088,7 +6089,7 @@ static void Cmd_moveend(void) { u32 battler = battlers[i]; - if (battler != gBattlerAttacker && ejectButtonBattlers & gBitTable[battler]) + if (battler != gBattlerAttacker && ejectButtonBattlers & (1u << battler)) { if (TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove)) // Apparently Sheer Force blocks Eject Button, but not Eject Pack continue; @@ -6097,7 +6098,7 @@ static void Cmd_moveend(void) if (!BATTLER_TURN_DAMAGED(battler)) continue; } - else if (ejectPackBattlers & gBitTable[battler]) + else if (ejectPackBattlers & (1u << battler)) { if (!gProtectStructs[battler].statFell || gProtectStructs[battler].disableEjectPack) continue; @@ -6119,7 +6120,7 @@ static void Cmd_moveend(void) gBattlescriptCurrInstr = BattleScript_MoveEnd; // Prevent user switch-in selection effect = TRUE; BattleScriptPushCursor(); - if (ejectButtonBattlers & gBitTable[battler]) + if (ejectButtonBattlers & (1u << battler)) { gBattlescriptCurrInstr = BattleScript_EjectButtonActivates; } @@ -6158,7 +6159,7 @@ static void Cmd_moveend(void) if (i == gBattlerAttacker) continue; if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_RED_CARD) - redCardBattlers |= gBitTable[i]; + redCardBattlers |= (1u << i); } if (redCardBattlers && (gMovesInfo[gCurrentMove].effect != EFFECT_HIT_SWITCH_TARGET || gBattleStruct->hitSwitchTargetFailed) @@ -6175,7 +6176,7 @@ static void Cmd_moveend(void) u32 battler = battlers[i]; // Search for fastest hit pokemon with a red card // Attacker is the one to be switched out, battler is one with red card - if (redCardBattlers & gBitTable[battler] + if (redCardBattlers & (1u << battler) && IsBattlerAlive(battler) && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && BATTLER_TURN_DAMAGED(battler) @@ -6206,7 +6207,7 @@ static void Cmd_moveend(void) case MOVEEND_PICKPOCKET: if (IsBattlerAlive(gBattlerAttacker) && gBattleMons[gBattlerAttacker].item != ITEM_NONE // Attacker must be holding an item - && !(gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerAttacker)] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]]) // But not knocked off + && !(gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerAttacker)] & (1u << gBattlerPartyIndexes[gBattlerAttacker])) // But not knocked off && !(TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove)) // Pickpocket doesn't activate for sheer force && IsMoveMakingContact(gCurrentMove, gBattlerAttacker) // Pickpocket requires contact && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) // Obviously attack needs to have worked @@ -6246,7 +6247,7 @@ static void Cmd_moveend(void) u32 battler, nextDancer = 0; bool32 turnOnHitmarker = FALSE; - for (battler = 0; battler < MAX_BATTLERS_COUNT; battler++) + for (battler = 0; battler < gBattlersCount; battler++) { if (gSpecialStatuses[battler].dancerUsedMove) { @@ -6256,9 +6257,8 @@ static void Cmd_moveend(void) } } - if (!(gBattleStruct->lastMoveFailed & gBitTable[gBattlerAttacker] - || (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove - && gBattleStruct->bouncedMoveIsUsed))) + if (!(gMoveResultFlags & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE) + || (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove && gBattleStruct->bouncedMoveIsUsed))) { // Dance move succeeds // Set target for other Dancer mons; set bit so that mon cannot activate Dancer off of its own move if (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove) @@ -6267,7 +6267,7 @@ static void Cmd_moveend(void) gBattleScripting.savedBattler |= (gBattlerAttacker << 4); gSpecialStatuses[gBattlerAttacker].dancerUsedMove = TRUE; } - for (battler = 0; battler < MAX_BATTLERS_COUNT; battler++) + for (battler = 0; battler < gBattlersCount; battler++) { if (GetBattlerAbility(battler) == ABILITY_DANCER && !gSpecialStatuses[battler].dancerUsedMove) { @@ -6391,6 +6391,7 @@ static void Cmd_moveend(void) gBattleStruct->enduredDamage = 0; gBattleStruct->additionalEffectsCounter = 0; gBattleStruct->poisonPuppeteerConfusion = FALSE; + gBattleStruct->fickleBeamBoosted = FALSE; if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE) SetActiveGimmick(gBattlerAttacker, GIMMICK_NONE); gBattleStruct->distortedTypeMatchups = 0; @@ -6450,7 +6451,7 @@ static void Cmd_getswitchedmondata(void) gBattlerPartyIndexes[battler] = gBattleStruct->monToSwitchIntoId[battler]; - BtlController_EmitGetMonData(battler, BUFFER_A, REQUEST_ALL_BATTLE, gBitTable[gBattlerPartyIndexes[battler]]); + BtlController_EmitGetMonData(battler, BUFFER_A, REQUEST_ALL_BATTLE, 1u << gBattlerPartyIndexes[battler]); MarkBattlerForControllerExec(battler); gBattlescriptCurrInstr = cmd->nextInstr; @@ -6496,7 +6497,7 @@ static void Cmd_switchindataupdate(void) if (i != PARTY_SIZE) { gBattlerPartyIndexes[battler] = gBattleStruct->monToSwitchIntoId[battler] = i; - BtlController_EmitGetMonData(battler, BUFFER_A, REQUEST_ALL_BATTLE, gBitTable[gBattlerPartyIndexes[battler]]); + BtlController_EmitGetMonData(battler, BUFFER_A, REQUEST_ALL_BATTLE, 1u << gBattlerPartyIndexes[battler]); MarkBattlerForControllerExec(battler); return; } @@ -6519,7 +6520,7 @@ static void Cmd_switchindataupdate(void) // check knocked off item i = GetBattlerSide(battler); - if (gWishFutureKnock.knockedOffMons[i] & gBitTable[gBattlerPartyIndexes[battler]]) + if (gWishFutureKnock.knockedOffMons[i] & (1u << gBattlerPartyIndexes[battler])) { gBattleMons[battler].item = ITEM_NONE; } @@ -6540,7 +6541,7 @@ static void Cmd_switchindataupdate(void) && IsBattlerAlive(battler) && !(gBattleMons[battler].status1 & STATUS1_SLEEP)) { - gBattleStruct->palaceFlags |= gBitTable[battler]; + gBattleStruct->palaceFlags |= 1u << battler; } gBattleScripting.battler = battler; @@ -6569,7 +6570,7 @@ static void Cmd_switchinanim(void) | BATTLE_TYPE_FRONTIER))) HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[battler].species), FLAG_SET_SEEN, gBattleMons[battler].personality); - gAbsentBattlerFlags &= ~(gBitTable[battler]); + gAbsentBattlerFlags &= ~(1u << battler); BtlController_EmitSwitchInAnim(battler, BUFFER_A, gBattlerPartyIndexes[battler], cmd->dontClearSubstitute); MarkBattlerForControllerExec(battler); @@ -6689,7 +6690,7 @@ bool32 CanBattlerSwitch(u32 battler) { battlerIn1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) battlerIn2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); else battlerIn2 = battlerIn1; @@ -6701,7 +6702,7 @@ bool32 CanBattlerSwitch(u32 battler) // Check if attacker side has mon to switch into battlerIn1 = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) battlerIn2 = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); else battlerIn2 = battlerIn1; @@ -6748,7 +6749,7 @@ static void ChooseMonToSendOut(u32 battler, u8 slotId) { gBattleStruct->battlerPartyIndexes[battler] = gBattlerPartyIndexes[battler]; gBattleStruct->monToSwitchIntoId[battler] = PARTY_SIZE; - gBattleStruct->field_93 &= ~(gBitTable[battler]); + gBattleStruct->field_93 &= ~(1u << battler); BtlController_EmitChoosePokemon(battler, BUFFER_A, PARTY_ACTION_SEND_OUT, slotId, ABILITY_NONE, gBattleStruct->battlerPartyOrders[battler]); MarkBattlerForControllerExec(battler); @@ -6765,7 +6766,7 @@ static void Cmd_openpartyscreen(void) if (cmd->battler == BS_FAINTED_MULTIPLE_1) { - if ((gBattleTypeFlags & BATTLE_TYPE_MULTI) || !(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + if ((gBattleTypeFlags & BATTLE_TYPE_MULTI) || !(IsDoubleBattle())) { for (battler = 0; battler < gBattlersCount; battler++) { @@ -6773,7 +6774,7 @@ static void Cmd_openpartyscreen(void) { if (HasNoMonsToSwitch(battler, PARTY_SIZE, PARTY_SIZE)) { - gAbsentBattlerFlags |= gBitTable[battler]; + gAbsentBattlerFlags |= 1u << battler; gHitMarker &= ~HITMARKER_FAINTED(battler); BtlController_EmitLinkStandbyMsg(battler, BUFFER_A, LINK_STANDBY_MSG_ONLY, FALSE); MarkBattlerForControllerExec(battler); @@ -6791,18 +6792,18 @@ static void Cmd_openpartyscreen(void) } } } - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + else if (IsDoubleBattle()) { bool8 hasReplacement_0, hasReplacement_1, hasReplacement_2, hasReplacement_3; hitmarkerFaintBits = gHitMarker >> 28; - if (gBitTable[0] & hitmarkerFaintBits) + if (1u & hitmarkerFaintBits) { battler = 0; if (HasNoMonsToSwitch(battler, PARTY_SIZE, PARTY_SIZE)) { - gAbsentBattlerFlags |= gBitTable[battler]; + gAbsentBattlerFlags |= 1u << battler; gHitMarker &= ~HITMARKER_FAINTED(battler); BtlController_EmitCantSwitch(battler, BUFFER_A); MarkBattlerForControllerExec(battler); @@ -6819,12 +6820,12 @@ static void Cmd_openpartyscreen(void) flags |= 1; } } - if (gBitTable[2] & hitmarkerFaintBits && !(gBitTable[0] & hitmarkerFaintBits)) + if (4u & hitmarkerFaintBits && !(1u & hitmarkerFaintBits)) { battler = 2; if (HasNoMonsToSwitch(battler, PARTY_SIZE, PARTY_SIZE)) { - gAbsentBattlerFlags |= gBitTable[battler]; + gAbsentBattlerFlags |= 1u << battler; gHitMarker &= ~HITMARKER_FAINTED(battler); BtlController_EmitCantSwitch(battler, BUFFER_A); MarkBattlerForControllerExec(battler); @@ -6840,12 +6841,12 @@ static void Cmd_openpartyscreen(void) MarkBattlerForControllerExec(battler); } } - if (gBitTable[1] & hitmarkerFaintBits) + if (2 & hitmarkerFaintBits) { battler = 1; if (HasNoMonsToSwitch(battler, PARTY_SIZE, PARTY_SIZE)) { - gAbsentBattlerFlags |= gBitTable[battler]; + gAbsentBattlerFlags |= 1u << battler; gHitMarker &= ~HITMARKER_FAINTED(battler); BtlController_EmitCantSwitch(battler, BUFFER_A); MarkBattlerForControllerExec(battler); @@ -6862,12 +6863,12 @@ static void Cmd_openpartyscreen(void) flags |= 2; } } - if (gBitTable[3] & hitmarkerFaintBits && !(gBitTable[1] & hitmarkerFaintBits)) + if (8 & hitmarkerFaintBits && !(2 & hitmarkerFaintBits)) { battler = 3; if (HasNoMonsToSwitch(battler, PARTY_SIZE, PARTY_SIZE)) { - gAbsentBattlerFlags |= gBitTable[battler]; + gAbsentBattlerFlags |= 1u << battler; gHitMarker &= ~HITMARKER_FAINTED(battler); BtlController_EmitCantSwitch(battler, BUFFER_A); MarkBattlerForControllerExec(battler); @@ -6890,7 +6891,7 @@ static void Cmd_openpartyscreen(void) hasReplacement_2 = gSpecialStatuses[2].faintedHasReplacement; if (!hasReplacement_2 && hitmarkerFaintBits != 0) { - if (gAbsentBattlerFlags & gBitTable[0]) + if (gAbsentBattlerFlags & 1) battler = 2; else battler = 0; @@ -6906,7 +6907,7 @@ static void Cmd_openpartyscreen(void) hasReplacement_3 = gSpecialStatuses[3].faintedHasReplacement; if (!hasReplacement_3 && hitmarkerFaintBits != 0) { - if (gAbsentBattlerFlags & gBitTable[1]) + if (gAbsentBattlerFlags & 2) battler = 3; else battler = 1; @@ -6922,15 +6923,15 @@ static void Cmd_openpartyscreen(void) { if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI)) { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { hitmarkerFaintBits = gHitMarker >> 28; - if (gBitTable[2] & hitmarkerFaintBits && gBitTable[0] & hitmarkerFaintBits) + if (4 & hitmarkerFaintBits && 1 & hitmarkerFaintBits) { battler = 2; if (HasNoMonsToSwitch(battler, gBattleResources->bufferB[0][1], PARTY_SIZE)) { - gAbsentBattlerFlags |= gBitTable[battler]; + gAbsentBattlerFlags |= 1u << battler; gHitMarker &= ~HITMARKER_FAINTED(battler); BtlController_EmitCantSwitch(battler, BUFFER_A); MarkBattlerForControllerExec(battler); @@ -6941,12 +6942,12 @@ static void Cmd_openpartyscreen(void) gSpecialStatuses[battler].faintedHasReplacement = TRUE; } } - if (gBitTable[3] & hitmarkerFaintBits && hitmarkerFaintBits & gBitTable[1]) + if (8u & hitmarkerFaintBits && hitmarkerFaintBits & 2u) { battler = 3; if (HasNoMonsToSwitch(battler, gBattleResources->bufferB[1][1], PARTY_SIZE)) { - gAbsentBattlerFlags |= gBitTable[battler]; + gAbsentBattlerFlags |= 1u << battler; gHitMarker &= ~HITMARKER_FAINTED(battler); BtlController_EmitCantSwitch(battler, BUFFER_A); MarkBattlerForControllerExec(battler); @@ -6974,7 +6975,7 @@ static void Cmd_openpartyscreen(void) hitmarkerFaintBits = gHitMarker >> 28; gBattlerFainted = 0; - while (!(gBitTable[gBattlerFainted] & hitmarkerFaintBits) + while (!((1u << gBattlerFainted) & hitmarkerFaintBits) && gBattlerFainted < gBattlersCount) gBattlerFainted++; @@ -6995,7 +6996,7 @@ static void Cmd_openpartyscreen(void) } else if (HasNoMonsToSwitch(battler, PARTY_SIZE, PARTY_SIZE)) { - gAbsentBattlerFlags |= gBitTable[battler]; + gAbsentBattlerFlags |= 1u << battler; gHitMarker &= ~HITMARKER_FAINTED(battler); gBattlescriptCurrInstr = failInstr; } @@ -7003,7 +7004,7 @@ static void Cmd_openpartyscreen(void) { *(gBattleStruct->battlerPartyIndexes + battler) = gBattlerPartyIndexes[battler]; *(gBattleStruct->monToSwitchIntoId + battler) = PARTY_SIZE; - gBattleStruct->field_93 &= ~(gBitTable[battler]); + gBattleStruct->field_93 &= ~(1u << battler); BtlController_EmitChoosePokemon(battler, BUFFER_A, hitmarkerFaintBits, *(gBattleStruct->monToSwitchIntoId + BATTLE_PARTNER(battler)), ABILITY_NONE, gBattleStruct->battlerPartyOrders[battler]); MarkBattlerForControllerExec(battler); @@ -7027,7 +7028,7 @@ static void Cmd_openpartyscreen(void) else { u32 battlerOpposite = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler))); - if (gAbsentBattlerFlags & gBitTable[battlerOpposite]) + if (gAbsentBattlerFlags & (1u << battlerOpposite)) battlerOpposite ^= BIT_FLANK; // Make sure we're checking a valid battler. In edge case scenarios - battler could be absent and battlerOpposite would become a non-existent one softlocking the game. @@ -7059,10 +7060,10 @@ static void Cmd_switchhandleorder(void) if (gBattleResources->bufferB[i][0] == CONTROLLER_CHOSENMONRETURNVALUE) { *(gBattleStruct->monToSwitchIntoId + i) = gBattleResources->bufferB[i][1]; - if (!(gBattleStruct->field_93 & gBitTable[i])) + if (!(gBattleStruct->field_93 & (1u << i))) { RecordedBattle_SetBattlerAction(i, gBattleResources->bufferB[i][1]); - gBattleStruct->field_93 |= gBitTable[i]; + gBattleStruct->field_93 |= 1u << i; } } } @@ -7072,10 +7073,10 @@ static void Cmd_switchhandleorder(void) SwitchPartyOrder(battler); break; case 2: - if (!(gBattleStruct->field_93 & gBitTable[battler])) + if (!(gBattleStruct->field_93 & (1u << battler))) { RecordedBattle_SetBattlerAction(battler, gBattleResources->bufferB[battler][1]); - gBattleStruct->field_93 |= gBitTable[battler]; + gBattleStruct->field_93 |= 1u << battler; } // fall through case 3: @@ -7143,7 +7144,7 @@ static void UpdateSentMonFlags(u32 battler) gSpecialStatuses[battler].faintedHasReplacement = FALSE; if (!BattlerHasAi(battler)) - gBattleStruct->appearedInBattle |= gBitTable[gBattlerPartyIndexes[battler]]; + gBattleStruct->appearedInBattle |= 1u << gBattlerPartyIndexes[battler]; } static bool32 DoSwitchInEffectsForBattler(u32 battler) @@ -7160,20 +7161,20 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) } // Healing Wish activates before hazards. // Starting from Gen8 - it heals only pokemon which can be healed. In gens 5,6,7 the effect activates anyways. - else if (((gBattleStruct->storedHealingWish & gBitTable[battler]) || (gBattleStruct->storedLunarDance & gBitTable[battler])) + else if (((gBattleStruct->storedHealingWish & (1u << battler)) || (gBattleStruct->storedLunarDance & (1u << battler))) && (gBattleMons[battler].hp != gBattleMons[battler].maxHP || gBattleMons[battler].status1 != 0 || B_HEALING_WISH_SWITCH < GEN_8)) { - if (gBattleStruct->storedHealingWish & gBitTable[battler]) + if (gBattleStruct->storedHealingWish & (1u << battler)) { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_HealingWishActivates; - gBattleStruct->storedHealingWish &= ~(gBitTable[battler]); + gBattleStruct->storedHealingWish &= ~(1u << battler); } else // Lunar Dance { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_LunarDanceActivates; - gBattleStruct->storedLunarDance &= ~(gBitTable[battler]); + gBattleStruct->storedLunarDance &= ~(1u << battler); } } else if (!(gDisableStructs[battler].spikesDone) @@ -7280,19 +7281,32 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) gDisableStructs[battler].truantSwitchInHack = 0; - for (i = 0; i < gBattlersCount; i++) - { - if (i != battler - && GetBattlerAbility(i) == ABILITY_TRACE - && AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, i, 0, 0, 0)) - return TRUE; - } - if (DoSwitchInAbilities(battler) || ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, battler, FALSE)) return TRUE; else if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0)) return TRUE; + for (i = 0; i < gBattlersCount; i++) + { + if (i == battler) + continue; + + switch (GetBattlerAbility(i)) + { + case ABILITY_TRACE: + if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, i, 0, 0, 0)) + return TRUE; + break; + case ABILITY_FORECAST: + case ABILITY_FLOWER_GIFT: + case ABILITY_ICE_FACE: + case ABILITY_PROTOSYNTHESIS: + if (AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, i, 0, 0, 0)) + return TRUE; + break; + } + } + gDisableStructs[battler].stickyWebDone = FALSE; gDisableStructs[battler].spikesDone = FALSE; gDisableStructs[battler].toxicSpikesDone = FALSE; @@ -7307,7 +7321,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) gBattleStruct->hpOnSwitchout[GetBattlerSide(i)] = gBattleMons[i].hp; } - gBattleStruct->forcedSwitch &= ~(gBitTable[battler]); + gBattleStruct->forcedSwitch &= ~(1u << battler); return FALSE; } @@ -7323,7 +7337,7 @@ static void Cmd_switchineffects(void) { // Multiple mons fainted and are being switched-in. Their abilities/hazards will play according to speed ties. case BS_FAINTED_MULTIPLE_1: // Saves the battlers. - gBattleStruct->multipleSwitchInBattlers |= gBitTable[battler]; + gBattleStruct->multipleSwitchInBattlers |= 1 << battler; UpdateSentMonFlags(battler); // Increment fainted battler. @@ -7332,7 +7346,7 @@ static void Cmd_switchineffects(void) gBattlerFainted++; if (gBattlerFainted >= gBattlersCount) break; - if (gHitMarker & HITMARKER_FAINTED(gBattlerFainted) && !(gAbsentBattlerFlags & gBitTable[gBattlerFainted])) + if (gHitMarker & HITMARKER_FAINTED(gBattlerFainted) && !(gAbsentBattlerFlags & (1u << gBattlerFainted))) break; } while (1); @@ -7352,7 +7366,7 @@ static void Cmd_switchineffects(void) for (; gBattleStruct->multipleSwitchInCursor < gBattlersCount; gBattleStruct->multipleSwitchInCursor++) { gBattlerFainted = gBattleStruct->multipleSwitchInSortedBattlers[gBattleStruct->multipleSwitchInCursor]; - if (gBattleStruct->multipleSwitchInBattlers & gBitTable[gBattlerFainted]) + if (gBattleStruct->multipleSwitchInBattlers & (1 << (gBattlerFainted))) { if (DoSwitchInEffectsForBattler(gBattlerFainted)) return; @@ -7466,7 +7480,7 @@ static void Cmd_handlelearnnewmove(void) { GiveMoveToBattleMon(&gBattleMons[battler], learnMove); } - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { battler = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); if (gBattlerPartyIndexes[battler] == monId @@ -7572,7 +7586,7 @@ static void Cmd_yesnoboxlearnmove(void) RemoveBattleMonPPBonus(&gBattleMons[0], movePosition); SetBattleMonMoveSlot(&gBattleMons[0], gMoveToLearn, movePosition); } - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE + if (IsDoubleBattle() && gBattlerPartyIndexes[2] == gBattleStruct->expGetterMonId && MOVE_IS_PERMANENT(2, movePosition)) { @@ -7686,7 +7700,7 @@ static u32 GetTrainerMoneyToGive(u16 trainerId) if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) moneyReward = 4 * lastMonLevel * gBattleStruct->moneyMultiplier * trainerMoney; - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + else if (IsDoubleBattle()) moneyReward = 4 * lastMonLevel * gBattleStruct->moneyMultiplier * 2 * trainerMoney; else moneyReward = 4 * lastMonLevel * gBattleStruct->moneyMultiplier * trainerMoney; @@ -7981,7 +7995,7 @@ static bool32 TryCheekPouch(u32 battler, u32 itemId) if (ItemId_GetPocket(itemId) == POCKET_BERRIES && GetBattlerAbility(battler) == ABILITY_CHEEK_POUCH && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK) - && gBattleStruct->ateBerry[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]] + && gBattleStruct->ateBerry[GetBattlerSide(battler)] & (1u << gBattlerPartyIndexes[battler]) && !BATTLER_MAX_HP(battler)) { gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 3; @@ -8059,6 +8073,7 @@ static void Cmd_removeitem(void) gBattleStruct->usedHeldItems[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)] = itemId; // Remember if switched out gBattleMons[battler].item = ITEM_NONE; + gBattleStruct->canPickupItem |= (1u << battler); CheckSetUnburden(battler); BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[battler].item), &gBattleMons[battler].item); @@ -8352,7 +8367,7 @@ static bool32 IsMonGettingExpSentOut(void) { if (gBattlerPartyIndexes[0] == gBattleStruct->expGetterMonId) return TRUE; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && gBattlerPartyIndexes[2] == gBattleStruct->expGetterMonId) + if (IsDoubleBattle() && gBattlerPartyIndexes[2] == gBattleStruct->expGetterMonId) return TRUE; return FALSE; @@ -8425,7 +8440,7 @@ static void Cmd_hpthresholds(void) { CMD_ARGS(u8 battler); - if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + if (!(IsDoubleBattle())) { u32 battler = GetBattlerForBattleScript(cmd->battler); u32 opposingBattler = BATTLE_OPPOSITE(battler); @@ -8451,7 +8466,7 @@ static void Cmd_hpthresholds2(void) { CMD_ARGS(u8 battler); - if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + if (!(IsDoubleBattle())) { u32 battler = GetBattlerForBattleScript(cmd->battler); u32 opposingBattler = BATTLE_OPPOSITE(battler); @@ -8514,7 +8529,7 @@ bool32 CanUseLastResort(u8 battler) { if (gBattleMons[battler].moves[i] != MOVE_NONE) knownMovesCount++; - if (i != gCurrMovePos && gDisableStructs[battler].usedMoves & gBitTable[i]) // Increment used move count for all moves except current Last Resort. + if (i != gCurrMovePos && gDisableStructs[battler].usedMoves & (1u << i)) // Increment used move count for all moves except current Last Resort. usedMovesCount++; } @@ -8605,11 +8620,14 @@ static bool32 TryDefogClear(u32 battlerAtk, bool32 clear) DEFOG_CLEAR(SIDE_STATUS_AURORA_VEIL, auroraVeilTimer, BattleScript_SideStatusWoreOffReturn, MOVE_AURORA_VEIL); DEFOG_CLEAR(SIDE_STATUS_SAFEGUARD, safeguardTimer, BattleScript_SideStatusWoreOffReturn, MOVE_SAFEGUARD); } - DEFOG_CLEAR(SIDE_STATUS_SPIKES, spikesAmount, BattleScript_SpikesDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_STEALTH_ROCK, stealthRockAmount, BattleScript_StealthRockDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_TOXIC_SPIKES, toxicSpikesAmount, BattleScript_ToxicSpikesDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_STICKY_WEB, stickyWebAmount, BattleScript_StickyWebDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_STEELSURGE, steelsurgeAmount, BattleScript_SteelsurgeDefog, 0); + if (B_DEFOG_EFFECT_CLEARING >= GEN_6) + { + DEFOG_CLEAR(SIDE_STATUS_SPIKES, spikesAmount, BattleScript_SpikesDefog, 0); + DEFOG_CLEAR(SIDE_STATUS_STEALTH_ROCK, stealthRockAmount, BattleScript_StealthRockDefog, 0); + DEFOG_CLEAR(SIDE_STATUS_TOXIC_SPIKES, toxicSpikesAmount, BattleScript_ToxicSpikesDefog, 0); + DEFOG_CLEAR(SIDE_STATUS_STICKY_WEB, stickyWebAmount, BattleScript_StickyWebDefog, 0); + DEFOG_CLEAR(SIDE_STATUS_STEELSURGE, steelsurgeAmount, BattleScript_SteelsurgeDefog, 0); + } if (gBattleWeather & B_WEATHER_FOG) { gBattleWeather &= ~B_WEATHER_FOG; @@ -8617,7 +8635,7 @@ static bool32 TryDefogClear(u32 battlerAtk, bool32 clear) gBattlescriptCurrInstr = BattleScript_FogEnded_Ret; return TRUE; } - if (B_DEFOG_CLEARS_TERRAIN >= GEN_8 && (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) + if (B_DEFOG_EFFECT_CLEARING >= GEN_8 && (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) { RemoveAllTerrains(); BattleScriptPushCursor(); @@ -8843,7 +8861,7 @@ static void HandleScriptMegaPrimalBurst(u32 caseId, u32 battler, u32 type) PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[battler].species); - BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_SPECIES_BATTLE, gBitTable[gBattlerPartyIndexes[battler]], sizeof(gBattleMons[battler].species), &gBattleMons[battler].species); + BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_SPECIES_BATTLE, 1u << gBattlerPartyIndexes[battler], sizeof(gBattleMons[battler].species), &gBattleMons[battler].species); MarkBattlerForControllerExec(battler); } // Update healthbox and elevation and play cry. @@ -9161,9 +9179,9 @@ static void Cmd_various(void) // Raise stats for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) { - if (gBattleStruct->stolenStats[0] & gBitTable[i]) + if (gBattleStruct->stolenStats[0] & (1u << i)) { - gBattleStruct->stolenStats[0] &= ~(gBitTable[i]); + gBattleStruct->stolenStats[0] &= ~(1u << i); SET_STATCHANGER(i, gBattleStruct->stolenStats[i], FALSE); if (ChangeStatBuffs(GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger), i, MOVE_EFFECT_CERTAIN | MOVE_EFFECT_AFFECTS_USER, NULL) == STAT_CHANGE_WORKED) { @@ -9188,7 +9206,7 @@ static void Cmd_various(void) for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) { if (CompareStat(battler, i, MAX_STAT_STAGE, CMP_LESS_THAN)) - bits |= gBitTable[i]; + bits |= 1u << i; } if (bits) { @@ -9196,7 +9214,7 @@ static void Cmd_various(void) do { statId = (Random() % (NUM_BATTLE_STATS - 1)) + 1; - } while (!(bits & gBitTable[statId])); + } while (!(bits & (1u << statId))); SET_STATCHANGER(statId, 2, FALSE); gBattlescriptCurrInstr = cmd->nextInstr; @@ -9296,12 +9314,12 @@ static void Cmd_various(void) // Try and print end-of-turn Battle Palace flavor text (e.g. "A glint appears in mon's eyes") gBattleCommunication[0] = FALSE; // whether or not msg should be printed gBattleScripting.battler = battler = gBattleCommunication[1]; - if (!(gBattleStruct->palaceFlags & gBitTable[battler]) + if (!(gBattleStruct->palaceFlags & (1u << battler)) && gBattleMons[battler].maxHP / 2 >= gBattleMons[battler].hp && IsBattlerAlive(battler) && !(gBattleMons[battler].status1 & STATUS1_SLEEP)) { - gBattleStruct->palaceFlags |= gBitTable[battler]; + gBattleStruct->palaceFlags |= 1u << battler; gBattleCommunication[0] = TRUE; gBattleCommunication[MULTISTRING_CHOOSER] = gNaturesInfo[GetNatureFromPersonality(gBattleMons[battler].personality)].battlePalaceFlavorText; } @@ -9326,7 +9344,7 @@ static void Cmd_various(void) VARIOUS_ARGS(); gBattleMons[1].hp = 0; gHitMarker |= HITMARKER_FAINTED(1); - gBattleStruct->arenaLostOpponentMons |= gBitTable[gBattlerPartyIndexes[1]]; + gBattleStruct->arenaLostOpponentMons |= 1u << gBattlerPartyIndexes[1]; gDisableStructs[1].truantSwitchInHack = 1; break; } @@ -9336,7 +9354,7 @@ static void Cmd_various(void) gBattleMons[0].hp = 0; gHitMarker |= HITMARKER_FAINTED(0); gHitMarker |= HITMARKER_PLAYER_FAINTED; - gBattleStruct->arenaLostPlayerMons |= gBitTable[gBattlerPartyIndexes[0]]; + gBattleStruct->arenaLostPlayerMons |= 1u << gBattlerPartyIndexes[0]; gDisableStructs[0].truantSwitchInHack = 1; break; } @@ -9348,8 +9366,8 @@ static void Cmd_various(void) gHitMarker |= HITMARKER_FAINTED(0); gHitMarker |= HITMARKER_FAINTED(1); gHitMarker |= HITMARKER_PLAYER_FAINTED; - gBattleStruct->arenaLostPlayerMons |= gBitTable[gBattlerPartyIndexes[0]]; - gBattleStruct->arenaLostOpponentMons |= gBitTable[gBattlerPartyIndexes[1]]; + gBattleStruct->arenaLostPlayerMons |= 1u << gBattlerPartyIndexes[0]; + gBattleStruct->arenaLostOpponentMons |= 1u << gBattlerPartyIndexes[1]; gDisableStructs[0].truantSwitchInHack = 1; gDisableStructs[1].truantSwitchInHack = 1; break; @@ -9434,7 +9452,7 @@ static void Cmd_various(void) case VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT: { VARIOUS_ARGS(); - gBattleStruct->alreadyStatusedMoveAttempt |= gBitTable[battler]; + gBattleStruct->alreadyStatusedMoveAttempt |= 1u << battler; break; } case VARIOUS_PALACE_TRY_ESCAPE_STATUS: @@ -9451,7 +9469,7 @@ static void Cmd_various(void) // and its partner is still alive. if (GetBattlerSide(battler) == B_SIDE_OPPONENT && IsBattlerAlive(BATTLE_PARTNER(battler))) { - gAbsentBattlerFlags |= gBitTable[battler]; + gAbsentBattlerFlags |= 1u << battler; gHitMarker |= HITMARKER_FAINTED(battler); gBattleMons[battler].hp = 0; SetMonData(&gEnemyParty[gBattlerPartyIndexes[battler]], MON_DATA_HP, &gBattleMons[battler].hp); @@ -9826,7 +9844,7 @@ static void Cmd_various(void) if (!gBattleTextBuff1) PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[battler].species); */ - BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_SPECIES_BATTLE, gBitTable[gBattlerPartyIndexes[battler]], sizeof(gBattleMons[battler].species), &gBattleMons[battler].species); + BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_SPECIES_BATTLE, 1u << gBattlerPartyIndexes[battler], sizeof(gBattleMons[battler].species), &gBattleMons[battler].species); MarkBattlerForControllerExec(battler); } // Change stats. @@ -9931,7 +9949,7 @@ static void Cmd_various(void) case VARIOUS_ABILITY_POPUP: { VARIOUS_ARGS(); - CreateAbilityPopUp(battler, gBattleMons[battler].ability, (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) != 0); + CreateAbilityPopUp(battler, gBattleMons[battler].ability, (IsDoubleBattle()) != 0); break; } case VARIOUS_UPDATE_ABILITY_POPUP: @@ -10030,7 +10048,7 @@ static void Cmd_various(void) || gBattleMons[gBattlerTarget].item != ITEM_NONE || !CanBattlerGetOrLoseItem(gBattlerAttacker, gBattleMons[gBattlerAttacker].item) || !CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerAttacker].item) - || gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerTarget)] & gBitTable[gBattlerPartyIndexes[gBattlerTarget]]) + || gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerTarget)] & (1u << gBattlerPartyIndexes[gBattlerTarget])) { gBattlescriptCurrInstr = cmd->failInstr; } @@ -10125,7 +10143,7 @@ static void Cmd_various(void) gSideTimers[GetBattlerSide(battler)].auroraVeilTimer = 5; gSideTimers[GetBattlerSide(battler)].auroraVeilBattlerId = battler; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerAttacker) == 2) + if (IsDoubleBattle() && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerAttacker) == 2) gBattleCommunication[MULTISTRING_CHOOSER] = 5; else gBattleCommunication[MULTISTRING_CHOOSER] = 5; @@ -10275,7 +10293,7 @@ static void Cmd_various(void) ConvertIntToDecimalStringN(gBattleTextBuff2, ppToDeduct, STR_CONV_MODE_LEFT_ALIGN, 1); PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff2, 1, ppToDeduct) gBattleMons[battler].pp[i] -= ppToDeduct; - if (!(gDisableStructs[battler].mimickedMoves & gBitTable[i]) + if (!(gDisableStructs[battler].mimickedMoves & (1u << i)) && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) { BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_PPMOVE1_BATTLE + i, 0, sizeof(gBattleMons[battler].pp[i]), &gBattleMons[battler].pp[i]); @@ -10301,7 +10319,7 @@ static void Cmd_various(void) case VARIOUS_JUMP_IF_TEAM_HEALTHY: { VARIOUS_ARGS(const u8 *jumpInstr); - if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && IsBattlerAlive(BATTLE_PARTNER(battler))) + if ((IsDoubleBattle()) && IsBattlerAlive(BATTLE_PARTNER(battler))) { u8 partner = BATTLE_PARTNER(battler); if ((gBattleMons[battler].hp == gBattleMons[battler].maxHP && !(gBattleMons[battler].status1 & STATUS1_ANY)) @@ -10514,9 +10532,9 @@ static void Cmd_various(void) if (gBattleMons[gBattlerAttacker].species == SPECIES_GRENINJA_BATTLE_BOND && HasAttackerFaintedTarget() && CalculateBattlerPartyCount(gBattlerTarget) > 1 - && !(gBattleStruct->battleBondTransformed[GetBattlerSide(gBattlerAttacker)] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]])) + && !(gBattleStruct->battleBondTransformed[GetBattlerSide(gBattlerAttacker)] & (1u << gBattlerPartyIndexes[gBattlerAttacker]))) { - gBattleStruct->battleBondTransformed[GetBattlerSide(gBattlerAttacker)] |= gBitTable[gBattlerPartyIndexes[gBattlerAttacker]]; + gBattleStruct->battleBondTransformed[GetBattlerSide(gBattlerAttacker)] |= 1u << gBattlerPartyIndexes[gBattlerAttacker]; PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerAttacker].species); gBattleStruct->changedSpecies[GetBattlerSide(gBattlerAttacker)][gBattlerPartyIndexes[gBattlerAttacker]] = gBattleMons[gBattlerAttacker].species; gBattleMons[gBattlerAttacker].species = SPECIES_GRENINJA_ASH; @@ -10538,7 +10556,7 @@ static void Cmd_various(void) if (cmd->fromBattler) gLastUsedItem = gBattleMons[battler].item; - gBattleStruct->ateBerry[battler & BIT_SIDE] |= gBitTable[gBattlerPartyIndexes[battler]]; + gBattleStruct->ateBerry[battler & BIT_SIDE] |= 1u << gBattlerPartyIndexes[battler]; gBattleScripting.battler = gEffectBattler = gBattlerTarget = battler; // Cover all berry effect battler cases. e.g. ChangeStatBuffs uses target ID if (ItemBattleEffects(ITEMEFFECT_USE_LAST_ITEM, battler, FALSE)) return; @@ -10878,9 +10896,9 @@ static void Cmd_various(void) { VARIOUS_ARGS(); if (gCurrentMove == MOVE_LUNAR_DANCE) - gBattleStruct->storedLunarDance |= gBitTable[battler]; + gBattleStruct->storedLunarDance |= 1u << battler; else - gBattleStruct->storedHealingWish |= gBitTable[battler]; + gBattleStruct->storedHealingWish |= 1u << battler; break; } case VARIOUS_HIT_SWITCH_TARGET_FAILED: @@ -10909,12 +10927,12 @@ static void Cmd_various(void) struct Pokemon *party = GetSideParty(side); u16 hp = GetMonData(&party[gSelectedMonPartyId], MON_DATA_MAX_HP) / 2; - BtlController_EmitSetMonData(gBattlerAttacker, BUFFER_A, REQUEST_HP_BATTLE, gBitTable[gSelectedMonPartyId], sizeof(hp), &hp); + BtlController_EmitSetMonData(gBattlerAttacker, BUFFER_A, REQUEST_HP_BATTLE, 1u << gSelectedMonPartyId, sizeof(hp), &hp); MarkBattlerForControllerExec(gBattlerAttacker); PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gSelectedMonPartyId], MON_DATA_SPECIES)); // If an on-field battler is revived, it needs to be sent out again. - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && + if (IsDoubleBattle() && gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)] == gSelectedMonPartyId) { gBattleScripting.battler = BATTLE_PARTNER(gBattlerAttacker); @@ -11233,7 +11251,7 @@ static void Cmd_setreflect(void) gSideTimers[GetBattlerSide(gBattlerAttacker)].reflectTimer = 5; gSideTimers[GetBattlerSide(gBattlerAttacker)].reflectBattlerId = gBattlerAttacker; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerAttacker) == 2) + if (IsDoubleBattle() && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerAttacker) == 2) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_REFLECT_DOUBLE; else gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_REFLECT_SINGLE; @@ -12097,7 +12115,7 @@ static void Cmd_forcerandomswitch(void) battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + else if (IsDoubleBattle()) { firstMonId = 0; lastMonId = PARTY_SIZE; @@ -12132,7 +12150,7 @@ static void Cmd_forcerandomswitch(void) { *(gBattleStruct->battlerPartyIndexes + gBattlerTarget) = gBattlerPartyIndexes[gBattlerTarget]; gBattlescriptCurrInstr = BattleScript_RoarSuccessSwitch; - gBattleStruct->forcedSwitch |= gBitTable[gBattlerTarget]; + gBattleStruct->forcedSwitch |= 1u << gBattlerTarget; *(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = validMons[RandomUniform(RNG_FORCE_RANDOM_SWITCH, 0, validMonsCount - 1)]; if (!IsMultiBattle()) @@ -12295,7 +12313,7 @@ static void Cmd_setlightscreen(void) gSideTimers[GetBattlerSide(gBattlerAttacker)].lightscreenTimer = 5; gSideTimers[GetBattlerSide(gBattlerAttacker)].lightscreenBattlerId = gBattlerAttacker; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerAttacker) == 2) + if (IsDoubleBattle() && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerAttacker) == 2) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_LIGHTSCREEN_DOUBLE; else gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_LIGHTSCREEN_SINGLE; @@ -12460,15 +12478,15 @@ static void Cmd_updatestatusicon(void) else { battler = gBattlerAttacker; - if (!(gAbsentBattlerFlags & gBitTable[battler])) + if (!(gAbsentBattlerFlags & (1u << battler))) { BtlController_EmitStatusIconUpdate(battler, BUFFER_A, gBattleMons[battler].status1, gBattleMons[battler].status2); MarkBattlerForControllerExec(battler); } - if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + if ((IsDoubleBattle())) { battler = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker))); - if (!(gAbsentBattlerFlags & gBitTable[battler])) + if (!(gAbsentBattlerFlags & (1u << battler))) { BtlController_EmitStatusIconUpdate(battler, BUFFER_A, gBattleMons[battler].status1, gBattleMons[battler].status2); MarkBattlerForControllerExec(battler); @@ -12502,8 +12520,8 @@ static void Cmd_setfocusenergy(void) CMD_ARGS(u8 battler); u8 battler = GetBattlerForBattleScript(cmd->battler); - if ((gMovesInfo[gCurrentMove].effect == EFFECT_DRAGON_CHEER && (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || (gAbsentBattlerFlags & gBitTable[battler]))) - || gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY) + if ((gMovesInfo[gCurrentMove].effect == EFFECT_DRAGON_CHEER && (!(IsDoubleBattle()) || (gAbsentBattlerFlags & (1u << battler)))) + || gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY) { gMoveResultFlags |= MOVE_RESULT_FAILED; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FOCUS_ENERGY_FAILED; @@ -12646,7 +12664,7 @@ static void Cmd_mimicattackcopy(void) PREPARE_MOVE_BUFFER(gBattleTextBuff1, gLastMoves[gBattlerTarget]) - gDisableStructs[gBattlerAttacker].mimickedMoves |= gBitTable[gCurrMovePos]; + gDisableStructs[gBattlerAttacker].mimickedMoves |= 1u << gCurrMovePos; gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -12887,7 +12905,7 @@ static void Cmd_settypetorandomresistance(void) { gBattlescriptCurrInstr = cmd->failInstr; } - else if (gLastHitByType[gBattlerAttacker] == TYPE_STELLAR) + else if (gLastHitByType[gBattlerAttacker] == TYPE_STELLAR || gLastHitByType[gBattlerAttacker] == TYPE_MYSTERY) { gBattlescriptCurrInstr = cmd->failInstr; } @@ -12902,7 +12920,7 @@ static void Cmd_settypetorandomresistance(void) { case UQ_4_12(0): case UQ_4_12(0.5): - resistTypes |= gBitTable[i]; + resistTypes |= 1u << i; break; } } @@ -12910,11 +12928,11 @@ static void Cmd_settypetorandomresistance(void) while (resistTypes != 0) { i = Random() % NUMBER_OF_MON_TYPES; - if (resistTypes & gBitTable[i]) + if (resistTypes & (1u << i)) { if (IS_BATTLER_OF_TYPE(gBattlerAttacker, i)) { - resistTypes &= ~(gBitTable[i]); // Type resists, but the user is already of this type. + resistTypes &= ~(1u << i); // Type resists, but the user is already of this type. } else { @@ -13004,7 +13022,7 @@ static void Cmd_trychoosesleeptalkmove(void) if (gMovesInfo[gBattleMons[gBattlerAttacker].moves[i]].sleepTalkBanned || gBattleMoveEffects[gMovesInfo[gBattleMons[gBattlerAttacker].moves[i]].effect].twoTurnEffect) { - unusableMovesBits |= gBitTable[i]; + unusableMovesBits |= (1 << (i)); } } @@ -13016,11 +13034,11 @@ static void Cmd_trychoosesleeptalkmove(void) else // at least one move can be chosen { // Set Sleep Talk as used move, so it works with Last Resort. - gDisableStructs[gBattlerAttacker].usedMoves |= gBitTable[gCurrMovePos]; + gDisableStructs[gBattlerAttacker].usedMoves |= 1u << gCurrMovePos; do { movePosition = MOD(Random(), MAX_MON_MOVES); - } while ((gBitTable[movePosition] & unusableMovesBits)); + } while ((1u << movePosition) & unusableMovesBits); if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IS_MOVE_STATUS(gBattleMons[gBattlerAttacker].moves[movePosition])) { @@ -13131,7 +13149,7 @@ static void Cmd_tryspiteppreduce(void) gBattleMons[gBattlerTarget].pp[i] -= ppToDeduct; // if (MOVE_IS_PERMANENT(gBattlerTarget, i)), but backwards - if (!(gDisableStructs[gBattlerTarget].mimickedMoves & gBitTable[i]) + if (!(gDisableStructs[gBattlerTarget].mimickedMoves & (1u << i)) && !(gBattleMons[gBattlerTarget].status2 & STATUS2_TRANSFORMED)) { BtlController_EmitSetMonData(gBattlerTarget, BUFFER_A, REQUEST_PPMOVE1_BATTLE + i, 0, sizeof(gBattleMons[gBattlerTarget].pp[i]), &gBattleMons[gBattlerTarget].pp[i]); @@ -13245,8 +13263,8 @@ static void Cmd_healpartystatus(void) gBattleMons[gBattlerAttacker].status1 = 0; gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE - && !(gAbsentBattlerFlags & gBitTable[partner])) + if (IsDoubleBattle() + && !(gAbsentBattlerFlags & (1u <failInstr; } @@ -14615,7 +14633,7 @@ static void Cmd_switchoutabilities(void) case ABILITY_NATURAL_CURE: gBattleMons[battler].status1 = 0; BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, - gBitTable[*(gBattleStruct->battlerPartyIndexes + battler)], + 1u << *(gBattleStruct->battlerPartyIndexes + battler), sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); @@ -14626,7 +14644,7 @@ static void Cmd_switchoutabilities(void) if (gBattleMoveDamage > gBattleMons[battler].maxHP) gBattleMoveDamage = gBattleMons[battler].maxHP; BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_HP_BATTLE, - gBitTable[*(gBattleStruct->battlerPartyIndexes + battler)], + 1u << *(gBattleStruct->battlerPartyIndexes + battler), sizeof(gBattleMoveDamage), &gBattleMoveDamage); MarkBattlerForControllerExec(battler); @@ -14841,7 +14859,10 @@ static void Cmd_tryrecycleitem(void) u16 *usedHeldItem; - usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerAttacker]][GetBattlerSide(gBattlerAttacker)]; + if (gCurrentMove == MOVE_NONE && GetBattlerAbility(gBattlerAttacker) == ABILITY_PICKUP) + usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerTarget]][GetBattlerSide(gBattlerTarget)]; + else + usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerAttacker]][GetBattlerSide(gBattlerAttacker)]; if (*usedHeldItem != ITEM_NONE && gBattleMons[gBattlerAttacker].item == ITEM_NONE) { gLastUsedItem = *usedHeldItem; @@ -14910,8 +14931,8 @@ static void Cmd_pursuitdoubles(void) u32 battler = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker))); - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE - && !(gAbsentBattlerFlags & gBitTable[battler]) + if (IsDoubleBattle() + && !(gAbsentBattlerFlags & (1u << battler)) && gChosenActionByBattler[battler] == B_ACTION_USE_MOVE && gMovesInfo[gChosenMoveByBattler[battler]].effect == EFFECT_PURSUIT) { @@ -15653,17 +15674,26 @@ static void Cmd_swapstatstages(void) gBattlescriptCurrInstr = cmd->nextInstr; } +static u16 *GetBattlerStat(struct BattlePokemon *battler, u32 stat) +{ + switch (stat) + { + case STAT_ATK: return &battler->attack; + case STAT_DEF: return &battler->defense; + case STAT_SPATK: return &battler->spAttack; + case STAT_SPDEF: return &battler->spDefense; + default: return NULL; + } +} + static void Cmd_averagestats(void) { CMD_ARGS(u8 stat); - u8 stat = cmd->stat; - u16 atkStat = *(u16 *)((&gBattleMons[gBattlerAttacker].attack) + (stat - 1)); - u16 defStat = *(u16 *)((&gBattleMons[gBattlerTarget].attack) + (stat - 1)); - u16 average = (atkStat + defStat) / 2; - - *(u16 *)((&gBattleMons[gBattlerAttacker].attack) + (stat - 1)) = average; - *(u16 *)((&gBattleMons[gBattlerTarget].attack) + (stat - 1)) = average; + u16 *stat1 = GetBattlerStat(&gBattleMons[gBattlerAttacker], cmd->stat); + u16 *stat2 = GetBattlerStat(&gBattleMons[gBattlerTarget], cmd->stat); + u16 avg = (*stat1 + *stat2) / 2; + *stat1 = *stat2 = avg; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -15908,7 +15938,7 @@ bool32 IsMoveAffectedByParentalBond(u32 move, u32 battler) && gMovesInfo[move].strikeCount < 2 && gMovesInfo[move].effect != EFFECT_MULTI_HIT) { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { switch (GetBattlerMoveTargetType(battler, move)) { @@ -16025,7 +16055,7 @@ void BS_SetZEffect(void) static void TryUpdateRoundTurnOrder(void) { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { u32 i; u32 j = 0; @@ -16163,8 +16193,7 @@ void BS_ItemRestoreHP(void) // Check if the recipient is an active battler. if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) battler = gBattlerAttacker; - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE - && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) + else if (IsDoubleBattle() && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) battler = BATTLE_PARTNER(gBattlerAttacker); // Get amount to heal. @@ -16201,9 +16230,9 @@ void BS_ItemRestoreHP(void) SetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_HP, &hp); // Revived battlers on the field need to be brought back. - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && battler != MAX_BATTLERS_COUNT) + if (IsDoubleBattle() && battler != MAX_BATTLERS_COUNT) { - gAbsentBattlerFlags &= ~gBitTable[battler]; + gAbsentBattlerFlags &= ~(1u << battler); gBattleMons[battler].hp = hp; gBattleCommunication[MULTIUSE_STATE] = TRUE; } @@ -16227,7 +16256,7 @@ void BS_ItemCureStatus(void) previousStatus2 = gBattleMons[battler].status2; gBattleMons[gBattlerAttacker].status2 &= ~GetItemStatus2Mask(gLastUsedItem); } - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE + else if (IsDoubleBattle() && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) { battler = BATTLE_PARTNER(gBattlerAttacker); @@ -16292,7 +16321,7 @@ void BS_ItemRestorePP(void) // Check if the recipient is an active battler. if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) battler = gBattlerAttacker; - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE + else if (IsDoubleBattle() && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) battler = BATTLE_PARTNER(gBattlerAttacker); @@ -16623,7 +16652,7 @@ void BS_SetPledge(void) gBattleCommunication[MSG_DISPLAY] = 0; } else if ((gChosenActionByBattler[partner] == B_ACTION_USE_MOVE) - && gBattleTypeFlags & BATTLE_TYPE_DOUBLE + && IsDoubleBattle() && IsBattlerAlive(partner) && gCurrentMove != partnerMove && gMovesInfo[partnerMove].effect == EFFECT_PLEDGE) @@ -17121,3 +17150,19 @@ void BS_DamageToQuarterTargetHP(void) gBattlescriptCurrInstr = cmd->nextInstr; } + +void BS_FickleBeamDamageCalculation(void) +{ + NATIVE_ARGS(); + gBattleStruct->fickleBeamBoosted = FALSE; + + if (RandomPercentage(RNG_FICKLE_BEAM, 30)) + { + gBattleStruct->fickleBeamBoosted = TRUE; + gBattlescriptCurrInstr = BattleScript_FickleBeamDoubled; + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } +} diff --git a/src/battle_setup.c b/src/battle_setup.c index 41f2b9b502..54c4f99b92 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -1940,7 +1940,7 @@ void IncrementRematchStepCounter(void) #if FREE_MATCH_CALL == FALSE if (!HasAtLeastFiveBadges()) return; - + if (IsVsSeekerEnabled()) return; diff --git a/src/battle_terastal.c b/src/battle_terastal.c index 6866c6aaad..2c140414db 100644 --- a/src/battle_terastal.c +++ b/src/battle_terastal.c @@ -30,7 +30,7 @@ void ActivateTera(u32 battler) if (B_FLAG_TERA_ORB_CHARGED != 0 && (B_FLAG_TERA_ORB_NO_COST == 0 || !FlagGet(B_FLAG_TERA_ORB_NO_COST)) && side == B_SIDE_PLAYER - && !(gBattleTypeFlags & BATTLE_TYPE_DOUBLE && !IsPartnerMonFromSameTrainer(battler))) + && !(IsDoubleBattle() && !IsPartnerMonFromSameTrainer(battler))) { FlagClear(B_FLAG_TERA_ORB_CHARGED); } @@ -63,6 +63,10 @@ bool32 CanTerastallize(u32 battler) { u32 holdEffect = GetBattlerHoldEffect(battler, FALSE); + // Prevents Zigzagoon from terastalizing in vanilla. + if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE && GetBattlerSide(battler) == B_SIDE_OPPONENT) + return FALSE; + if (TESTING || GetBattlerSide(battler) == B_SIDE_OPPONENT) { // Skip all other checks in this block, go to HasTrainerUsedGimmick @@ -110,14 +114,14 @@ u32 GetBattlerTeraType(u32 battler) void ExpendTypeStellarBoost(u32 battler, u32 type) { if (type < 32 && gBattleMons[battler].species != SPECIES_TERAPAGOS_STELLAR) // avoid OOB access - gBattleStruct->stellarBoostFlags[GetBattlerSide(battler)] |= gBitTable[type]; + gBattleStruct->stellarBoostFlags[GetBattlerSide(battler)] |= 1u << type; } // Checks whether a type's Stellar boost has been expended. bool32 IsTypeStellarBoosted(u32 battler, u32 type) { if (type < 32) // avoid OOB access - return !(gBattleStruct->stellarBoostFlags[GetBattlerSide(battler)] & gBitTable[type]); + return !(gBattleStruct->stellarBoostFlags[GetBattlerSide(battler)] & (1u << type)); else return FALSE; } diff --git a/src/battle_util.c b/src/battle_util.c index 3d9338acee..d33ca634cf 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -130,7 +130,7 @@ void HandleAction_UseMove(void) u16 moveTarget; gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber]; - if (gBattleStruct->absentBattlerFlags & gBitTable[gBattlerAttacker] || !IsBattlerAlive(gBattlerAttacker)) + if (gBattleStruct->absentBattlerFlags & (1u << gBattlerAttacker) || !IsBattlerAlive(gBattlerAttacker)) { gCurrentActionFuncId = B_ACTION_FINISHED; return; @@ -221,7 +221,7 @@ void HandleAction_UseMove(void) { gBattleStruct->moveTarget[gBattlerAttacker] = gBattlerTarget = gSideTimers[side].followmeTarget; // follow me moxie fix } - else if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + else if (IsDoubleBattle() && gSideTimers[side].followmeTimer == 0 && (gMovesInfo[gCurrentMove].power != 0 || (moveTarget != MOVE_TARGET_USER && moveTarget != MOVE_TARGET_ALL_BATTLERS)) && ((GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) @@ -305,8 +305,7 @@ void HandleAction_UseMove(void) gBattlerTarget = battler; } } - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE - && moveTarget & MOVE_TARGET_RANDOM) + else if (IsDoubleBattle() && moveTarget & MOVE_TARGET_RANDOM) { if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) { @@ -323,7 +322,7 @@ void HandleAction_UseMove(void) gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); } - if (gAbsentBattlerFlags & gBitTable[gBattlerTarget] + if (gAbsentBattlerFlags & (1u << gBattlerTarget) && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget)) { gBattlerTarget = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerTarget))); @@ -336,8 +335,7 @@ void HandleAction_UseMove(void) else gBattlerTarget = gBattlerAttacker; } - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE - && moveTarget == MOVE_TARGET_FOES_AND_ALLY) + else if (IsDoubleBattle() && moveTarget == MOVE_TARGET_FOES_AND_ALLY) { for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++) { @@ -966,29 +964,29 @@ static void UNUSED MarkAllBattlersForControllerExec(void) if (gBattleTypeFlags & BATTLE_TYPE_LINK) { for (i = 0; i < gBattlersCount; i++) - gBattleControllerExecFlags |= gBitTable[i] << (32 - MAX_BATTLERS_COUNT); + gBattleControllerExecFlags |= 1u << (i + 32 - MAX_BATTLERS_COUNT); } else { for (i = 0; i < gBattlersCount; i++) - gBattleControllerExecFlags |= gBitTable[i]; + gBattleControllerExecFlags |= 1 << i; } } bool32 IsBattlerMarkedForControllerExec(u32 battler) { if (gBattleTypeFlags & BATTLE_TYPE_LINK) - return (gBattleControllerExecFlags & (gBitTable[battler] << 0x1C)) != 0; + return (gBattleControllerExecFlags & (1 << (battler + 28))) != 0; else - return (gBattleControllerExecFlags & (gBitTable[battler])) != 0; + return (gBattleControllerExecFlags & (1 << battler)) != 0; } void MarkBattlerForControllerExec(u32 battler) { if (gBattleTypeFlags & BATTLE_TYPE_LINK) - gBattleControllerExecFlags |= gBitTable[battler] << (32 - MAX_BATTLERS_COUNT); + gBattleControllerExecFlags |= 1u << (32 - MAX_BATTLERS_COUNT); else - gBattleControllerExecFlags |= gBitTable[battler]; + gBattleControllerExecFlags |= 1u << battler; } void MarkBattlerReceivedLinkData(u32 battler) @@ -996,9 +994,9 @@ void MarkBattlerReceivedLinkData(u32 battler) s32 i; for (i = 0; i < GetLinkPlayerCount(); i++) - gBattleControllerExecFlags |= gBitTable[battler] << (i << 2); + gBattleControllerExecFlags |= 1u << (battler + (i << 2)); - gBattleControllerExecFlags &= ~((1 << 28) << battler); + gBattleControllerExecFlags &= ~(1u << (28 + battler)); } const u8* CancelMultiTurnMoves(u32 battler) @@ -1174,7 +1172,7 @@ void ResetSentPokesToOpponentValue(void) gSentPokesToOpponent[1] = 0; for (i = 0; i < gBattlersCount; i += 2) - bits |= gBitTable[gBattlerPartyIndexes[i]]; + bits |= 1u << gBattlerPartyIndexes[i]; for (i = 1; i < gBattlersCount; i += 2) gSentPokesToOpponent[(i & BIT_FLANK) >> 1] = bits; @@ -1192,8 +1190,8 @@ void OpponentSwitchInResetSentPokesToOpponentValue(u32 battler) for (i = 0; i < gBattlersCount; i += 2) { - if (!(gAbsentBattlerFlags & gBitTable[i])) - bits |= gBitTable[gBattlerPartyIndexes[i]]; + if (!(gAbsentBattlerFlags & (1u << i))) + bits |= 1u << gBattlerPartyIndexes[i]; } gSentPokesToOpponent[flank] = bits; } @@ -1209,7 +1207,7 @@ void UpdateSentPokesToOpponentValue(u32 battler) { s32 i; for (i = 1; i < gBattlersCount; i++) - gSentPokesToOpponent[(i & BIT_FLANK) >> 1] |= gBitTable[gBattlerPartyIndexes[battler]]; + gSentPokesToOpponent[(i & BIT_FLANK) >> 1] |= 1u << gBattlerPartyIndexes[battler]; } } @@ -1250,7 +1248,7 @@ bool32 IsBelchPreventingMove(u32 battler, u32 move) if (gMovesInfo[move].effect != EFFECT_BELCH) return FALSE; - return !(gBattleStruct->ateBerry[battler & BIT_SIDE] & gBitTable[gBattlerPartyIndexes[battler]]); + return !(gBattleStruct->ateBerry[battler & BIT_SIDE] & (1u << gBattlerPartyIndexes[battler])); } // Dynamax bypasses all selection prevention except Taunt and Assault Vest. @@ -1515,55 +1513,55 @@ u8 CheckMoveLimitations(u32 battler, u8 unusableMoves, u16 check) moveEffect = gMovesInfo[move].effect; // No move if (check & MOVE_LIMITATION_ZEROMOVE && move == MOVE_NONE) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; // No PP else if (check & MOVE_LIMITATION_PP && gBattleMons[battler].pp[i] == 0) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; // Placeholder else if (check & MOVE_LIMITATION_PLACEHOLDER && moveEffect == EFFECT_PLACEHOLDER) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; // Disable else if (check & MOVE_LIMITATION_DISABLED && move == gDisableStructs[battler].disabledMove) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; // Torment else if (check & MOVE_LIMITATION_TORMENTED && move == gLastMoves[battler] && gBattleMons[battler].status2 & STATUS2_TORMENT) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; // Taunt else if (check & MOVE_LIMITATION_TAUNT && gDisableStructs[battler].tauntTimer && IS_MOVE_STATUS(move)) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; // Imprison else if (check & MOVE_LIMITATION_IMPRISON && GetImprisonedMovesCount(battler, move)) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; // Encore else if (check & MOVE_LIMITATION_ENCORE && gDisableStructs[battler].encoreTimer && gDisableStructs[battler].encoredMove != move) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; // Choice Items else if (check & MOVE_LIMITATION_CHOICE_ITEM && HOLD_EFFECT_CHOICE(holdEffect) && *choicedMove != MOVE_NONE && *choicedMove != MOVE_UNAVAILABLE && *choicedMove != move) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; // Assault Vest else if (check & MOVE_LIMITATION_ASSAULT_VEST && holdEffect == HOLD_EFFECT_ASSAULT_VEST && IS_MOVE_STATUS(move) && gMovesInfo[move].effect != EFFECT_ME_FIRST) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; // Gravity else if (check & MOVE_LIMITATION_GRAVITY && IsGravityPreventingMove(move)) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; // Heal Block else if (check & MOVE_LIMITATION_HEAL_BLOCK && IsHealBlockPreventingMove(battler, move)) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; // Belch else if (check & MOVE_LIMITATION_BELCH && IsBelchPreventingMove(battler, move)) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; // Throat Chop else if (check & MOVE_LIMITATION_THROAT_CHOP && gDisableStructs[battler].throatChopTimer && gMovesInfo[move].soundMove) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; // Stuff Cheeks else if (check & MOVE_LIMITATION_STUFF_CHEEKS && moveEffect == EFFECT_STUFF_CHEEKS && ItemId_GetPocket(gBattleMons[battler].item) != POCKET_BERRIES) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; // Gorilla Tactics else if (check & MOVE_LIMITATION_CHOICE_ITEM && GetBattlerAbility(battler) == ABILITY_GORILLA_TACTICS && *choicedMove != MOVE_NONE && *choicedMove != MOVE_UNAVAILABLE && *choicedMove != move) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; // Can't Use Twice flag else if (check & MOVE_LIMITATION_CANT_USE_TWICE && gMovesInfo[move].cantUseTwice && move == gLastResultingMoves[battler]) - unusableMoves |= gBitTable[i]; + unusableMoves |= 1u << i; } return unusableMoves; } @@ -1671,8 +1669,6 @@ enum ENDTURN_PSYCHIC_TERRAIN, ENDTURN_ION_DELUGE, ENDTURN_FAIRY_LOCK, - ENDTURN_RETALIATE, - ENDTURN_WEATHER_FORM, ENDTURN_STATUS_HEAL, ENDTURN_RAINBOW, ENDTURN_SEA_OF_FIRE, @@ -1705,10 +1701,10 @@ u8 DoFieldEndTurnEffects(void) { u8 effect = 0; - for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount && gAbsentBattlerFlags & gBitTable[gBattlerAttacker]; gBattlerAttacker++) + for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount && gAbsentBattlerFlags & (1u << gBattlerAttacker); gBattlerAttacker++) { } - for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount && gAbsentBattlerFlags & gBitTable[gBattlerTarget]; gBattlerTarget++) + for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount && gAbsentBattlerFlags & (1u << gBattlerTarget); gBattlerTarget++) { } @@ -2165,25 +2161,6 @@ u8 DoFieldEndTurnEffects(void) } gBattleStruct->turnCountersTracker++; break; - case ENDTURN_RETALIATE: - if (gSideTimers[B_SIDE_PLAYER].retaliateTimer > 0) - gSideTimers[B_SIDE_PLAYER].retaliateTimer--; - if (gSideTimers[B_SIDE_OPPONENT].retaliateTimer > 0) - gSideTimers[B_SIDE_OPPONENT].retaliateTimer--; - gBattleStruct->turnCountersTracker++; - break; - case ENDTURN_WEATHER_FORM: - for (i = 0; i < gBattlersCount; i++) - { - if (AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, i, 0, 0, 0)) - { - effect++; - break; - } - } - if (effect == 0) - gBattleStruct->turnCountersTracker++; - break; case ENDTURN_STATUS_HEAL: for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; gBattlerAttacker++) { @@ -2372,7 +2349,7 @@ u8 DoBattlerEndTurnEffects(void) while (gBattleStruct->turnEffectsBattlerId < gBattlersCount && gBattleStruct->turnEffectsTracker <= ENDTURN_BATTLER_COUNT) { battler = gBattlerAttacker = gBattlerByTurnOrder[gBattleStruct->turnEffectsBattlerId]; - if (gAbsentBattlerFlags & gBitTable[battler]) + if (gAbsentBattlerFlags & (1u << battler)) { gBattleStruct->turnEffectsBattlerId++; continue; @@ -2401,6 +2378,8 @@ u8 DoBattlerEndTurnEffects(void) { gBattleScripting.battler = battler; gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; BattleScriptExecute(BattleScript_DamagingWeather); effect++; } @@ -2411,7 +2390,7 @@ u8 DoBattlerEndTurnEffects(void) && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) { gBattleScripting.battler = battler; - gBattleMoveDamage = -1 * (GetNonDynamaxMaxHP(battler) / 16); + gBattleMoveDamage = -1 * max(1, GetNonDynamaxMaxHP(battler) / 16); BattleScriptExecute(BattleScript_IceBodyHeal); effect++; } @@ -2425,6 +2404,8 @@ u8 DoBattlerEndTurnEffects(void) { gBattleScripting.battler = battler; gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; BattleScriptExecute(BattleScript_DamagingWeather); effect++; } @@ -3034,7 +3015,7 @@ bool32 HandleWishPerishSongOnTurnEnd(void) if (gWishFutureKnock.futureSightCounter[battler] != 0 && --gWishFutureKnock.futureSightCounter[battler] == 0 - && !(gAbsentBattlerFlags & gBitTable[battler])) + && !(gAbsentBattlerFlags & (1u << battler))) { struct Pokemon *party; @@ -3075,7 +3056,7 @@ bool32 HandleWishPerishSongOnTurnEnd(void) while (gBattleStruct->wishPerishSongBattlerId < gBattlersCount) { battler = gBattlerAttacker = gBattlerByTurnOrder[gBattleStruct->wishPerishSongBattlerId]; - if (gAbsentBattlerFlags & gBitTable[battler]) + if (gAbsentBattlerFlags & (1u << battler)) { gBattleStruct->wishPerishSongBattlerId++; continue; @@ -3141,8 +3122,8 @@ bool32 HandleFaintedMonActions(void) gBattleStruct->faintedActionsState++; for (i = 0; i < gBattlersCount; i++) { - if (gAbsentBattlerFlags & gBitTable[i] && !HasNoMonsToSwitch(i, PARTY_SIZE, PARTY_SIZE)) - gAbsentBattlerFlags &= ~(gBitTable[i]); + if (gAbsentBattlerFlags & (1u << i) && !HasNoMonsToSwitch(i, PARTY_SIZE, PARTY_SIZE)) + gAbsentBattlerFlags &= ~(1u << i); } // fall through case 1: @@ -3150,8 +3131,8 @@ bool32 HandleFaintedMonActions(void) { gBattlerFainted = gBattlerTarget = gBattleStruct->faintedActionsBattlerId; if (gBattleMons[gBattleStruct->faintedActionsBattlerId].hp == 0 - && !(gBattleStruct->givenExpMons & gBitTable[gBattlerPartyIndexes[gBattleStruct->faintedActionsBattlerId]]) - && !(gAbsentBattlerFlags & gBitTable[gBattleStruct->faintedActionsBattlerId])) + && !(gBattleStruct->givenExpMons & (1u << gBattlerPartyIndexes[gBattleStruct->faintedActionsBattlerId])) + && !(gAbsentBattlerFlags & (1u << gBattleStruct->faintedActionsBattlerId))) { BattleScriptExecute(BattleScript_GiveExp); gBattleStruct->faintedActionsState = 2; @@ -3172,7 +3153,7 @@ bool32 HandleFaintedMonActions(void) && !NoAliveMonsForEitherParty() && gCurrentTurnActionNumber != gBattlersCount) { - gAbsentBattlerFlags |= gBitTable[gBattlerFainted]; + gAbsentBattlerFlags |= 1u << gBattlerFainted; if (gBattleStruct->faintedActionsState != 1) return FALSE; } @@ -3194,7 +3175,7 @@ bool32 HandleFaintedMonActions(void) { gBattlerFainted = gBattlerTarget = gBattleStruct->faintedActionsBattlerId; if (gBattleMons[gBattleStruct->faintedActionsBattlerId].hp == 0 - && !(gAbsentBattlerFlags & gBitTable[gBattleStruct->faintedActionsBattlerId])) + && !(gAbsentBattlerFlags & (1u << gBattleStruct->faintedActionsBattlerId))) { BattleScriptExecute(BattleScript_HandleFaintedMon); gBattleStruct->faintedActionsState = 5; @@ -3500,7 +3481,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) gCurrentMove = MOVE_BIDE; gBattleScripting.bideDmg = gBideDmg[gBattlerAttacker] * 2; gBattlerTarget = gBideTarget[gBattlerAttacker]; - if (gAbsentBattlerFlags & gBitTable[gBattlerTarget]) + if (gAbsentBattlerFlags & (1u << gBattlerTarget)) gBattlerTarget = GetMoveTarget(MOVE_BIDE, MOVE_TARGET_SELECTED + 1); gBattlescriptCurrInstr = BattleScript_BideAttack; } @@ -3659,13 +3640,14 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) else { gMultiHitCounter = gMovesInfo[gCurrentMove].strikeCount; - PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 3, 0) if (gMovesInfo[gCurrentMove].effect == EFFECT_DRAGON_DARTS && CanTargetPartner(gBattlerAttacker, gBattlerTarget) && TargetFullyImmuneToCurrMove(gBattlerAttacker, gBattlerTarget)) gBattlerTarget = BATTLE_PARTNER(gBattlerTarget); } + + PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 3, 0) } else if (B_BEAT_UP >= GEN_5 && gMovesInfo[gCurrentMove].effect == EFFECT_BEAT_UP) { @@ -3744,7 +3726,7 @@ bool32 HasNoMonsToSwitch(u32 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2 u32 i, side, playerId, flankId; struct Pokemon *party; - if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + if (!IsDoubleBattle()) return FALSE; side = GetBattlerSide(battler); @@ -3895,21 +3877,6 @@ static const u16 sWeatherFlagsInfo[][3] = [ENUM_WEATHER_FOG] = {B_WEATHER_FOG_TEMPORARY, B_WEATHER_FOG_PERMANENT, HOLD_EFFECT_NONE}, }; -static void ShouldChangeFormInWeather(u32 battler) -{ - int i; - int side = GetBattlerSide(battler); - struct Pokemon *party = GetSideParty(side); - - for (i = 0; i < PARTY_SIZE; i++) - { - if (GetMonData(&party[i], MON_DATA_SPECIES) == SPECIES_EISCUE_NOICE_FACE) - gBattleStruct->allowedToChangeFormInWeather[i][side] = TRUE; - else - gBattleStruct->allowedToChangeFormInWeather[i][side] = FALSE; - } -} - bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility) { u16 battlerAbility = GetBattlerAbility(battler); @@ -3923,7 +3890,6 @@ bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility) else if (B_ABILITY_WEATHER < GEN_6 && viaAbility && !(gBattleWeather & sWeatherFlagsInfo[weatherEnumId][1])) { gBattleWeather = (sWeatherFlagsInfo[weatherEnumId][0] | sWeatherFlagsInfo[weatherEnumId][1]); - ShouldChangeFormInWeather(battler); return TRUE; } else if (!(gBattleWeather & (sWeatherFlagsInfo[weatherEnumId][0] | sWeatherFlagsInfo[weatherEnumId][1]))) @@ -3933,7 +3899,6 @@ bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility) gWishFutureKnock.weatherDuration = 8; else gWishFutureKnock.weatherDuration = 5; - ShouldChangeFormInWeather(battler); return TRUE; } return FALSE; @@ -4061,6 +4026,54 @@ static inline bool32 HadMoreThanHalfHpNowDoesnt(u32 battler) && gBattleMons[battler].hp <= cutoff); } +#define ANIM_STAT_HP 0 +#define ANIM_STAT_ATK 1 +#define ANIM_STAT_DEF 2 +#define ANIM_STAT_SPATK 3 +#define ANIM_STAT_SPDEF 4 +#define ANIM_STAT_SPEED 5 +#define ANIM_STAT_ACC 6 +#define ANIM_STAT_EVASION 7 +static void ChooseStatBoostAnimation(u32 battler) +{ + u32 stat; + bool32 statBuffMoreThan1 = FALSE; + u32 static const statsOrder[NUM_BATTLE_STATS] = + { + [ANIM_STAT_HP] = STAT_HP, + [ANIM_STAT_ATK] = STAT_ATK, + [ANIM_STAT_DEF] = STAT_DEF, + [ANIM_STAT_SPATK] = STAT_SPATK, + [ANIM_STAT_SPDEF] = STAT_SPDEF, + [ANIM_STAT_SPEED] = STAT_SPEED, + [ANIM_STAT_ACC] = STAT_ACC, + [ANIM_STAT_EVASION] = STAT_EVASION, + }; + gBattleScripting.animArg1 = 0; + + for (stat = 1; stat < NUM_BATTLE_STATS; stat++) // Start loop at 1 to avoid STAT_HP + { + if ((gQueuedStatBoosts[battler].stats & (1 << statsOrder[stat])) == 0) + continue; + + if (!statBuffMoreThan1) + statBuffMoreThan1 = ((gQueuedStatBoosts[battler].stats & (1 << statsOrder[stat])) > 1); + + if (gBattleScripting.animArg1 != 0) // Already set in a different stat so now boosting multiple stats + gBattleScripting.animArg1 = (statBuffMoreThan1 ? STAT_ANIM_MULTIPLE_PLUS2 : STAT_ANIM_MULTIPLE_PLUS1); + else + gBattleScripting.animArg1 = GET_STAT_BUFF_ID((statsOrder[stat] + 1)) + (statBuffMoreThan1 ? STAT_ANIM_PLUS2 : STAT_ANIM_PLUS1); + } +} +#undef ANIM_STAT_HP +#undef ANIM_STAT_ATK +#undef ANIM_STAT_DEF +#undef ANIM_STAT_SPATK +#undef ANIM_STAT_SPDEF +#undef ANIM_STAT_SPEED +#undef ANIM_STAT_ACC +#undef ANIM_STAT_EVASION + u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 moveArg) { u32 effect = 0; @@ -4328,7 +4341,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 target1 = GetBattlerAtPosition(side); target2 = GetBattlerAtPosition(side + BIT_FLANK); gSpecialStatuses[battler].switchInAbilityDone = TRUE; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { if (!gAbilitiesInfo[gBattleMons[target1].ability].cantBeTraced && gBattleMons[target1].hp != 0 && !gAbilitiesInfo[gBattleMons[target2].ability].cantBeTraced && gBattleMons[target2].hp != 0) @@ -4685,11 +4698,11 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_SUPERSWEET_SYRUP: if (!gSpecialStatuses[battler].switchInAbilityDone - && !(gBattleStruct->supersweetSyrup[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]])) + && !(gBattleStruct->supersweetSyrup[GetBattlerSide(battler)] & (1u << gBattlerPartyIndexes[battler]))) { gBattlerAttacker = battler; gSpecialStatuses[battler].switchInAbilityDone = TRUE; - gBattleStruct->supersweetSyrup[GetBattlerSide(battler)] |= gBitTable[gBattlerPartyIndexes[battler]]; + gBattleStruct->supersweetSyrup[GetBattlerSide(battler)] |= (1u << gBattlerPartyIndexes[battler]); BattleScriptPushCursorAndCallback(BattleScript_SupersweetSyrupActivates); effect++; } @@ -4726,12 +4739,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_INTREPID_SWORD: if (!gSpecialStatuses[battler].switchInAbilityDone && CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN) - && !(gBattleStruct->intrepidSwordBoost[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]])) + && !(gBattleStruct->intrepidSwordBoost[GetBattlerSide(battler)] & (1u << gBattlerPartyIndexes[battler]))) { gBattleScripting.savedBattler = gBattlerAttacker; gBattlerAttacker = battler; if (B_INTREPID_SWORD == GEN_9) - gBattleStruct->intrepidSwordBoost[GetBattlerSide(battler)] |= gBitTable[gBattlerPartyIndexes[battler]]; + gBattleStruct->intrepidSwordBoost[GetBattlerSide(battler)] |= 1u << gBattlerPartyIndexes[battler]; gSpecialStatuses[battler].switchInAbilityDone = TRUE; SET_STATCHANGER(STAT_ATK, 1, FALSE); BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn); @@ -4740,18 +4753,31 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_DAUNTLESS_SHIELD: if (!gSpecialStatuses[battler].switchInAbilityDone && CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN) - && !(gBattleStruct->dauntlessShieldBoost[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]])) + && !(gBattleStruct->dauntlessShieldBoost[GetBattlerSide(battler)] & (1u << gBattlerPartyIndexes[battler]))) { gBattleScripting.savedBattler = gBattlerAttacker; gBattlerAttacker = battler; if (B_DAUNTLESS_SHIELD == GEN_9) - gBattleStruct->dauntlessShieldBoost[GetBattlerSide(battler)] |= gBitTable[gBattlerPartyIndexes[battler]]; + gBattleStruct->dauntlessShieldBoost[GetBattlerSide(battler)] |= 1u << gBattlerPartyIndexes[battler]; gSpecialStatuses[battler].switchInAbilityDone = TRUE; SET_STATCHANGER(STAT_DEF, 1, FALSE); BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn); effect++; } break; + case ABILITY_WIND_RIDER: + if (!gSpecialStatuses[battler].switchInAbilityDone + && CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN) + && gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_TAILWIND) + { + gBattleScripting.savedBattler = gBattlerAttacker; + gBattlerAttacker = battler; + gSpecialStatuses[battler].switchInAbilityDone = TRUE; + SET_STATCHANGER(STAT_ATK, 1, FALSE); + BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn); + effect++; + } + break; case ABILITY_DESOLATE_LAND: if (TryChangeBattleWeather(battler, ENUM_WEATHER_SUN_PRIMAL, TRUE)) { @@ -4849,11 +4875,11 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gSpecialStatuses[battler].switchInAbilityDone && GetMonData(mon, MON_DATA_SPECIES) == SPECIES_PALAFIN_HERO - && !(gBattleStruct->transformZeroToHero[side] & gBitTable[gBattlerPartyIndexes[battler]])) + && !(gBattleStruct->transformZeroToHero[side] & (1u << gBattlerPartyIndexes[battler]))) { gSpecialStatuses[battler].switchInAbilityDone = TRUE; gBattlerAttacker = battler; - gBattleStruct->transformZeroToHero[side] |= gBitTable[gBattlerPartyIndexes[battler]]; + gBattleStruct->transformZeroToHero[side] |= 1u << gBattlerPartyIndexes[battler]; BattleScriptPushCursorAndCallback(BattleScript_ZeroToHeroActivates); effect++; } @@ -4914,6 +4940,17 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect++; } break; + case ABILITY_ICE_FACE: + if (IsBattlerWeatherAffected(battler, B_WEATHER_HAIL | B_WEATHER_SNOW) + && gBattleMons[battler].species == SPECIES_EISCUE_NOICE_FACE + && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + { + // TODO: Convert this to a proper FORM_CHANGE type. + gBattleMons[battler].species = SPECIES_EISCUE_ICE_FACE; + BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3); + effect++; + } + break; } break; case ABILITYEFFECT_ENDTURN: @@ -4922,8 +4959,19 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gBattlerAttacker = battler; switch (gLastUsedAbility) { + case ABILITY_PICKUP: + if (gBattleMons[battler].item == ITEM_NONE + && gBattleStruct->changedItems[battler] == ITEM_NONE // Will not inherit an item + && PickupHasValidTarget(battler)) + { + gBattlerTarget = RandomUniformExcept(RNG_PICKUP, 0, gBattlersCount - 1, CantPickupItem); + gLastUsedItem = GetUsedHeldItem(gBattlerTarget); + BattleScriptPushCursorAndCallback(BattleScript_PickupActivates); + effect++; + } + break; case ABILITY_HARVEST: - if ((IsBattlerWeatherAffected(battler, B_WEATHER_SUN) || Random() % 2 == 0) + if ((IsBattlerWeatherAffected(battler, B_WEATHER_SUN) || RandomPercentage(RNG_HARVEST, 50)) && gBattleMons[battler].item == ITEM_NONE && gBattleStruct->changedItems[battler] == ITEM_NONE // Will not inherit an item && ItemId_GetPocket(GetUsedHeldItem(battler)) == POCKET_BERRIES) @@ -5000,9 +5048,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 for (i = STAT_ATK; i < statsNum; i++) { if (CompareStat(battler, i, MIN_STAT_STAGE, CMP_GREATER_THAN)) - validToLower |= gBitTable[i]; + validToLower |= 1u << i; if (CompareStat(battler, i, MAX_STAT_STAGE, CMP_LESS_THAN)) - validToRaise |= gBitTable[i]; + validToRaise |= 1u << i; } if (validToLower != 0 || validToRaise != 0) // Can lower one stat, or can raise one stat @@ -5013,16 +5061,16 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 do { i = (Random() % statsNum) + STAT_ATK; - } while (!(validToRaise & gBitTable[i])); + } while (!(validToRaise & (1u << i))); SET_STATCHANGER(i, 2, FALSE); - validToLower &= ~(gBitTable[i]); // Can't lower the same stat as raising. + validToLower &= ~(1u << i); // Can't lower the same stat as raising. } if (validToLower != 0) // Find stat to lower { do { i = (Random() % statsNum) + STAT_ATK; - } while (!(validToLower & gBitTable[i])); + } while (!(validToLower & (1u << i))); SET_STATCHANGER2(gBattleScripting.savedStatChanger, i, 1, TRUE); } BattleScriptPushCursorAndCallback(BattleScript_MoodyActivates); @@ -5177,7 +5225,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && BlocksPrankster(move, gBattlerAttacker, gBattlerTarget, TRUE) && !(IS_MOVE_STATUS(move) && (gLastUsedAbility == ABILITY_MAGIC_BOUNCE || gProtectStructs[gBattlerTarget].bounceMove))) { - if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(moveTarget & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) + if (!IsDoubleBattle() || !(moveTarget & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected gBattleScripting.battler = gBattlerAbility = gBattlerTarget; battleScriptBlocksMove = BattleScript_DarkTypePreventsPrankster; @@ -5518,6 +5566,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && TARGET_TURN_DAMAGED && !IS_BATTLER_OF_TYPE(battler, moveType) && moveType != TYPE_STELLAR + && moveType != TYPE_MYSTERY && IsBattlerAlive(battler)) { SET_BATTLER_TYPE(battler, moveType); @@ -5978,6 +6027,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gBattlescriptCurrInstr = BattleScript_AbilityStatusEffect; effect++; } + break; } break; case ABILITYEFFECT_MOVE_END_OTHER: // Abilities that activate on *another* battler's moveend: Dancer, Soul-Heart, Receiver, Symbiosis @@ -6002,6 +6052,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 // Edge case for dance moves that hit multiply targets gHitMarker &= ~HITMARKER_NO_ATTACKSTRING; + SetTypeBeforeUsingMove(gCalledMove, battler); // Make sure that the target isn't an ally - if it is, target the original user if (GetBattlerSide(gBattlerTarget) == GetBattlerSide(gBattlerAttacker)) @@ -6025,40 +6076,10 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_OPPORTUNIST: if (gProtectStructs[battler].activateOpportunist == 2) { - bool32 statBuffMoreThan1 = FALSE; - bool32 handleSpeedAnimLater = FALSE; gBattleScripting.animArg1 = 0; gBattleScripting.battler = battler; gProtectStructs[battler].activateOpportunist--; - - for (i = 0; i < (NUM_BATTLE_STATS - 1); i++) - { - if ((gQueuedStatBoosts[battler].stats & (1 << i)) == 0) - continue; - - if (i == STAT_SPEED) - { - handleSpeedAnimLater = TRUE; - continue; - } - - if (!statBuffMoreThan1) - statBuffMoreThan1 = ((gQueuedStatBoosts[battler].stats & (1 << i)) > 1); - - if (gBattleScripting.animArg1 != 0) //Already set in a different stat so now boosting multiple stats - gBattleScripting.animArg1 = (!statBuffMoreThan1 ? STAT_ANIM_MULTIPLE_PLUS1 : STAT_ANIM_MULTIPLE_PLUS2); - else - gBattleScripting.animArg1 = GET_STAT_BUFF_ID((i + 1)) + (!statBuffMoreThan1 ? STAT_ANIM_PLUS1 : STAT_ANIM_PLUS2); - - } - if (handleSpeedAnimLater) - { - if (gBattleScripting.animArg1 != 0) //Already set in a different stat so now boosting multiple stats - gBattleScripting.animArg1 = (!statBuffMoreThan1 ? STAT_ANIM_MULTIPLE_PLUS1 : STAT_ANIM_MULTIPLE_PLUS2); - else - gBattleScripting.animArg1 = GET_STAT_BUFF_ID((STAT_SPEED + 1)) + (!statBuffMoreThan1 ? STAT_ANIM_PLUS1 : STAT_ANIM_PLUS2); - } - + ChooseStatBoostAnimation(battler); BattleScriptPushCursorAndCallback(BattleScript_OpportunistCopyStatChange); effect = 1; } @@ -6248,17 +6269,17 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITYEFFECT_ON_WEATHER: // For ability effects that activate when the battle weather changes. - battler = gBattlerAbility = gBattleScripting.battler; gLastUsedAbility = GetBattlerAbility(battler); switch (gLastUsedAbility) { case ABILITY_FORECAST: case ABILITY_FLOWER_GIFT: if ((IsBattlerWeatherAffected(battler, gBattleWeather) - || gBattleWeather == B_WEATHER_NONE - || !WEATHER_HAS_EFFECT) // Air Lock active - && TryBattleFormChange(battler, FORM_CHANGE_BATTLE_WEATHER)) + || gBattleWeather == B_WEATHER_NONE + || !WEATHER_HAS_EFFECT) // Air Lock active + && TryBattleFormChange(battler, FORM_CHANGE_BATTLE_WEATHER)) { + gBattleScripting.battler = battler; BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3); effect++; } @@ -6266,11 +6287,10 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_ICE_FACE: if (IsBattlerWeatherAffected(battler, B_WEATHER_HAIL | B_WEATHER_SNOW) && gBattleMons[battler].species == SPECIES_EISCUE_NOICE_FACE - && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) - && gBattleStruct->allowedToChangeFormInWeather[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)]) + && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) { // TODO: Convert this to a proper FORM_CHANGE type. - gBattleStruct->allowedToChangeFormInWeather[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)] = FALSE; + gBattleScripting.battler = battler; gBattleMons[battler].species = SPECIES_EISCUE_ICE_FACE; BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3); effect++; @@ -6281,7 +6301,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 { gDisableStructs[battler].weatherAbilityDone = TRUE; PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler)); - gBattlerAbility = gBattleScripting.battler = battler; + gBattleScripting.battler = battler; BattleScriptPushCursorAndCallback(BattleScript_ProtosynthesisActivates); effect++; } @@ -7007,43 +7027,11 @@ static u8 TryConsumeMirrorHerb(u32 battler, bool32 execute) if (gProtectStructs[battler].eatMirrorHerb) { - u32 i; - bool32 statBuffMoreThan1 = FALSE; - bool32 handleSpeedAnimLater = FALSE; - gBattleScripting.animArg1 = 0; gLastUsedItem = gBattleMons[battler].item; gBattleScripting.battler = battler; gProtectStructs[battler].eatMirrorHerb = 0; - - for (i = 0; i < (NUM_BATTLE_STATS - 1); i++) - { - if ((gQueuedStatBoosts[battler].stats & (1 << i)) == 0) - continue; - - if (i == STAT_SPEED) - { - handleSpeedAnimLater = TRUE; - continue; - } - - if (!statBuffMoreThan1) - statBuffMoreThan1 = ((gQueuedStatBoosts[battler].stats & (1 << i)) > 1); - - if (gBattleScripting.animArg1 != 0) //Already set in a different stat so now boosting multiple stats - gBattleScripting.animArg1 = (!statBuffMoreThan1 ? STAT_ANIM_MULTIPLE_PLUS1 : STAT_ANIM_MULTIPLE_PLUS2); - else - gBattleScripting.animArg1 = GET_STAT_BUFF_ID((i + 1)) + (!statBuffMoreThan1 ? STAT_ANIM_PLUS1 : STAT_ANIM_PLUS2); - - } - if (handleSpeedAnimLater) - { - if (gBattleScripting.animArg1 != 0) //Already set in a different stat so now boosting multiple stats - gBattleScripting.animArg1 = (!statBuffMoreThan1 ? STAT_ANIM_MULTIPLE_PLUS1 : STAT_ANIM_MULTIPLE_PLUS2); - else - gBattleScripting.animArg1 = GET_STAT_BUFF_ID((STAT_SPEED + 1)) + (!statBuffMoreThan1 ? STAT_ANIM_PLUS1 : STAT_ANIM_PLUS2); - } - + ChooseStatBoostAnimation(battler); if (execute) { BattleScriptExecute(BattleScript_MirrorHerbCopyStatChangeEnd2); @@ -7574,13 +7562,13 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) effect = TryConsumeMirrorHerb(battler, TRUE); break; case HOLD_EFFECT_BOOSTER_ENERGY: - if (!(gBattleStruct->boosterEnergyActivates & gBitTable[battler]) + if (!(gBattleStruct->boosterEnergyActivates & (1u << battler)) && (((GetBattlerAbility(battler) == ABILITY_PROTOSYNTHESIS) && !(gBattleWeather & B_WEATHER_SUN)) || ((GetBattlerAbility(battler) == ABILITY_QUARK_DRIVE) && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN)))) { PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler)); gBattleScripting.battler = battler; - gBattleStruct->boosterEnergyActivates |= gBitTable[battler]; + gBattleStruct->boosterEnergyActivates |= 1u << battler; BattleScriptExecute(BattleScript_BoosterEnergyEnd2); effect = ITEM_EFFECT_OTHER; } @@ -7841,13 +7829,13 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) effect = TryConsumeMirrorHerb(battler, TRUE); break; case HOLD_EFFECT_BOOSTER_ENERGY: - if (!(gBattleStruct->boosterEnergyActivates & gBitTable[battler]) + if (!(gBattleStruct->boosterEnergyActivates & (1u << battler)) && (((GetBattlerAbility(battler) == ABILITY_PROTOSYNTHESIS) && !(gBattleWeather & B_WEATHER_SUN)) || ((GetBattlerAbility(battler) == ABILITY_QUARK_DRIVE) && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN)))) { PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler)); gBattlerAbility = gBattleScripting.battler = battler; - gBattleStruct->boosterEnergyActivates |= gBitTable[battler]; + gBattleStruct->boosterEnergyActivates |= 1u << battler; BattleScriptExecute(BattleScript_BoosterEnergyEnd2); effect = ITEM_EFFECT_OTHER; } @@ -8224,7 +8212,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) // Berry was successfully used on a Pokemon. if (effect && (gLastUsedItem >= FIRST_BERRY_INDEX && gLastUsedItem <= LAST_BERRY_INDEX)) - gBattleStruct->ateBerry[battler & BIT_SIDE] |= gBitTable[gBattlerPartyIndexes[battler]]; + gBattleStruct->ateBerry[battler & BIT_SIDE] |= 1u << gBattlerPartyIndexes[battler]; return effect; } @@ -8252,7 +8240,7 @@ u32 SetRandomTarget(u32 battler) [B_SIDE_OPPONENT] = {B_POSITION_PLAYER_LEFT, B_POSITION_PLAYER_RIGHT}, }; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { target = GetBattlerAtPosition(targets[GetBattlerSide(battler)][Random() % 2]); if (!IsBattlerAlive(target)) @@ -8270,6 +8258,7 @@ u32 GetMoveTarget(u16 move, u8 setTarget) { u8 targetBattler = 0; u32 moveTarget, side; + u32 moveType = GetMoveType(move); if (setTarget != NO_TARGET_OVERRIDE) moveTarget = setTarget - 1; @@ -8287,7 +8276,7 @@ u32 GetMoveTarget(u16 move, u8 setTarget) else { targetBattler = SetRandomTarget(gBattlerAttacker); - if (gMovesInfo[move].type == TYPE_ELECTRIC + if (moveType == TYPE_ELECTRIC && IsAbilityOnOpposingSide(gBattlerAttacker, ABILITY_LIGHTNING_ROD) && GetBattlerAbility(targetBattler) != ABILITY_LIGHTNING_ROD) { @@ -8295,7 +8284,7 @@ u32 GetMoveTarget(u16 move, u8 setTarget) RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); gSpecialStatuses[targetBattler].lightningRodRedirected = TRUE; } - else if (gMovesInfo[move].type == TYPE_WATER + else if (moveType == TYPE_WATER && IsAbilityOnOpposingSide(gBattlerAttacker, ABILITY_STORM_DRAIN) && GetBattlerAbility(targetBattler) != ABILITY_STORM_DRAIN) { @@ -8317,7 +8306,7 @@ u32 GetMoveTarget(u16 move, u8 setTarget) side = BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker)); if (IsAffectedByFollowMe(gBattlerAttacker, side, move)) targetBattler = gSideTimers[side].followmeTarget; - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && moveTarget & MOVE_TARGET_RANDOM) + else if (IsDoubleBattle() && moveTarget & MOVE_TARGET_RANDOM) targetBattler = SetRandomTarget(gBattlerAttacker); else targetBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker))); @@ -8404,7 +8393,7 @@ u8 IsMonDisobedient(void) // is not obedient if (gCurrentMove == MOVE_RAGE) gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_RAGE; - if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP && (gCurrentMove == MOVE_SNORE || gCurrentMove == MOVE_SLEEP_TALK)) + if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP && (gMovesInfo[gCurrentMove].effect == EFFECT_SNORE || gMovesInfo[gCurrentMove].effect == EFFECT_SLEEP_TALK)) { gBattlescriptCurrInstr = BattleScript_IgnoresWhileAsleep; return 1; @@ -8414,7 +8403,7 @@ u8 IsMonDisobedient(void) calc = (levelReferenced + obedienceLevel) * rnd >> 8; if (calc < obedienceLevel) { - calc = CheckMoveLimitations(gBattlerAttacker, gBitTable[gCurrMovePos], MOVE_LIMITATIONS_ALL); + calc = CheckMoveLimitations(gBattlerAttacker, 1u << gCurrMovePos, MOVE_LIMITATIONS_ALL); if (calc == ALL_MOVES_MASK) // all moves cannot be used { // Randomly select, then print a disobedient string @@ -8428,7 +8417,7 @@ u8 IsMonDisobedient(void) do { gCurrMovePos = gChosenMovePos = MOD(Random(), MAX_MON_MOVES); - } while (gBitTable[gCurrMovePos] & calc); + } while ((1u << gCurrMovePos) & calc); gCalledMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos]; SetAtkCancellerForCalledMove(); @@ -8570,16 +8559,20 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move) // Protective Pads doesn't stop Unseen Fist from bypassing Protect effects, so IsMoveMakingContact() isn't used here. // This means extra logic is needed to handle Shell Side Arm. if (GetBattlerAbility(gBattlerAttacker) == ABILITY_UNSEEN_FIST - && (gMovesInfo[move].makesContact - || (gMovesInfo[move].effect == EFFECT_SHELL_SIDE_ARM && gBattleStruct->shellSideArmCategory[battlerAtk][battlerDef] == DAMAGE_CATEGORY_PHYSICAL)) - && !gProtectStructs[battlerDef].maxGuarded) // Max Guard cannot be bypassed by Unseen Fist + && (gMovesInfo[move].makesContact + || (gMovesInfo[move].effect == EFFECT_SHELL_SIDE_ARM + && gBattleStruct->shellSideArmCategory[battlerAtk][battlerDef] == DAMAGE_CATEGORY_PHYSICAL)) + && !gProtectStructs[battlerDef].maxGuarded) // Max Guard cannot be bypassed by Unseen Fist return FALSE; + else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_CRAFTY_SHIELD + && IS_MOVE_STATUS(move)) + return TRUE; else if (gMovesInfo[move].ignoresProtect) return FALSE; else if (gProtectStructs[battlerDef].protected) return TRUE; else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_WIDE_GUARD - && GetBattlerMoveTargetType(gBattlerAttacker, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) + && GetBattlerMoveTargetType(gBattlerAttacker, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) return TRUE; else if (gProtectStructs[battlerDef].banefulBunkered) return TRUE; @@ -8596,11 +8589,8 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move) else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_QUICK_GUARD && GetChosenMovePriority(gBattlerAttacker) > 0) return TRUE; - else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_CRAFTY_SHIELD - && IS_MOVE_STATUS(move)) - return TRUE; else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_MAT_BLOCK - && !IS_MOVE_STATUS(move)) + && !IS_MOVE_STATUS(move)) return TRUE; else return FALSE; @@ -8643,7 +8633,7 @@ bool32 IsBattlerAlive(u32 battler) return FALSE; else if (battler >= gBattlersCount) return FALSE; - else if (gAbsentBattlerFlags & gBitTable[battler]) + else if (gAbsentBattlerFlags & (1u << battler)) return FALSE; else return TRUE; @@ -8716,12 +8706,12 @@ u32 GetMoveTargetCount(u32 move, u32 battlerAtk, u32 battlerDef) switch (GetBattlerMoveTargetType(gBattlerAttacker, move)) { case MOVE_TARGET_BOTH: - return !(gAbsentBattlerFlags & gBitTable[battlerDef]) - + !(gAbsentBattlerFlags & gBitTable[BATTLE_PARTNER(battlerDef)]); + return !(gAbsentBattlerFlags & (1u << battlerDef)) + + !(gAbsentBattlerFlags & (1u << BATTLE_PARTNER(battlerDef))); case MOVE_TARGET_FOES_AND_ALLY: - return !(gAbsentBattlerFlags & gBitTable[battlerDef]) - + !(gAbsentBattlerFlags & gBitTable[BATTLE_PARTNER(battlerDef)]) - + !(gAbsentBattlerFlags & gBitTable[BATTLE_PARTNER(battlerAtk)]); + return !(gAbsentBattlerFlags & (1u << battlerDef)) + + !(gAbsentBattlerFlags & (1u << BATTLE_PARTNER(battlerDef))) + + !(gAbsentBattlerFlags & (1u << BATTLE_PARTNER(battlerAtk))); case MOVE_TARGET_OPPONENTS_FIELD: return 1; case MOVE_TARGET_DEPENDS: @@ -8899,10 +8889,7 @@ static inline u32 CalcMoveBasePower(u32 move, u32 battlerAtk, u32 battlerDef, u3 basePower = gBattleStruct->presentBasePower; break; case EFFECT_TRIPLE_KICK: - if (gMultiHitCounter == 0) // Calc damage with max BP for move consideration - basePower *= 6; - else - basePower *= 1 + gMovesInfo[move].strikeCount - gMultiHitCounter; + basePower *= 1 + gMovesInfo[move].strikeCount - gMultiHitCounter; break; case EFFECT_SPIT_UP: basePower = 100 * gDisableStructs[battlerAtk].stockpileCounter; @@ -9087,7 +9074,7 @@ static inline u32 CalcMoveBasePower(u32 move, u32 battlerAtk, u32 battlerDef, u3 basePower = (basePower > 350) ? 350 : basePower; break; case EFFECT_FICKLE_BEAM: - if (RandomPercentage(RNG_FICKLE_BEAM, 30)) + if (gBattleStruct->fickleBeamBoosted) basePower *= 2; break; case EFFECT_TERA_BLAST: @@ -9142,7 +9129,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32 modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); break; case EFFECT_STOMPING_TANTRUM: - if (gBattleStruct->lastMoveFailed & gBitTable[battlerAtk]) + if (gBattleStruct->lastMoveFailed & (1u << battlerAtk)) modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case EFFECT_MAGNITUDE: @@ -9297,7 +9284,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32 case ABILITY_PROTOSYNTHESIS: { u8 atkHighestStat = GetHighestStatId(battlerAtk); - if ((weather & B_WEATHER_SUN || gBattleStruct->boosterEnergyActivates & gBitTable[battlerAtk]) + if ((weather & B_WEATHER_SUN || gBattleStruct->boosterEnergyActivates & (1u << battlerAtk)) && ((IS_MOVE_PHYSICAL(move) && atkHighestStat == STAT_ATK) || (IS_MOVE_SPECIAL(move) && atkHighestStat == STAT_SPATK))) modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); } @@ -9305,7 +9292,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32 case ABILITY_QUARK_DRIVE: { u8 atkHighestStat = GetHighestStatId(battlerAtk); - if ((gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gBattleStruct->boosterEnergyActivates & gBitTable[battlerAtk]) + if ((gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gBattleStruct->boosterEnergyActivates & (1u << battlerAtk)) && ((IS_MOVE_PHYSICAL(move) && atkHighestStat == STAT_ATK) || (IS_MOVE_SPECIAL(move) && atkHighestStat == STAT_SPATK))) modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); } @@ -9375,7 +9362,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32 case ABILITY_PROTOSYNTHESIS: { u8 defHighestStat = GetHighestStatId(battlerDef); - if ((weather & B_WEATHER_SUN || gBattleStruct->boosterEnergyActivates & gBitTable[battlerDef]) + if ((weather & B_WEATHER_SUN || gBattleStruct->boosterEnergyActivates & (1u << battlerDef)) && ((IS_MOVE_PHYSICAL(move) && defHighestStat == STAT_DEF) || (IS_MOVE_SPECIAL(move) && defHighestStat == STAT_SPDEF))) modifier = uq4_12_multiply(modifier, UQ_4_12(0.7)); } @@ -9383,7 +9370,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32 case ABILITY_QUARK_DRIVE: { u8 defHighestStat = GetHighestStatId(battlerDef); - if ((gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gBattleStruct->boosterEnergyActivates & gBitTable[battlerDef]) + if ((gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gBattleStruct->boosterEnergyActivates & (1u << battlerDef)) && ((IS_MOVE_PHYSICAL(move) && defHighestStat == STAT_DEF) || (IS_MOVE_SPECIAL(move) && defHighestStat == STAT_SPDEF))) modifier = uq4_12_multiply(modifier, UQ_4_12(0.7)); } @@ -9787,7 +9774,7 @@ static inline u32 CalcDefenseStat(u32 move, u32 battlerAtk, u32 battlerDef, u32 modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); break; case ABILITY_PURIFYING_SALT: - if (gMovesInfo[move].type == TYPE_GHOST) + if (moveType == TYPE_GHOST) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(2.0)); break; } @@ -9878,7 +9865,9 @@ static inline uq4_12_t GetParentalBondModifier(u32 battlerAtk) static inline uq4_12_t GetSameTypeAttackBonusModifier(u32 battlerAtk, u32 moveType, u32 move, u32 abilityAtk) { - if (gBattleStruct->pledgeMove && IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerAtk), moveType)) + if (moveType == TYPE_MYSTERY) + return UQ_4_12(1.0); + else if (gBattleStruct->pledgeMove && IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerAtk), moveType)) return (abilityAtk == ABILITY_ADAPTABILITY) ? UQ_4_12(2.0) : UQ_4_12(1.5); else if (!IS_BATTLER_OF_TYPE(battlerAtk, moveType) || move == MOVE_STRUGGLE || move == MOVE_NONE) return UQ_4_12(1.0); @@ -9983,7 +9972,7 @@ static inline uq4_12_t GetScreensModifier(u32 move, u32 battlerAtk, u32 battlerD if (isCrit || abilityAtk == ABILITY_INFILTRATOR || gProtectStructs[battlerAtk].confusionSelfDmg) return UQ_4_12(1.0); if (reflect || lightScreen || auroraVeil) - return (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) ? UQ_4_12(0.667) : UQ_4_12(0.5); + return (IsDoubleBattle()) ? UQ_4_12(0.667) : UQ_4_12(0.5); return UQ_4_12(1.0); } @@ -10349,7 +10338,7 @@ static inline void MulByTypeEffectiveness(uq4_12_t *modifier, u32 move, u32 move mod = UQ_4_12(1.0); } - if (gBattleStruct->distortedTypeMatchups & gBitTable[battlerDef] || (gBattleStruct->aiCalcInProgress && ShouldTeraShellDistortTypeMatchups(move, battlerDef))) + if (gBattleStruct->distortedTypeMatchups & (1u << battlerDef) || (gBattleStruct->aiCalcInProgress && ShouldTeraShellDistortTypeMatchups(move, battlerDef))) { mod = UQ_4_12(0.5); if (recordAbilities) @@ -10481,7 +10470,7 @@ uq4_12_t CalcTypeEffectivenessMultiplier(u32 move, u32 moveType, u32 battlerAtk, uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef) { uq4_12_t modifier = UQ_4_12(1.0); - u8 moveType = gMovesInfo[move].type; + u32 moveType = GetMoveType(move); if (move != MOVE_STRUGGLE && moveType != TYPE_MYSTERY) { @@ -11259,7 +11248,7 @@ bool32 CanStealItem(u32 battlerStealing, u32 battlerItem, u16 item) | BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_SECRET_BASE)) - && (gWishFutureKnock.knockedOffMons[stealerSide] & gBitTable[gBattlerPartyIndexes[battlerStealing]])) + && (gWishFutureKnock.knockedOffMons[stealerSide] & (1u << gBattlerPartyIndexes[battlerStealing]))) { return FALSE; } @@ -11425,6 +11414,25 @@ u16 GetUsedHeldItem(u32 battler) return gBattleStruct->usedHeldItems[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)]; } +bool32 CantPickupItem(u32 battler) +{ + // Used by RandomUniformExcept() for RNG_PICKUP + if (battler == gBattlerAttacker && gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_LINK)) + return TRUE; + return !(IsBattlerAlive(battler) && GetUsedHeldItem(battler) && gBattleStruct->canPickupItem & (1u << battler)); +} + +bool32 PickupHasValidTarget(u32 battler) +{ + u32 i; + for (i = 0; i < gBattlersCount; i++) + { + if (!CantPickupItem(i)) + return TRUE; + } + return FALSE; +} + bool32 IsBattlerWeatherAffected(u32 battler, u32 weatherFlags) { if (gBattleWeather & weatherFlags && WEATHER_HAS_EFFECT) @@ -11787,7 +11795,7 @@ void SetShellSideArmCategory(void) bool32 CanTargetPartner(u32 battlerAtk, u32 battlerDef) { - return (gBattleTypeFlags & BATTLE_TYPE_DOUBLE + return (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battlerDef)) && battlerDef != BATTLE_PARTNER(battlerAtk)); } diff --git a/src/battle_util2.c b/src/battle_util2.c index 2c333978d2..326acf0e40 100644 --- a/src/battle_util2.c +++ b/src/battle_util2.c @@ -80,7 +80,7 @@ void AdjustFriendshipOnBattleFaint(u8 battler) { u8 opposingBattlerId; - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (IsDoubleBattle()) { u8 opposingBattlerId2; diff --git a/src/battle_z_move.c b/src/battle_z_move.c index 8113da48a9..5a5816142c 100644 --- a/src/battle_z_move.c +++ b/src/battle_z_move.c @@ -209,13 +209,13 @@ void AssignUsableZMoves(u32 battler, u16 *moves) for (i = 0; i < MAX_MON_MOVES; i++) { if (moves[i] != MOVE_NONE && IsViableZMove(battler, moves[i])) - gBattleStruct->zmove.possibleZMoves[battler] |= gBitTable[i]; + gBattleStruct->zmove.possibleZMoves[battler] |= 1u << i; } } bool32 TryChangeZTrigger(u32 battler, u32 moveIndex) { - bool32 viableZMove = (gBattleStruct->zmove.possibleZMoves[battler] & gBitTable[moveIndex]) != 0; + bool32 viableZMove = (gBattleStruct->zmove.possibleZMoves[battler] & (1u << moveIndex)) != 0; if (gBattleStruct->zmove.viable && !viableZMove) HideGimmickTriggerSprite(); // Was a viable z move, now is not -> slide out diff --git a/src/berry.c b/src/berry.c index 9f187bd1e2..1a1c3b7f1f 100644 --- a/src/berry.c +++ b/src/berry.c @@ -1817,6 +1817,8 @@ bool32 BerryTreeGrow(struct BerryTree *tree) tree->stage = BERRY_STAGE_BERRIES; break; case BERRY_STAGE_BERRIES: + if (OW_BERRY_IMMORTAL) + break; tree->watered = 0; tree->berryYield = 0; tree->stage = BERRY_STAGE_SPROUTED; @@ -1842,16 +1844,16 @@ static u16 GetMulchAffectedGrowthRate(u16 berryDuration, u8 mulch, u8 stage) void BerryTreeTimeUpdate(s32 minutes) { int i; - u8 drainVal; + u32 drainVal; struct BerryTree *tree; for (i = 0; i < BERRY_TREES_COUNT; i++) { tree = &gSaveBlock1Ptr->berryTrees[i]; - if (tree->berry && tree->stage && !tree->stopGrowth) + if (tree->berry && tree->stage && !tree->stopGrowth && (!OW_BERRY_IMMORTAL || tree->stage != BERRY_STAGE_BERRIES)) { - if (minutes >= GetStageDurationByBerryType(tree->berry) * 71) + if ((!OW_BERRY_IMMORTAL) && (minutes >= GetStageDurationByBerryType(tree->berry) * 71)) { *tree = gBlankBerryTree; } diff --git a/src/clock.c b/src/clock.c index 7061f96b7f..54c9422bbe 100644 --- a/src/clock.c +++ b/src/clock.c @@ -84,7 +84,7 @@ static void FormChangeTimeUpdate() { struct Pokemon *mon = &gPlayerParty[i]; u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_TIME_OF_DAY, 0); - + if (targetSpecies != SPECIES_NONE) { SetMonData(mon, MON_DATA_SPECIES, &targetSpecies); diff --git a/src/data/battle_anim.h b/src/data/battle_anim.h index ec98ecd854..72a3c7121b 100644 --- a/src/data/battle_anim.h +++ b/src/data/battle_anim.h @@ -1461,6 +1461,10 @@ const struct CompressedSpriteSheet gBattleAnimPicTable[] = {gBattleAnimSpriteGfx_TeraCrystal, 0x800, ANIM_TAG_TERA_CRYSTAL}, {gBattleAnimSpriteGfx_TeraShatter, 0x0180, ANIM_TAG_TERA_SHATTER}, {gBattleAnimSpriteGfx_DreepyMissile, 0x200, ANIM_TAG_DREEPY_SHINY}, + {gBattleAnimSpriteGfx_BloodMoon, 0x0800, ANIM_TAG_BLOOD_MOON}, + {gBattleAnimSpriteGfx_RedExplosion, 0x0800, ANIM_TAG_RED_EXPLOSION}, + {gBattleAnimSpriteGfx_Beam, 0x0800, ANIM_TAG_BEAM}, + {gBattleAnimSpriteGfx_PurpleChain, 0x1000, ANIM_TAG_PURPLE_CHAIN}, }; const struct CompressedSpritePalette gBattleAnimPaletteTable[] = @@ -1923,6 +1927,10 @@ const struct CompressedSpritePalette gBattleAnimPaletteTable[] = {gBattleAnimSpritePal_TeraCrystal, ANIM_TAG_TERA_CRYSTAL}, {gBattleAnimSpritePal_TeraShatter, ANIM_TAG_TERA_SHATTER}, {gBattleAnimSpritePal_DreepyMissileShiny, ANIM_TAG_DREEPY_SHINY}, + {gBattleAnimSpritePal_BloodMoon, ANIM_TAG_BLOOD_MOON}, + {gBattleAnimSpritePal_RedExplosion, ANIM_TAG_RED_EXPLOSION}, + {gBattleAnimSpritePal_Beam, ANIM_TAG_BEAM}, + {gBattleAnimSpritePal_PurpleChain, ANIM_TAG_PURPLE_CHAIN}, }; const struct BattleAnimBackground gBattleAnimBackgroundTable[] = diff --git a/src/data/battle_move_effects.h b/src/data/battle_move_effects.h index f970f0e9f7..ead7cee6f1 100644 --- a/src/data/battle_move_effects.h +++ b/src/data/battle_move_effects.h @@ -2169,7 +2169,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_FICKLE_BEAM] = { - .battleScript = BattleScript_EffectHit, + .battleScript = BattleScript_EffectFickleBeam, .battleTvScore = 0, // TODO: Assign points }, diff --git a/src/data/gimmicks.h b/src/data/gimmicks.h index 95a233e3fe..5b06feddef 100644 --- a/src/data/gimmicks.h +++ b/src/data/gimmicks.h @@ -5,7 +5,7 @@ const struct GimmickInfo gGimmicksInfo[GIMMICKS_COUNT] = { [GIMMICK_NONE] = {0}, - [GIMMICK_MEGA] = + [GIMMICK_MEGA] = { .triggerSheet = &sSpriteSheet_MegaTrigger, .triggerPal = &sSpritePalette_MegaTrigger, @@ -15,7 +15,7 @@ const struct GimmickInfo gGimmicksInfo[GIMMICKS_COUNT] = .CanActivate = CanMegaEvolve, .ActivateGimmick = ActivateMegaEvolution, }, - [GIMMICK_Z_MOVE] = + [GIMMICK_Z_MOVE] = { .triggerSheet = &sSpriteSheet_ZMoveTrigger, .triggerPal = &sSpritePalette_ZMoveTrigger, @@ -23,7 +23,7 @@ const struct GimmickInfo gGimmicksInfo[GIMMICKS_COUNT] = .CanActivate = CanUseZMove, .ActivateGimmick = ActivateZMove, }, - [GIMMICK_ULTRA_BURST] = + [GIMMICK_ULTRA_BURST] = { .triggerSheet = &sSpriteSheet_BurstTrigger, .triggerPal = &sSpritePalette_BurstTrigger, @@ -31,7 +31,7 @@ const struct GimmickInfo gGimmicksInfo[GIMMICKS_COUNT] = .CanActivate = CanUltraBurst, .ActivateGimmick = ActivateUltraBurst, }, - [GIMMICK_DYNAMAX] = + [GIMMICK_DYNAMAX] = { .triggerSheet = &sSpriteSheet_DynamaxTrigger, .triggerPal = &sSpritePalette_DynamaxTrigger, diff --git a/src/data/items.h b/src/data/items.h index daf1f9b957..f97c4670c1 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -12243,7 +12243,7 @@ const struct Item gItemsInfo[] = [ITEM_DOWSING_MACHINE] = { - .name = _("Dowsing MCHN"), + .name = HANDLE_EXPANDED_ITEM_NAME("Dowsing MCHN", "Dowsing Machine"), .price = 0, .description = COMPOUND_STRING( "A device that\n" diff --git a/src/data/moves_info.h b/src/data/moves_info.h index bec17632ec..08579f274f 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -17470,7 +17470,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .name = COMPOUND_STRING("Decorate"), .description = COMPOUND_STRING( "The user sharply raises\n" - "the target's Atk and Sp.Atk"), + "the target's Atk and Sp.Atk."), .effect = EFFECT_DECORATE, .power = 0, .type = TYPE_FAIRY, @@ -19739,7 +19739,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .name = HANDLE_EXPANDED_MOVE_NAME("ColisinCours", "Collision Course"), .description = COMPOUND_STRING( "Prehistoric explosion that's\n" - "stronger if supereffective."), + "stronger if super effective."), .effect = EFFECT_COLLISION_COURSE, .power = 100, .type = TYPE_FIGHTING, @@ -19758,7 +19758,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .name = HANDLE_EXPANDED_MOVE_NAME("ElectroDrift", "Electro Drift"), .description = COMPOUND_STRING( "Futuristic electricity. It's\n" - "stronger if supereffective."), + "stronger if super effective."), .effect = EFFECT_COLLISION_COURSE, .power = 100, .type = TYPE_ELECTRIC, diff --git a/src/data/object_events/object_event_graphics_info_pointers.h b/src/data/object_events/object_event_graphics_info_pointers.h index 7f487a5ae5..60dc6997db 100755 --- a/src/data/object_events/object_event_graphics_info_pointers.h +++ b/src/data/object_events/object_event_graphics_info_pointers.h @@ -239,7 +239,7 @@ extern const struct ObjectEventGraphicsInfo gObjectEventGraphicsInfo_HoOh; // Begin pokemon event objects extern const struct ObjectEventGraphicsInfo gObjectEventGraphicsInfo_PokeBall; extern const struct ObjectEventGraphicsInfo gObjectEventGraphicsInfo_Follower; - + extern const struct ObjectEventGraphicsInfo gObjectEventGraphicsInfo_Bard; extern const struct ObjectEventGraphicsInfo gObjectEventGraphicsInfo_Hipster; extern const struct ObjectEventGraphicsInfo gObjectEventGraphicsInfo_Trader; diff --git a/src/data/party_menu.h b/src/data/party_menu.h index 99488d4ebe..841cedca88 100644 --- a/src/data/party_menu.h +++ b/src/data/party_menu.h @@ -1140,11 +1140,18 @@ static const u8 *const sUnused_StatStrings[] = gText_Speed2 }; +#define ROTOM_BASE_MOVE MOVE_THUNDER_SHOCK +#define ROTOM_HEAT_MOVE MOVE_OVERHEAT +#define ROTOM_WASH_MOVE MOVE_HYDRO_PUMP +#define ROTOM_FROST_MOVE MOVE_BLIZZARD +#define ROTOM_FAN_MOVE MOVE_AIR_SLASH +#define ROTOM_MOW_MOVE MOVE_LEAF_STORM + static const u16 sRotomFormChangeMoves[5] = { - MOVE_HYDRO_PUMP, - MOVE_BLIZZARD, - MOVE_OVERHEAT, - MOVE_AIR_SLASH, - MOVE_LEAF_STORM, + ROTOM_HEAT_MOVE, + ROTOM_WASH_MOVE, + ROTOM_FROST_MOVE, + ROTOM_FAN_MOVE, + ROTOM_MOW_MOVE, }; diff --git a/src/data/pokemon/species_info/gen_9_families.h b/src/data/pokemon/species_info/gen_9_families.h index 5a8452af25..66ae0b8dff 100644 --- a/src/data/pokemon/species_info/gen_9_families.h +++ b/src/data/pokemon/species_info/gen_9_families.h @@ -1765,7 +1765,7 @@ const struct SpeciesInfo gSpeciesInfoGen9[] = .trainerOffset = 0, .frontPic = gMonFrontPic_Naclstack, .frontPicSize = MON_COORDS_SIZE(64, 64), - .frontPicYOffset = 2, + .frontPicYOffset = 9, .frontAnimFrames = sAnims_Naclstack, //.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, .backPic = gMonBackPic_Naclstack, @@ -1818,12 +1818,12 @@ const struct SpeciesInfo gSpeciesInfoGen9[] = .trainerOffset = 0, .frontPic = gMonFrontPic_Garganacl, .frontPicSize = MON_COORDS_SIZE(64, 64), - .frontPicYOffset = 1, + .frontPicYOffset = 5, .frontAnimFrames = sAnims_Garganacl, //.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, .backPic = gMonBackPic_Garganacl, .backPicSize = MON_COORDS_SIZE(64, 64), - .backPicYOffset = 2, + .backPicYOffset = 14, //.backAnimId = BACK_ANIM_NONE, .palette = gMonPalette_Garganacl, .shinyPalette = gMonShinyPalette_Garganacl, diff --git a/src/data/types_info.h b/src/data/types_info.h index f9bd233ca6..df74199bdd 100644 --- a/src/data/types_info.h +++ b/src/data/types_info.h @@ -60,6 +60,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB_WHITE, .damageCategory = DAMAGE_CATEGORY_PHYSICAL, .paletteTMHM = gItemIconPalette_NormalTMHM, + .useSecondTypeIconPalette = FALSE, + .isSpecialCaseType = TRUE, }, [TYPE_NORMAL] = { @@ -71,6 +73,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB_WHITE, // custom .damageCategory = DAMAGE_CATEGORY_PHYSICAL, .paletteTMHM = gItemIconPalette_NormalTMHM, + .useSecondTypeIconPalette = FALSE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_SILK_SCARF, //.berry = ITEM_CHILAN_BERRY, //.gem = ITEM_NORMAL_GEM, @@ -88,6 +92,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(26, 8, 14), .damageCategory = DAMAGE_CATEGORY_PHYSICAL, .paletteTMHM = gItemIconPalette_FightingTMHM, + .useSecondTypeIconPalette = FALSE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_BLACK_BELT, //.berry = ITEM_CHOPLE_BERRY, //.gem = ITEM_FIGHTING_GEM, @@ -107,6 +113,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(31, 26, 7), .damageCategory = DAMAGE_CATEGORY_PHYSICAL, .paletteTMHM = gItemIconPalette_FlyingTMHM, + .useSecondTypeIconPalette = FALSE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_SHARP_BEAK, //.berry = ITEM_COBA_BERRY, //.gem = ITEM_FLYING_GEM, @@ -126,6 +134,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(26, 10, 25), // custom .damageCategory = DAMAGE_CATEGORY_PHYSICAL, .paletteTMHM = gItemIconPalette_PoisonTMHM, + .useSecondTypeIconPalette = FALSE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_POISON_BARB, //.berry = ITEM_KEBIA_BERRY, //.gem = ITEM_POISON_GEM, @@ -145,6 +155,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(25, 23, 18), .damageCategory = DAMAGE_CATEGORY_PHYSICAL, .paletteTMHM = gItemIconPalette_GroundTMHM, + .useSecondTypeIconPalette = FALSE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_SOFT_SAND, //.berry = ITEM_SHUCA_BERRY, //.gem = ITEM_GROUND_GEM, @@ -164,6 +176,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(18, 16, 8), // custom .damageCategory = DAMAGE_CATEGORY_PHYSICAL, .paletteTMHM = gItemIconPalette_RockTMHM, + .useSecondTypeIconPalette = FALSE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_HARD_STONE, //.berry = ITEM_CHARTI_BERRY, //.gem = ITEM_ROCK_GEM, @@ -183,6 +197,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(18, 24, 6), .damageCategory = DAMAGE_CATEGORY_PHYSICAL, .paletteTMHM = gItemIconPalette_BugTMHM, + .useSecondTypeIconPalette = FALSE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_SILVER_POWDER, //.berry = ITEM_TANGA_BERRY, //.gem = ITEM_BUG_GEM, @@ -202,6 +218,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(12, 10, 16), .damageCategory = DAMAGE_CATEGORY_PHYSICAL, .paletteTMHM = gItemIconPalette_GhostTMHM, + .useSecondTypeIconPalette = FALSE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_SPELL_TAG, //.berry = ITEM_KASIB_BERRY, //.gem = ITEM_GHOST_GEM, @@ -221,6 +239,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(19, 19, 20), .damageCategory = DAMAGE_CATEGORY_PHYSICAL, .paletteTMHM = gItemIconPalette_SteelTMHM, + .useSecondTypeIconPalette = FALSE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_METAL_COAT, //.berry = ITEM_BABIRI_BERRY, //.gem = ITEM_STEEL_GEM, @@ -237,6 +257,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .palette = 15, .teraTypeRGBValue = RGB_WHITE, .damageCategory = DAMAGE_CATEGORY_SPECIAL, + .useSecondTypeIconPalette = FALSE, + .isSpecialCaseType = TRUE, }, [TYPE_FIRE] = { @@ -248,6 +270,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(31, 20, 11), .damageCategory = DAMAGE_CATEGORY_SPECIAL, .paletteTMHM = gItemIconPalette_FireTMHM, + .useSecondTypeIconPalette = TRUE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_CHARCOAL, //.berry = ITEM_OCCA_BERRY, //.gem = ITEM_FIRE_GEM, @@ -267,6 +291,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(10, 18, 27), .damageCategory = DAMAGE_CATEGORY_SPECIAL, .paletteTMHM = gItemIconPalette_WaterTMHM, + .useSecondTypeIconPalette = TRUE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_MYSTIC_WATER, //.berry = ITEM_PASSHO_BERRY, //.gem = ITEM_WATER_GEM, @@ -286,6 +312,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(12, 24, 11), .damageCategory = DAMAGE_CATEGORY_SPECIAL, .paletteTMHM = gItemIconPalette_GrassTMHM, + .useSecondTypeIconPalette = TRUE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_MIRACLE_SEED, //.berry = ITEM_RINDO_BERRY, //.gem = ITEM_GRASS_GEM, @@ -305,6 +333,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(30, 26, 7), .damageCategory = DAMAGE_CATEGORY_SPECIAL, .paletteTMHM = gItemIconPalette_ElectricTMHM, + .useSecondTypeIconPalette = TRUE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_MAGNET, //.berry = ITEM_WACAN_BERRY, //.gem = ITEM_ELECTRIC_GEM, @@ -324,6 +354,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(31, 14, 15), .damageCategory = DAMAGE_CATEGORY_SPECIAL, .paletteTMHM = gItemIconPalette_PsychicTMHM, + .useSecondTypeIconPalette = TRUE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_TWISTED_SPOON, //.berry = ITEM_PAYAPA_BERRY, //.gem = ITEM_PSYCHIC_GEM, @@ -343,6 +375,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(14, 26, 25), .damageCategory = DAMAGE_CATEGORY_SPECIAL, .paletteTMHM = gItemIconPalette_IceTMHM, + .useSecondTypeIconPalette = TRUE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_NEVER_MELT_ICE, //.berry = ITEM_YACHE_BERRY, //.gem = ITEM_ICE_GEM, @@ -362,6 +396,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(10, 18, 27), .damageCategory = DAMAGE_CATEGORY_SPECIAL, .paletteTMHM = gItemIconPalette_DragonTMHM, + .useSecondTypeIconPalette = TRUE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_DRAGON_FANG, //.berry = ITEM_HABAN_BERRY, //.gem = ITEM_DRAGON_GEM, @@ -381,6 +417,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(6, 5, 8), .damageCategory = DAMAGE_CATEGORY_SPECIAL, .paletteTMHM = gItemIconPalette_DarkTMHM, + .useSecondTypeIconPalette = TRUE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_BLACK_GLASSES, //.berry = ITEM_COLBUR_BERRY, //.gem = ITEM_DARK_GEM, @@ -400,6 +438,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .teraTypeRGBValue = RGB(31, 15, 21), .damageCategory = DAMAGE_CATEGORY_SPECIAL, .paletteTMHM = gItemIconPalette_FairyTMHM, + .useSecondTypeIconPalette = TRUE, + .isSpecialCaseType = FALSE, //.enhanceItem = ITEM_FAIRY_FEATHER, //.berry = ITEM_ROSELI_BERRY, //.gem = ITEM_FAIRY_GEM, @@ -418,6 +458,8 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .maxMove = MOVE_MAX_STRIKE, .teraTypeRGBValue = RGB(10, 18, 27), .paletteTMHM = gItemIconPalette_NormalTMHM, // failsafe + .useSecondTypeIconPalette = FALSE, + .isSpecialCaseType = TRUE, // .teraShard = ITEM_STELLAR_TERA_SHARD, }, }; diff --git a/src/field_specials.c b/src/field_specials.c index d0d370c566..4081e83757 100644 --- a/src/field_specials.c +++ b/src/field_specials.c @@ -45,6 +45,7 @@ #include "strings.h" #include "task.h" #include "text.h" +#include "tilesets.h" #include "tv.h" #include "wallclock.h" #include "window.h" @@ -970,6 +971,20 @@ void FieldShowRegionMap(void) SetMainCallback2(CB2_FieldShowRegionMap); } +static bool32 IsBuildingPCTile(u32 tileId) +{ + return gMapHeader.mapLayout->primaryTileset == &gTileset_Building && (tileId == METATILE_Building_PC_On || tileId == METATILE_Building_PC_Off); +} + +static bool32 IsPlayerHousePCTile(u32 tileId) +{ + return gMapHeader.mapLayout->secondaryTileset == &gTileset_BrendansMaysHouse + && (tileId == METATILE_BrendansMaysHouse_BrendanPC_On + || tileId == METATILE_BrendansMaysHouse_BrendanPC_Off + || tileId == METATILE_BrendansMaysHouse_MayPC_On + || tileId == METATILE_BrendansMaysHouse_MayPC_Off); +} + static bool8 IsPlayerInFrontOfPC(void) { s16 x, y; @@ -978,12 +993,7 @@ static bool8 IsPlayerInFrontOfPC(void) GetXYCoordsOneStepInFrontOfPlayer(&x, &y); tileInFront = MapGridGetMetatileIdAt(x, y); - return (tileInFront == METATILE_BrendansMaysHouse_BrendanPC_On - || tileInFront == METATILE_BrendansMaysHouse_BrendanPC_Off - || tileInFront == METATILE_BrendansMaysHouse_MayPC_On - || tileInFront == METATILE_BrendansMaysHouse_MayPC_Off - || tileInFront == METATILE_Building_PC_On - || tileInFront == METATILE_Building_PC_Off); + return IsBuildingPCTile(tileInFront) || IsPlayerHousePCTile(tileInFront); } // Task data for Task_PCTurnOnEffect and Task_LotteryCornerComputerEffect diff --git a/src/fieldmap.c b/src/fieldmap.c index 30daae49ca..7c40c755c4 100644 --- a/src/fieldmap.c +++ b/src/fieldmap.c @@ -141,7 +141,7 @@ static void InitBackupMapLayoutConnections(struct MapHeader *mapHeader) for (i = 0; i < count; i++, connection++) { struct MapHeader const *cMap = GetMapHeaderFromConnection(connection); - u32 offset = connection->offset; + s32 offset = connection->offset; switch (connection->direction) { case CONNECTION_SOUTH: diff --git a/src/frontier_util.c b/src/frontier_util.c index ca8c76a0fd..7cadbf364b 100644 --- a/src/frontier_util.c +++ b/src/frontier_util.c @@ -49,6 +49,17 @@ struct FrontierBrainMon u16 moves[MAX_MON_MOVES]; }; +struct FrontierBrain +{ + u16 trainerId; + u8 objEventGfx; + u8 isFemale; + const u8 *lostTexts[2]; + const u8 *wonTexts[2]; + u16 battledBit[2]; + u8 streakAppearances[4]; +}; + // This file's functions. static void GetChallengeStatus(void); static void GetFrontierData(void); @@ -83,16 +94,74 @@ static void ShowPyramidResultsWindow(void); static void ShowLinkContestResultsWindow(void); static void CopyFrontierBrainText(bool8 playerWonText); -// const rom data -static const u8 sFrontierBrainStreakAppearances[NUM_FRONTIER_FACILITIES][4] = +#define FRONTIER_BRAIN_SPRITES(Brain) \ + .trainerId = TRAINER_##Brain, \ + .objEventGfx = OBJ_EVENT_GFX_##Brain + +#define FRONTIER_BRAIN_TEXTS(Brain) \ + .lostTexts = {gText_##Brain##DefeatSilver, gText_##Brain##DefeatGold}, \ + .wonTexts = {gText_##Brain##WonSilver, gText_##Brain##WonGold} + +// battledBit: Flags to change the conversation when the Frontier Brain is encountered for a battle +// First bit is has battled them before and not won yet, second bit is has battled them and won (obtained a Symbol) +const struct FrontierBrain gFrontierBrainInfo[NUM_FRONTIER_FACILITIES] = { - [FRONTIER_FACILITY_TOWER] = {35, 70, 35, 1}, - [FRONTIER_FACILITY_DOME] = { 4, 9, 5, 0}, - [FRONTIER_FACILITY_PALACE] = {21, 42, 21, 1}, - [FRONTIER_FACILITY_ARENA] = {28, 56, 28, 1}, - [FRONTIER_FACILITY_FACTORY] = {21, 42, 21, 1}, - [FRONTIER_FACILITY_PIKE] = {28, 140, 56, 1}, - [FRONTIER_FACILITY_PYRAMID] = {21, 70, 35, 0}, + [FRONTIER_FACILITY_TOWER] = + { + FRONTIER_BRAIN_SPRITES(ANABEL), + .isFemale = TRUE, + FRONTIER_BRAIN_TEXTS(Anabel), + .battledBit = {1 << 0, 1 << 1}, + .streakAppearances = {35, 70, 35, 1}, + }, + [FRONTIER_FACILITY_DOME] = + { + FRONTIER_BRAIN_SPRITES(TUCKER), + .isFemale = FALSE, + FRONTIER_BRAIN_TEXTS(Tucker), + .battledBit = {1 << 2, 1 << 3}, + .streakAppearances = {1, 2, 5, 0}, + }, + [FRONTIER_FACILITY_PALACE] = + { + FRONTIER_BRAIN_SPRITES(SPENSER), + .isFemale = FALSE, + FRONTIER_BRAIN_TEXTS(Spenser), + .battledBit = {1 << 4, 1 << 5}, + .streakAppearances = {21, 42, 21, 1}, + }, + [FRONTIER_FACILITY_ARENA] = + { + FRONTIER_BRAIN_SPRITES(GRETA), + .isFemale = TRUE, + FRONTIER_BRAIN_TEXTS(Greta), + .battledBit = {1 << 6, 1 << 7}, + .streakAppearances = {28, 56, 28, 1}, + }, + [FRONTIER_FACILITY_FACTORY] = + { + FRONTIER_BRAIN_SPRITES(NOLAND), + .isFemale = FALSE, + FRONTIER_BRAIN_TEXTS(Noland), + .battledBit = {1 << 8, 1 << 9}, + .streakAppearances = {21, 42, 21, 1}, + }, + [FRONTIER_FACILITY_PIKE] = + { + FRONTIER_BRAIN_SPRITES(LUCY), + .isFemale = TRUE, + FRONTIER_BRAIN_TEXTS(Lucy), + .battledBit = {1 << 10, 1 << 11}, + .streakAppearances = {28, 140, 56, 1}, + }, + [FRONTIER_FACILITY_PYRAMID] = + { + FRONTIER_BRAIN_SPRITES(BRANDON), + .isFemale = FALSE, + FRONTIER_BRAIN_TEXTS(Brandon), + .battledBit = {1 << 12, 1 << 13}, + .streakAppearances = {21, 70, 35, 0}, + }, }; static const struct FrontierBrainMon sFrontierBrainsMons[][2][FRONTIER_PARTY_SIZE] = @@ -537,20 +606,6 @@ static const u8 sBattlePointAwards[NUM_FRONTIER_FACILITIES][FRONTIER_MODE_COUNT] }, }; - -// Flags to change the conversation when the Frontier Brain is encountered for a battle -// First bit is has battled them before and not won yet, second bit is has battled them and won (obtained a Symbol) -static const u16 sBattledBrainBitFlags[NUM_FRONTIER_FACILITIES][2] = -{ - [FRONTIER_FACILITY_TOWER] = {1 << 0, 1 << 1}, - [FRONTIER_FACILITY_DOME] = {1 << 2, 1 << 3}, - [FRONTIER_FACILITY_PALACE] = {1 << 4, 1 << 5}, - [FRONTIER_FACILITY_ARENA] = {1 << 6, 1 << 7}, - [FRONTIER_FACILITY_FACTORY] = {1 << 8, 1 << 9}, - [FRONTIER_FACILITY_PIKE] = {1 << 10, 1 << 11}, - [FRONTIER_FACILITY_PYRAMID] = {1 << 12, 1 << 13}, -}; - static void (* const sFrontierUtilFuncs[])(void) = { [FRONTIER_UTIL_FUNC_GET_STATUS] = GetChallengeStatus, @@ -611,18 +666,6 @@ static const struct WindowTemplate sRankingHallRecordsWindowTemplate = .baseBlock = 1 }; -// Second field - whether the character is female. -static const u8 sFrontierBrainObjEventGfx[NUM_FRONTIER_FACILITIES][2] = -{ - [FRONTIER_FACILITY_TOWER] = {OBJ_EVENT_GFX_ANABEL, TRUE}, - [FRONTIER_FACILITY_DOME] = {OBJ_EVENT_GFX_TUCKER, FALSE}, - [FRONTIER_FACILITY_PALACE] = {OBJ_EVENT_GFX_SPENSER, FALSE}, - [FRONTIER_FACILITY_ARENA] = {OBJ_EVENT_GFX_GRETA, TRUE}, - [FRONTIER_FACILITY_FACTORY] = {OBJ_EVENT_GFX_NOLAND, FALSE}, - [FRONTIER_FACILITY_PIKE] = {OBJ_EVENT_GFX_LUCY, TRUE}, - [FRONTIER_FACILITY_PYRAMID] = {OBJ_EVENT_GFX_BRANDON, FALSE}, -}; - static const u8 *const sRecordsWindowChallengeTexts[][2] = { [RANKING_HALL_TOWER_SINGLES] = {gText_BattleTower2, gText_FacilitySingle}, @@ -657,73 +700,6 @@ static const u8 *const sHallFacilityToRecordsText[] = [RANKING_HALL_TOWER_LINK] = gText_FrontierFacilityWinStreak, }; -static const u16 sFrontierBrainTrainerIds[NUM_FRONTIER_FACILITIES] = -{ - [FRONTIER_FACILITY_TOWER] = TRAINER_ANABEL, - [FRONTIER_FACILITY_DOME] = TRAINER_TUCKER, - [FRONTIER_FACILITY_PALACE] = TRAINER_SPENSER, - [FRONTIER_FACILITY_ARENA] = TRAINER_GRETA, - [FRONTIER_FACILITY_FACTORY] = TRAINER_NOLAND, - [FRONTIER_FACILITY_PIKE] = TRAINER_LUCY, - [FRONTIER_FACILITY_PYRAMID] = TRAINER_BRANDON, -}; - -static const u8 *const sFrontierBrainPlayerLostSilverTexts[NUM_FRONTIER_FACILITIES] = -{ - [FRONTIER_FACILITY_TOWER] = gText_AnabelWonSilver, - [FRONTIER_FACILITY_DOME] = gText_TuckerWonSilver, - [FRONTIER_FACILITY_PALACE] = gText_SpenserWonSilver, - [FRONTIER_FACILITY_ARENA] = gText_GretaWonSilver, - [FRONTIER_FACILITY_FACTORY] = gText_NolandWonSilver, - [FRONTIER_FACILITY_PIKE] = gText_LucyWonSilver, - [FRONTIER_FACILITY_PYRAMID] = gText_BrandonWonSilver, -}; - -static const u8 *const sFrontierBrainPlayerWonSilverTexts[NUM_FRONTIER_FACILITIES] = -{ - [FRONTIER_FACILITY_TOWER] = gText_AnabelDefeatSilver, - [FRONTIER_FACILITY_DOME] = gText_TuckerDefeatSilver, - [FRONTIER_FACILITY_PALACE] = gText_SpenserDefeatSilver, - [FRONTIER_FACILITY_ARENA] = gText_GretaDefeatSilver, - [FRONTIER_FACILITY_FACTORY] = gText_NolandDefeatSilver, - [FRONTIER_FACILITY_PIKE] = gText_LucyDefeatSilver, - [FRONTIER_FACILITY_PYRAMID] = gText_BrandonDefeatSilver, -}; - -static const u8 *const sFrontierBrainPlayerLostGoldTexts[NUM_FRONTIER_FACILITIES] = -{ - [FRONTIER_FACILITY_TOWER] = gText_AnabelWonGold, - [FRONTIER_FACILITY_DOME] = gText_TuckerWonGold, - [FRONTIER_FACILITY_PALACE] = gText_SpenserWonGold, - [FRONTIER_FACILITY_ARENA] = gText_GretaWonGold, - [FRONTIER_FACILITY_FACTORY] = gText_NolandWonGold, - [FRONTIER_FACILITY_PIKE] = gText_LucyWonGold, - [FRONTIER_FACILITY_PYRAMID] = gText_BrandonWonGold, -}; - -static const u8 *const sFrontierBrainPlayerWonGoldTexts[NUM_FRONTIER_FACILITIES] = -{ - [FRONTIER_FACILITY_TOWER] = gText_AnabelDefeatGold, - [FRONTIER_FACILITY_DOME] = gText_TuckerDefeatGold, - [FRONTIER_FACILITY_PALACE] = gText_SpenserDefeatGold, - [FRONTIER_FACILITY_ARENA] = gText_GretaDefeatGold, - [FRONTIER_FACILITY_FACTORY] = gText_NolandDefeatGold, - [FRONTIER_FACILITY_PIKE] = gText_LucyDefeatGold, - [FRONTIER_FACILITY_PYRAMID] = gText_BrandonDefeatGold, -}; - -static const u8 *const *const sFrontierBrainPlayerLostTexts[] = -{ - sFrontierBrainPlayerLostSilverTexts, - sFrontierBrainPlayerLostGoldTexts, -}; - -static const u8 *const *const sFrontierBrainPlayerWonTexts[] = -{ - sFrontierBrainPlayerWonSilverTexts, - sFrontierBrainPlayerWonGoldTexts, -}; - // code void CallFrontierUtilFunc(void) { @@ -785,7 +761,7 @@ static void GetFrontierData(void) gSpecialVar_Result = gSaveBlock2Ptr->frontier.disableRecordBattle; break; case FRONTIER_DATA_HEARD_BRAIN_SPEECH: - gSpecialVar_Result = gSaveBlock2Ptr->frontier.battledBrainFlags & sBattledBrainBitFlags[facility][hasSymbol]; + gSpecialVar_Result = gSaveBlock2Ptr->frontier.battledBrainFlags & gFrontierBrainInfo[facility].battledBit[hasSymbol]; break; } } @@ -820,7 +796,7 @@ static void SetFrontierData(void) gSaveBlock2Ptr->frontier.disableRecordBattle = gSpecialVar_0x8006; break; case FRONTIER_DATA_HEARD_BRAIN_SPEECH: - gSaveBlock2Ptr->frontier.battledBrainFlags |= sBattledBrainBitFlags[facility][hasSymbol]; + gSaveBlock2Ptr->frontier.battledBrainFlags |= gFrontierBrainInfo[facility].battledBit[hasSymbol]; break; } } @@ -1600,7 +1576,7 @@ u8 GetFrontierBrainStatus(void) s32 facility = VarGet(VAR_FRONTIER_FACILITY); s32 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE); u16 winStreakNoModifier = GetCurrentFacilityWinStreak(); - s32 winStreak = winStreakNoModifier + sFrontierBrainStreakAppearances[facility][3]; + s32 winStreak = winStreakNoModifier + gFrontierBrainInfo[facility].streakAppearances[3]; s32 symbolsCount; if (battleMode != FRONTIER_MODE_SINGLES) @@ -1612,20 +1588,20 @@ u8 GetFrontierBrainStatus(void) // Missing a symbol case 0: case 1: - if (winStreak == sFrontierBrainStreakAppearances[facility][symbolsCount]) + if (winStreak == gFrontierBrainInfo[facility].streakAppearances[symbolsCount]) status = symbolsCount + 1; // FRONTIER_BRAIN_SILVER and FRONTIER_BRAIN_GOLD break; // Already received both symbols case 2: default: // Silver streak is reached - if (winStreak == sFrontierBrainStreakAppearances[facility][0]) + if (winStreak == gFrontierBrainInfo[facility].streakAppearances[0]) status = FRONTIER_BRAIN_STREAK; // Gold streak is reached - else if (winStreak == sFrontierBrainStreakAppearances[facility][1]) + else if (winStreak == gFrontierBrainInfo[facility].streakAppearances[1]) status = FRONTIER_BRAIN_STREAK_LONG; // Some increment of the gold streak is reached - else if (winStreak > sFrontierBrainStreakAppearances[facility][1] && (winStreak - sFrontierBrainStreakAppearances[facility][1]) % sFrontierBrainStreakAppearances[facility][2] == 0) + else if (winStreak > gFrontierBrainInfo[facility].streakAppearances[1] && (winStreak - gFrontierBrainInfo[facility].streakAppearances[1]) % gFrontierBrainInfo[facility].streakAppearances[2] == 0) status = FRONTIER_BRAIN_STREAK_LONG; break; } @@ -2396,7 +2372,7 @@ u8 GetFrontierBrainTrainerPicIndex(void) else facility = VarGet(VAR_FRONTIER_FACILITY); - return GetTrainerPicFromId(sFrontierBrainTrainerIds[facility]); + return GetTrainerPicFromId(gFrontierBrainInfo[facility].trainerId); } u8 GetFrontierBrainTrainerClass(void) @@ -2408,7 +2384,7 @@ u8 GetFrontierBrainTrainerClass(void) else facility = VarGet(VAR_FRONTIER_FACILITY); - return GetTrainerClassFromId(sFrontierBrainTrainerIds[facility]); + return GetTrainerClassFromId(gFrontierBrainInfo[facility].trainerId); } void CopyFrontierBrainTrainerName(u8 *dst) @@ -2422,7 +2398,7 @@ void CopyFrontierBrainTrainerName(u8 *dst) else facility = VarGet(VAR_FRONTIER_FACILITY); - trainerName = GetTrainerNameFromId(sFrontierBrainTrainerIds[facility]); + trainerName = GetTrainerNameFromId(gFrontierBrainInfo[facility].trainerId); for (i = 0; i < PLAYER_NAME_LENGTH; i++) dst[i] = trainerName[i]; @@ -2432,13 +2408,13 @@ void CopyFrontierBrainTrainerName(u8 *dst) bool8 IsFrontierBrainFemale(void) { s32 facility = VarGet(VAR_FRONTIER_FACILITY); - return sFrontierBrainObjEventGfx[facility][1]; + return gFrontierBrainInfo[facility].isFemale; } void SetFrontierBrainObjEventGfx_2(void) { s32 facility = VarGet(VAR_FRONTIER_FACILITY); - VarSet(VAR_OBJ_GFX_ID_0, sFrontierBrainObjEventGfx[facility][0]); + VarSet(VAR_OBJ_GFX_ID_0, gFrontierBrainInfo[facility].objEventGfx); } #define FRONTIER_BRAIN_OTID 61226 @@ -2505,7 +2481,7 @@ u16 GetFrontierBrainMonSpecies(u8 monId) void SetFrontierBrainObjEventGfx(u8 facility) { gTrainerBattleOpponent_A = TRAINER_FRONTIER_BRAIN; - VarSet(VAR_OBJ_GFX_ID_0, sFrontierBrainObjEventGfx[facility][0]); + VarSet(VAR_OBJ_GFX_ID_0, gFrontierBrainInfo[facility].objEventGfx); } u16 GetFrontierBrainMonMove(u8 monId, u8 moveSlotId) @@ -2540,12 +2516,12 @@ s32 GetFronterBrainSymbol(void) if (symbol == 2) { u16 winStreak = GetCurrentFacilityWinStreak(); - if (winStreak + sFrontierBrainStreakAppearances[facility][3] == sFrontierBrainStreakAppearances[facility][0]) + if (winStreak + gFrontierBrainInfo[facility].streakAppearances[3] == gFrontierBrainInfo[facility].streakAppearances[0]) symbol = 0; - else if (winStreak + sFrontierBrainStreakAppearances[facility][3] == sFrontierBrainStreakAppearances[facility][1]) + else if (winStreak + gFrontierBrainInfo[facility].streakAppearances[3] == gFrontierBrainInfo[facility].streakAppearances[1]) symbol = 1; - else if (winStreak + sFrontierBrainStreakAppearances[facility][3] > sFrontierBrainStreakAppearances[facility][1] - && (winStreak + sFrontierBrainStreakAppearances[facility][3] - sFrontierBrainStreakAppearances[facility][1]) % sFrontierBrainStreakAppearances[facility][2] == 0) + else if (winStreak + gFrontierBrainInfo[facility].streakAppearances[3] > gFrontierBrainInfo[facility].streakAppearances[1] + && (winStreak + gFrontierBrainInfo[facility].streakAppearances[3] - gFrontierBrainInfo[facility].streakAppearances[1]) % gFrontierBrainInfo[facility].streakAppearances[2] == 0) symbol = 1; } return symbol; @@ -2571,10 +2547,10 @@ static void CopyFrontierBrainText(bool8 playerWonText) switch (playerWonText) { case FALSE: - StringCopy(gStringVar4, sFrontierBrainPlayerLostTexts[symbol][facility]); + StringCopy(gStringVar4, gFrontierBrainInfo[facility].wonTexts[symbol]); break; case TRUE: - StringCopy(gStringVar4, sFrontierBrainPlayerWonTexts[symbol][facility]); + StringCopy(gStringVar4, gFrontierBrainInfo[facility].lostTexts[symbol]); break; } } diff --git a/src/graphics.c b/src/graphics.c index c35cec3467..8df7055bd8 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -81,6 +81,9 @@ const u32 gBattleAnimSpritePal_AvalancheRocks[] = INCBIN_U32("graphics/battle_an const u32 gBattleAnimSpriteGfx_NewPokeball[] = INCBIN_U32("graphics/battle_anims/sprites/baton_pass_ball.4bpp.lz"); const u32 gBattleAnimSpritePal_NewPokeball[] = INCBIN_U32("graphics/battle_anims/sprites/baton_pass_ball.gbapal.lz"); +const u32 gBattleAnimSpriteGfx_Beam[] = INCBIN_U32("graphics/battle_anims/sprites/beam.4bpp.lz"); +const u32 gBattleAnimSpritePal_Beam[] = INCBIN_U32("graphics/battle_anims/sprites/beam.gbapal.lz"); + const u32 gBattleAnimSpriteGfx_BerryEaten[] = INCBIN_U32("graphics/battle_anims/sprites/berry_eaten.4bpp.lz"); const u32 gBattleAnimSpritePal_BerryEaten[] = INCBIN_U32("graphics/battle_anims/sprites/berry_eaten.gbapal.lz"); @@ -93,6 +96,9 @@ const u32 gBattleAnimSpritePal_BigRock[] = INCBIN_U32("graphics/battle_anims/spr const u32 gBattleAnimSpriteGfx_BlacephalonHead[] = INCBIN_U32("graphics/battle_anims/sprites/blacephalon_head.4bpp.lz"); const u32 gBattleAnimSpritePal_BlacephalonHead[] = INCBIN_U32("graphics/battle_anims/sprites/blacephalon_head.gbapal.lz"); +const u32 gBattleAnimSpriteGfx_BloodMoon[] = INCBIN_U32("graphics/battle_anims/sprites/blood_moon.4bpp.lz"); +const u32 gBattleAnimSpritePal_BloodMoon[] = INCBIN_U32("graphics/battle_anims/sprites/blood_moon.gbapal.lz"); + const u32 gBattleAnimSpritePal_BlueFlare[] = INCBIN_U32("graphics/battle_anims/sprites/blue_flare.gbapal.lz"); const u32 gBattleAnimSpriteGfx_Branch[] = INCBIN_U32("graphics/battle_anims/sprites/branch.4bpp.lz"); @@ -233,12 +239,18 @@ const u32 gBattleAnimSpritePal_PoisonColumn[] = INCBIN_U32("graphics/battle_anim const u32 gBattleAnimSpriteGfx_PowerTrick[] = INCBIN_U32("graphics/battle_anims/sprites/power_trick.4bpp.lz"); const u32 gBattleAnimSpritePal_PowerTrick[] = INCBIN_U32("graphics/battle_anims/sprites/power_trick.gbapal.lz"); +const u32 gBattleAnimSpriteGfx_PurpleChain[] = INCBIN_U32("graphics/battle_anims/sprites/purple_chain.4bpp.lz"); +const u32 gBattleAnimSpritePal_PurpleChain[] = INCBIN_U32("graphics/battle_anims/sprites/purple_chain.gbapal.lz"); + const u32 gBattleAnimSpriteGfx_PurpleDrake[] = INCBIN_U32("graphics/battle_anims/sprites/purple_drake.4bpp.lz"); const u32 gBattleAnimSpritePal_PurpleDrake[] = INCBIN_U32("graphics/battle_anims/sprites/purple_drake.gbapal.lz"); const u32 gBattleAnimSpriteGfx_RazorShell[] = INCBIN_U32("graphics/battle_anims/sprites/razor_shell.4bpp.lz"); const u32 gBattleAnimSpritePal_RazorShell[] = INCBIN_U32("graphics/battle_anims/sprites/razor_shell.gbapal.lz"); +const u32 gBattleAnimSpriteGfx_RedExplosion[] = INCBIN_U32("graphics/battle_anims/sprites/red_explosion.4bpp.lz"); +const u32 gBattleAnimSpritePal_RedExplosion[] = INCBIN_U32("graphics/battle_anims/sprites/red_explosion.gbapal.lz"); + const u32 gBattleAnimSpriteGfx_RocksSmall[] = INCBIN_U32("graphics/battle_anims/sprites/rock_small.4bpp.lz"); const u32 gBattleAnimSpriteGfx_NewRocks[] = INCBIN_U32("graphics/battle_anims/sprites/rocks_new.4bpp.lz"); @@ -2048,3 +2060,9 @@ const u16 gFrontierPassCancelButtonHighlighted_Tilemap[] = INCBIN_U16("graphics/ const u16 gBerryCrush_Crusher_Pal[] = INCBIN_U16("graphics/berry_crush/crusher.gbapal"); const u32 gBerryCrush_Crusher_Gfx[] = INCBIN_U32("graphics/berry_crush/crusher.4bpp.lz"); const u32 gBerryCrush_TextWindows_Tilemap[] = INCBIN_U32("graphics/berry_crush/text_windows.bin.lz"); + +const u32 gBattleIcons_Gfx1[] = INCBIN_U32("graphics/types/battle_icons1.4bpp.lz"); +const u32 gBattleIcons_Gfx2[] = INCBIN_U32("graphics/types/battle_icons2.4bpp.lz"); +const u32 gBattleIcons_Pal1[] = INCBIN_U32("graphics/types/battle_icons1.gbapal.lz"); +const u32 gBattleIcons_Pal2[] = INCBIN_U32("graphics/types/battle_icons2.gbapal.lz"); + diff --git a/src/item_use.c b/src/item_use.c index 502612a184..fd74b7082b 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -430,46 +430,43 @@ static bool8 IsHiddenItemPresentAtCoords(const struct MapEvents *events, s16 x, static bool8 IsHiddenItemPresentInConnection(const struct MapConnection *connection, int x, int y) { + s16 connectionX, connectionY; + struct MapHeader const *const connectionHeader = GetMapHeaderFromConnection(connection); - u16 localX, localY; - u32 localOffset; - s32 localLength; - - struct MapHeader const *const mapHeader = GetMapHeaderFromConnection(connection); - +// To convert our x/y into coordinates that are relative to the connected map, we must: +// - Subtract the virtual offset used for the border buffer (MAP_OFFSET). +// - Subtract the horizontal offset between North/South connections, or the vertical offset for East/West +// - Account for map size. (0,0) is in the NW corner of our map, so when looking North/West we have to add the height/width of the connected map, +// and when looking South/East we have to subtract the height/width of our current map. +#define localX (x - MAP_OFFSET) +#define localY (y - MAP_OFFSET) switch (connection->direction) { - // same weird temp variable behavior seen in IsHiddenItemPresentAtCoords case CONNECTION_NORTH: - localOffset = connection->offset + MAP_OFFSET; - localX = x - localOffset; - localLength = mapHeader->mapLayout->height - MAP_OFFSET; - localY = localLength + y; // additions are reversed for some reason + connectionX = localX - connection->offset; + connectionY = connectionHeader->mapLayout->height + localY; break; case CONNECTION_SOUTH: - localOffset = connection->offset + MAP_OFFSET; - localX = x - localOffset; - localLength = gMapHeader.mapLayout->height + MAP_OFFSET; - localY = y - localLength; + connectionX = localX - connection->offset; + connectionY = localY - gMapHeader.mapLayout->height; break; case CONNECTION_WEST: - localLength = mapHeader->mapLayout->width - MAP_OFFSET; - localX = localLength + x; // additions are reversed for some reason - localOffset = connection->offset + MAP_OFFSET; - localY = y - localOffset; + connectionX = connectionHeader->mapLayout->width + localX; + connectionY = localY - connection->offset; break; case CONNECTION_EAST: - localLength = gMapHeader.mapLayout->width + MAP_OFFSET; - localX = x - localLength; - localOffset = connection->offset + MAP_OFFSET; - localY = y - localOffset; + connectionX = localX - gMapHeader.mapLayout->width; + connectionY = localY - connection->offset; break; default: return FALSE; } - return IsHiddenItemPresentAtCoords(mapHeader->events, localX, localY); + return IsHiddenItemPresentAtCoords(connectionHeader->events, connectionX, connectionY); } +#undef localX +#undef localY + static void CheckForHiddenItemsInMapConnection(u8 taskId) { s16 playerX, playerY; diff --git a/src/load_save.c b/src/load_save.c index ee8a6bd04c..a5f2693538 100644 --- a/src/load_save.c +++ b/src/load_save.c @@ -211,7 +211,7 @@ void SaveObjectEvents(void) gSaveBlock1Ptr->objectEvents[i].graphicsId = (graphicsId >> 8) | (graphicsId << 8); gSaveBlock1Ptr->objectEvents[i].spriteId = 127; // magic number // To avoid crash on vanilla, save follower as inactive - if (gObjectEvents[i].localId == OBJ_EVENT_ID_FOLLOWER) + if (gObjectEvents[i].localId == OBJ_EVENT_ID_FOLLOWER) gSaveBlock1Ptr->objectEvents[i].active = FALSE; } } diff --git a/src/main.c b/src/main.c index b0bba2f3f3..47907a0111 100644 --- a/src/main.c +++ b/src/main.c @@ -205,12 +205,9 @@ void SetMainCallback2(MainCallback callback) void StartTimer1(void) { - if (HQ_RANDOM) - { - REG_TM2CNT_L = 0; - REG_TM2CNT_H = TIMER_ENABLE | TIMER_COUNTUP; - } + REG_TM2CNT_L = 0; + REG_TM2CNT_H = TIMER_ENABLE | TIMER_COUNTUP; REG_TM1CNT_H = TIMER_ENABLE; } @@ -218,24 +215,12 @@ void SeedRngAndSetTrainerId(void) { u32 val; - if (HQ_RANDOM) - { - REG_TM1CNT_H = 0; - REG_TM2CNT_H = 0; - val = ((u32)REG_TM2CNT_L) << 16; - val |= REG_TM1CNT_L; - SeedRng(val); - sTrainerId = Random(); - } - else - { - // Do it exactly like it was originally done, including not stopping - // the timer beforehand. - val = REG_TM1CNT_L; - SeedRng((u16)val); - REG_TM1CNT_H = 0; - sTrainerId = val; - } + REG_TM1CNT_H = 0; + REG_TM2CNT_H = 0; + val = ((u32)REG_TM2CNT_L) << 16; + val |= REG_TM1CNT_L; + SeedRng(val); + sTrainerId = Random(); } u16 GetGeneratedTrainerIdLower(void) @@ -254,22 +239,16 @@ void EnableVCountIntrAtLine150(void) #ifdef BUGFIX static void SeedRngWithRtc(void) { - #if HQ_RANDOM == FALSE - u32 seed = RtcGetMinuteCount(); - seed = (seed >> 16) ^ (seed & 0xFFFF); - SeedRng(seed); - #else - #define BCD8(x) ((((x) >> 4) & 0xF) * 10 + ((x) & 0xF)) - u32 seconds; - struct SiiRtcInfo rtc; - RtcGetInfo(&rtc); - seconds = - ((HOURS_PER_DAY * RtcGetDayCount(&rtc) + BCD8(rtc.hour)) - * MINUTES_PER_HOUR + BCD8(rtc.minute)) - * SECONDS_PER_MINUTE + BCD8(rtc.second); - SeedRng(seconds); - #undef BCD8 - #endif + #define BCD8(x) ((((x) >> 4) & 0xF) * 10 + ((x) & 0xF)) + u32 seconds; + struct SiiRtcInfo rtc; + RtcGetInfo(&rtc); + seconds = + ((HOURS_PER_DAY * RtcGetDayCount(&rtc) + BCD8(rtc.hour)) + * MINUTES_PER_HOUR + BCD8(rtc.minute)) + * SECONDS_PER_MINUTE + BCD8(rtc.second); + SeedRng(seconds); + #undef BCD8 } #endif diff --git a/src/map_name_popup.c b/src/map_name_popup.c index 67a0d6373f..5cc1f3cfd5 100644 --- a/src/map_name_popup.c +++ b/src/map_name_popup.c @@ -550,7 +550,7 @@ static void ShowMapNamePopUpWindow(void) if (OW_POPUP_GENERATION == GEN_5) { AddTextPrinterParameterized(mapNamePopUpWindowId, FONT_SHORT, mapDisplayHeader, 8, 2, TEXT_SKIP_DRAW, NULL); - + if (OW_POPUP_BW_TIME_MODE != OW_POPUP_BW_TIME_NONE) { RtcCalcLocalTime(); @@ -622,7 +622,7 @@ static void LoadMapNamePopUpWindowBg(void) if (OW_POPUP_GENERATION == GEN_5) { popUpThemeId = sRegionMapSectionId_To_PopUpThemeIdMapping_BW[regionMapSectionId]; - switch (popUpThemeId) + switch (popUpThemeId) { // add additional gen 5-style pop-up themes as cases here case MAPPOPUP_THEME_BW_DEFAULT: diff --git a/src/party_menu.c b/src/party_menu.c index 5214ddc2be..5def34b3eb 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -1353,7 +1353,7 @@ static void DrawCancelConfirmButtons(void) bool8 IsMultiBattle(void) { - if (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_DOUBLE && gMain.inBattle) + if (gBattleTypeFlags & BATTLE_TYPE_MULTI && IsDoubleBattle() && gMain.inBattle) return TRUE; else return FALSE; @@ -6413,13 +6413,13 @@ static void Task_TryItemUseFormChange(u8 taskId) case 6: if (!IsPartyMenuTextPrinterActive()) { - if (gSpecialVar_ItemId == ITEM_ROTOM_CATALOG) //only for rotom currently + if (gSpecialVar_ItemId == ITEM_ROTOM_CATALOG) //only for Rotom currently { u32 i; for (i = 0; i < ARRAY_COUNT(sRotomFormChangeMoves); i++) DeleteMove(mon, sRotomFormChangeMoves[i]); - if (gSpecialVar_0x8000 == MOVE_THUNDER_SHOCK) + if (I_ROTOM_CATALOG_THUNDER_SHOCK < GEN_9 && gSpecialVar_0x8000 == ROTOM_BASE_MOVE) { if (!DoesMonHaveAnyMoves(mon)) FormChangeTeachMove(taskId, gSpecialVar_0x8000, gPartyMenu.slotId); @@ -6517,42 +6517,42 @@ bool32 TryMultichoiceFormChange(u8 taskId) static void CursorCb_CatalogBulb(u8 taskId) { gSpecialVar_Result = 0; - gSpecialVar_0x8000 = MOVE_THUNDER_SHOCK; + gSpecialVar_0x8000 = ROTOM_BASE_MOVE; TryMultichoiceFormChange(taskId); } static void CursorCb_CatalogOven(u8 taskId) { gSpecialVar_Result = 1; - gSpecialVar_0x8000 = MOVE_OVERHEAT; + gSpecialVar_0x8000 = ROTOM_HEAT_MOVE; TryMultichoiceFormChange(taskId); } static void CursorCb_CatalogWashing(u8 taskId) { gSpecialVar_Result = 2; - gSpecialVar_0x8000 = MOVE_HYDRO_PUMP; + gSpecialVar_0x8000 = ROTOM_WASH_MOVE; TryMultichoiceFormChange(taskId); } static void CursorCb_CatalogFridge(u8 taskId) { gSpecialVar_Result = 3; - gSpecialVar_0x8000 = MOVE_BLIZZARD; + gSpecialVar_0x8000 = ROTOM_FROST_MOVE; TryMultichoiceFormChange(taskId); } static void CursorCb_CatalogFan(u8 taskId) { gSpecialVar_Result = 4; - gSpecialVar_0x8000 = MOVE_AIR_SLASH; + gSpecialVar_0x8000 = ROTOM_FAN_MOVE; TryMultichoiceFormChange(taskId); } static void CursorCb_CatalogMower(u8 taskId) { gSpecialVar_Result = 5; - gSpecialVar_0x8000 = MOVE_LEAF_STORM; + gSpecialVar_0x8000 = ROTOM_MOW_MOVE; TryMultichoiceFormChange(taskId); } diff --git a/src/pokemon.c b/src/pokemon.c index 04bdfc9046..718ce00c65 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -2080,14 +2080,14 @@ u8 CountAliveMonsInBattle(u8 caseId, u32 battler) case BATTLE_ALIVE_EXCEPT_BATTLER: for (i = 0; i < MAX_BATTLERS_COUNT; i++) { - if (i != battler && !(gAbsentBattlerFlags & gBitTable[i])) + if (i != battler && !(gAbsentBattlerFlags & (1u << i))) retVal++; } break; case BATTLE_ALIVE_SIDE: for (i = 0; i < MAX_BATTLERS_COUNT; i++) { - if (GetBattlerSide(i) == GetBattlerSide(battler) && !(gAbsentBattlerFlags & gBitTable[i])) + if (GetBattlerSide(i) == GetBattlerSide(battler) && !(gAbsentBattlerFlags & (1u << i))) retVal++; } break; @@ -2100,7 +2100,7 @@ u8 GetDefaultMoveTarget(u8 battlerId) { u8 opposing = BATTLE_OPPOSITE(GetBattlerSide(battlerId)); - if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + if (!IsDoubleBattle()) return GetBattlerAtPosition(opposing); if (CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER, battlerId) > 1) { @@ -2115,7 +2115,7 @@ u8 GetDefaultMoveTarget(u8 battlerId) } else { - if ((gAbsentBattlerFlags & gBitTable[opposing])) + if ((gAbsentBattlerFlags & (1u << opposing))) return GetBattlerAtPosition(BATTLE_PARTNER(opposing)); else return GetBattlerAtPosition(opposing); @@ -2691,7 +2691,7 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) || substruct1->move2 == move || substruct1->move3 == move || substruct1->move4 == move) - retVal |= gBitTable[i]; + retVal |= (1u << i); i++; } } @@ -5316,7 +5316,7 @@ void RandomlyGivePartyPokerus(struct Pokemon *party) } while (!GetMonData(mon, MON_DATA_SPECIES, 0) || GetMonData(mon, MON_DATA_IS_EGG, 0)); - if (!(CheckPartyHasHadPokerus(party, gBitTable[rnd]))) + if (!(CheckPartyHasHadPokerus(party, 1u << rnd))) { u8 rnd2; @@ -6651,9 +6651,9 @@ void TrySpecialOverworldEvo(void) for (i = 0; i < PARTY_SIZE; i++) { u16 targetSpecies = GetEvolutionTargetSpecies(&gPlayerParty[i], EVO_MODE_OVERWORLD_SPECIAL, evoMethod, SPECIES_NONE); - if (targetSpecies != SPECIES_NONE && !(sTriedEvolving & gBitTable[i])) + if (targetSpecies != SPECIES_NONE && !(sTriedEvolving & (1u << i))) { - sTriedEvolving |= gBitTable[i]; + sTriedEvolving |= 1u << i; if(gMain.callback2 == TrySpecialOverworldEvo) // This fixes small graphics glitches. EvolutionScene(&gPlayerParty[i], targetSpecies, canStopEvo, i); else @@ -6929,7 +6929,26 @@ void UpdateDaysPassedSinceFormChange(u16 days) } } -u8 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler) +static inline u32 CalculateHiddenPowerType(struct Pokemon *mon) +{ + u32 typehp; + u32 type; + u8 typeBits = ((GetMonData(mon, MON_DATA_HP_IV) & 1) << 0) + | ((GetMonData(mon, MON_DATA_ATK_IV) & 1) << 1) + | ((GetMonData(mon, MON_DATA_DEF_IV) & 1) << 2) + | ((GetMonData(mon, MON_DATA_SPEED_IV) & 1) << 3) + | ((GetMonData(mon, MON_DATA_SPATK_IV) & 1) << 4) + | ((GetMonData(mon, MON_DATA_SPDEF_IV) & 1) << 5); + + type = (15 * typeBits) / 63 + 2; + if (type >= TYPE_MYSTERY) + type++; + type |= 0xC0; + typehp = type & 0x3F; + return typehp; +} + +u32 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler) { u32 type = gMovesInfo[move].type; u32 species = GetMonData(mon, MON_DATA_SPECIES); @@ -6938,11 +6957,12 @@ u8 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler) u32 ability = GetMonAbility(mon); u32 type1 = gSpeciesInfo[species].types[0]; u32 type2 = gSpeciesInfo[species].types[1]; + u32 effect = gMovesInfo[move].effect; - if (move == MOVE_IVY_CUDGEL - && (species == SPECIES_OGERPON_WELLSPRING_MASK || species == SPECIES_OGERPON_WELLSPRING_MASK_TERA - || species == SPECIES_OGERPON_HEARTHFLAME_MASK || species == SPECIES_OGERPON_HEARTHFLAME_MASK_TERA - || species == SPECIES_OGERPON_CORNERSTONE_MASK || species == SPECIES_OGERPON_CORNERSTONE_MASK_TERA)) + if (effect == EFFECT_IVY_CUDGEL + && (species == SPECIES_OGERPON_WELLSPRING_MASK || species == SPECIES_OGERPON_WELLSPRING_MASK_TERA + || species == SPECIES_OGERPON_HEARTHFLAME_MASK || species == SPECIES_OGERPON_HEARTHFLAME_MASK_TERA + || species == SPECIES_OGERPON_CORNERSTONE_MASK || species == SPECIES_OGERPON_CORNERSTONE_MASK_TERA)) { type = type2; } @@ -6950,11 +6970,11 @@ u8 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler) { return TYPE_NORMAL; } - else if (move == MOVE_TERA_BLAST && GetActiveGimmick(battler) == GIMMICK_TERA && gBattleMons[battler].species == species) + else if (effect == EFFECT_TERA_BLAST && GetActiveGimmick(battler) == GIMMICK_TERA && gBattleMons[battler].species == species) { return GetMonData(mon, MON_DATA_TERA_TYPE); } - else if (move == MOVE_TERA_STARSTORM && species == SPECIES_TERAPAGOS_STELLAR) + else if (effect == EFFECT_TERA_STARSTORM && species == SPECIES_TERAPAGOS_STELLAR) { return TYPE_STELLAR; } @@ -6962,39 +6982,39 @@ u8 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler) { return CalculateHiddenPowerType(mon); } - else if (move == MOVE_AURA_WHEEL && species == SPECIES_MORPEKO_HANGRY) + else if (effect == EFFECT_AURA_WHEEL && species == SPECIES_MORPEKO_HANGRY) { type = TYPE_DARK; } - else if (gMovesInfo[move].effect == EFFECT_CHANGE_TYPE_ON_ITEM) + else if (effect == EFFECT_CHANGE_TYPE_ON_ITEM) { if (heldItemEffect == gMovesInfo[move].argument) return ItemId_GetSecondaryId(heldItem); else return TYPE_NORMAL; } - else if (move == MOVE_NATURAL_GIFT) + else if (effect == EFFECT_NATURAL_GIFT) { if (ItemId_GetPocket(heldItem) == POCKET_BERRIES) return gNaturalGiftTable[ITEM_TO_BERRY(heldItem)].type; else return TYPE_NORMAL; } - else if (move == MOVE_RAGING_BULL - && (species == SPECIES_TAUROS_PALDEAN_COMBAT_BREED - || species == SPECIES_TAUROS_PALDEAN_BLAZE_BREED - || species == SPECIES_TAUROS_PALDEAN_AQUA_BREED)) + else if (effect == EFFECT_RAGING_BULL + && (species == SPECIES_TAUROS_PALDEAN_COMBAT_BREED + || species == SPECIES_TAUROS_PALDEAN_BLAZE_BREED + || species == SPECIES_TAUROS_PALDEAN_AQUA_BREED)) { return type2; - } - else if (move == MOVE_REVELATION_DANCE) + } + else if (effect == EFFECT_REVELATION_DANCE) { if (gBattleMons[battler].species != species && type1 != TYPE_MYSTERY) type = type1; else if (gBattleMons[battler].species != species && type2 != TYPE_MYSTERY) type = type2; else if (GetBattlerTeraType(battler) != TYPE_STELLAR && (GetActiveGimmick(battler) == GIMMICK_TERA || IsGimmickSelected(battler, GIMMICK_TERA))) - type = GetMonData(mon, MON_DATA_TERA_TYPE); + type = GetMonData(mon, MON_DATA_TERA_TYPE); else if (gBattleMons[battler].types[0] != TYPE_MYSTERY) type = gBattleMons[battler].types[0]; else if (gBattleMons[battler].types[1] != TYPE_MYSTERY) @@ -7002,34 +7022,78 @@ u8 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler) else if (gBattleMons[battler].types[2] != TYPE_MYSTERY) type = gBattleMons[battler].types[2]; } - else if (gMovesInfo[move].effect == EFFECT_TERRAIN_PULSE - && ((IsMonGrounded(heldItemEffect, ability, type1, type2) && gBattleMons[battler].species != species) + else if (effect == EFFECT_TERRAIN_PULSE + && ((IsMonGrounded(heldItemEffect, ability, type1, type2) && gBattleMons[battler].species != species) || (IsBattlerTerrainAffected(battler, STATUS_FIELD_TERRAIN_ANY) && gBattleMons[battler].species == species))) - { - if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) - return TYPE_ELECTRIC; - else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) - return TYPE_GRASS; - else if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) - return TYPE_FAIRY; - else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) - return TYPE_PSYCHIC; - else //failsafe - type = TYPE_NORMAL; + { + if (gMain.inBattle) + { + if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) + return TYPE_ELECTRIC; + else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) + return TYPE_GRASS; + else if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + return TYPE_FAIRY; + else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) + return TYPE_PSYCHIC; + else //failsafe + type = TYPE_NORMAL; + } + else + { + switch (gWeatherPtr->currWeather) + { + case WEATHER_RAIN_THUNDERSTORM: + if (B_THUNDERSTORM_TERRAIN) + return TYPE_ELECTRIC; + break; + case WEATHER_FOG_HORIZONTAL: + case WEATHER_FOG_DIAGONAL: + if (B_OVERWORLD_FOG >= GEN_8) + return TYPE_FAIRY; + break; + } + return TYPE_NORMAL; + } } - if (gMovesInfo[move].effect == EFFECT_WEATHER_BALL && WEATHER_HAS_EFFECT) + if (effect == EFFECT_WEATHER_BALL) { - if (gBattleWeather & B_WEATHER_RAIN && heldItemEffect != HOLD_EFFECT_UTILITY_UMBRELLA) - return TYPE_WATER; - else if (gBattleWeather & B_WEATHER_SANDSTORM) - return TYPE_ROCK; - else if (gBattleWeather & B_WEATHER_SUN && heldItemEffect != HOLD_EFFECT_UTILITY_UMBRELLA) - return TYPE_FIRE; - else if (gBattleWeather & (B_WEATHER_SNOW | B_WEATHER_HAIL)) - return TYPE_ICE; + if (gMain.inBattle && WEATHER_HAS_EFFECT) + { + if (gBattleWeather & B_WEATHER_RAIN && heldItemEffect != HOLD_EFFECT_UTILITY_UMBRELLA) + return TYPE_WATER; + else if (gBattleWeather & B_WEATHER_SANDSTORM) + return TYPE_ROCK; + else if (gBattleWeather & B_WEATHER_SUN && heldItemEffect != HOLD_EFFECT_UTILITY_UMBRELLA) + return TYPE_FIRE; + else if (gBattleWeather & (B_WEATHER_SNOW | B_WEATHER_HAIL)) + return TYPE_ICE; + else + return TYPE_NORMAL; + } else + { + switch (gWeatherPtr->currWeather) + { + case WEATHER_DROUGHT: + if (heldItem != ITEM_UTILITY_UMBRELLA) + return TYPE_FIRE; + break; + case WEATHER_RAIN: + case WEATHER_RAIN_THUNDERSTORM: + if (heldItem != ITEM_UTILITY_UMBRELLA) + return TYPE_WATER; + break; + case WEATHER_SNOW: + return TYPE_ICE; + break; + case WEATHER_SANDSTORM: + return TYPE_ROCK; + break; + } return TYPE_NORMAL; + } } if (ability == ABILITY_NORMALIZE && gMovesInfo[move].type != TYPE_NORMAL && GetActiveGimmick(battler) != GIMMICK_Z_MOVE) @@ -7055,22 +7119,3 @@ u8 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler) return type; } - -u8 CalculateHiddenPowerType(struct Pokemon *mon) -{ - u32 typehp; - u32 type; - u8 typeBits = ((GetMonData(mon, MON_DATA_HP_IV) & 1) << 0) - | ((GetMonData(mon, MON_DATA_ATK_IV) & 1) << 1) - | ((GetMonData(mon, MON_DATA_DEF_IV) & 1) << 2) - | ((GetMonData(mon, MON_DATA_SPEED_IV) & 1) << 3) - | ((GetMonData(mon, MON_DATA_SPATK_IV) & 1) << 4) - | ((GetMonData(mon, MON_DATA_SPDEF_IV) & 1) << 5); - - type = (15 * typeBits) / 63 + 2; - if (type >= TYPE_MYSTERY) - type++; - type |= 0xC0; - typehp = type & 0x3F; - return typehp; -} diff --git a/src/pokemon_storage_system.c b/src/pokemon_storage_system.c index fe65df0114..6c9c53fd7f 100644 --- a/src/pokemon_storage_system.c +++ b/src/pokemon_storage_system.c @@ -1998,7 +1998,10 @@ static void VBlankCB_PokeStorage(void) ProcessSpriteCopyRequests(); UnkUtil_Run(); TransferPlttBuffer(); - SetGpuReg(REG_OFFSET_BG2HOFS, sStorage->bg2_X); + if (sStorage != NULL) + { + SetGpuReg(REG_OFFSET_BG2HOFS, sStorage->bg2_X); + } } static void CB2_PokeStorage(void) @@ -4206,11 +4209,14 @@ static void StopFlashingCloseBoxButton(void) static void UpdateCloseBoxButtonFlash(void) { - if (sStorage->closeBoxFlashing && ++sStorage->closeBoxFlashTimer > 30) + if (sStorage != NULL) { - sStorage->closeBoxFlashTimer = 0; - sStorage->closeBoxFlashState = (sStorage->closeBoxFlashState == FALSE); - UpdateCloseBoxButtonTilemap(sStorage->closeBoxFlashState); + if (sStorage->closeBoxFlashing && ++sStorage->closeBoxFlashTimer > 30) + { + sStorage->closeBoxFlashTimer = 0; + sStorage->closeBoxFlashState = (sStorage->closeBoxFlashState == FALSE); + UpdateCloseBoxButtonTilemap(sStorage->closeBoxFlashState); + } } } diff --git a/src/pokenav_conditions_gfx.c b/src/pokenav_conditions_gfx.c index 26d8e99e06..8845307c0e 100644 --- a/src/pokenav_conditions_gfx.c +++ b/src/pokenav_conditions_gfx.c @@ -30,6 +30,8 @@ static const u32 sConditionGraphData_Gfx[] = INCBIN_U32("graphics/pokenav/condit static const u32 sConditionGraphData_Tilemap[] = INCBIN_U32("graphics/pokenav/condition/graph_data.bin.lz"); static const u16 sMonMarkings_Pal[] = INCBIN_U16("graphics/pokenav/condition/mon_markings.gbapal"); +static const u8 gText_Number2[] = _("No. "); + static const struct BgTemplate sMenuBgTemplates[3] = { { diff --git a/src/pokenav_conditions_search_results.c b/src/pokenav_conditions_search_results.c index 9afb2bb2d9..4889dd788c 100644 --- a/src/pokenav_conditions_search_results.c +++ b/src/pokenav_conditions_search_results.c @@ -22,6 +22,8 @@ enum CONDITION_SEARCH_FUNC_SELECT_MON, }; +static const u8 gText_NumberIndex[] = _("No. {DYNAMIC 0}"); + struct Pokenav_SearchResults { u32 (*callback)(struct Pokenav_SearchResults *); diff --git a/src/pokenav_list.c b/src/pokenav_list.c index ed3d40dee2..dbcf137331 100644 --- a/src/pokenav_list.c +++ b/src/pokenav_list.c @@ -96,6 +96,10 @@ static u32 LoopedTask_PrintCheckPageInfo(s32); static const u16 sListArrow_Pal[] = INCBIN_U16("graphics/pokenav/list_arrows.gbapal"); static const u32 sListArrow_Gfx[] = INCBIN_U32("graphics/pokenav/list_arrows.4bpp.lz"); +static const u8 gText_PokenavMatchCall_Strategy[] = _("STRATEGY"); +static const u8 gText_PokenavMatchCall_TrainerPokemon[] = _("TRAINER'S POKéMON"); +static const u8 gText_PokenavMatchCall_SelfIntroduction[] = _("SELF-INTRODUCTION"); + static EWRAM_DATA u32 sMoveWindowDownIndex = 0; // Read, but pointlessly bool32 CreatePokenavList(const struct BgTemplate *bgTemplate, struct PokenavListTemplate *listTemplate, s32 tileOffset) diff --git a/src/pokenav_main_menu.c b/src/pokenav_main_menu.c index 761f572d6b..dfd656833d 100644 --- a/src/pokenav_main_menu.c +++ b/src/pokenav_main_menu.c @@ -86,18 +86,18 @@ static const struct WindowTemplate sHelpBarWindowTemplate[] = static const u8 *const sHelpBarTexts[HELPBAR_COUNT] = { - [HELPBAR_NONE] = gText_Pokenav_ClearButtonList, - [HELPBAR_MAP_ZOOMED_OUT] = gText_PokenavMap_ZoomedOutButtons, - [HELPBAR_MAP_ZOOMED_IN] = gText_PokenavMap_ZoomedInButtons, - [HELPBAR_CONDITION_MON_LIST] = gText_PokenavCondition_MonListButtons, - [HELPBAR_CONDITION_MON_STATUS] = gText_PokenavCondition_MonStatusButtons, - [HELPBAR_CONDITION_MARKINGS] = gText_PokenavCondition_MarkingButtons, - [HELPBAR_MC_TRAINER_LIST] = gText_PokenavMatchCall_TrainerListButtons, - [HELPBAR_MC_CALL_MENU] = gText_PokenavMatchCall_CallMenuButtons, - [HELPBAR_MC_CHECK_PAGE] = gText_PokenavMatchCall_CheckTrainerButtons, - [HELPBAR_RIBBONS_MON_LIST] = gText_PokenavRibbons_MonListButtons, - [HELPBAR_RIBBONS_LIST] = gText_PokenavRibbons_RibbonListButtons, - [HELPBAR_RIBBONS_CHECK] = gText_PokenavRibbons_RibbonCheckButtons, + [HELPBAR_NONE] = COMPOUND_STRING("{CLEAR 0x80}"), + [HELPBAR_MAP_ZOOMED_OUT] = COMPOUND_STRING("{A_BUTTON}ZOOM {B_BUTTON}CANCEL"), + [HELPBAR_MAP_ZOOMED_IN] = COMPOUND_STRING("{A_BUTTON}FULL {B_BUTTON}CANCEL"), + [HELPBAR_CONDITION_MON_LIST] = COMPOUND_STRING("{A_BUTTON}CONDITION {B_BUTTON}CANCEL"), + [HELPBAR_CONDITION_MON_STATUS] = COMPOUND_STRING("{A_BUTTON}MARKINGS {B_BUTTON}CANCEL"), + [HELPBAR_CONDITION_MARKINGS] = COMPOUND_STRING("{A_BUTTON}SELECT MARK {B_BUTTON}CANCEL"), + [HELPBAR_MC_TRAINER_LIST] = COMPOUND_STRING("{A_BUTTON}MENU {B_BUTTON}CANCEL"), + [HELPBAR_MC_CALL_MENU] = COMPOUND_STRING("{A_BUTTON}OK {B_BUTTON}CANCEL"), + [HELPBAR_MC_CHECK_PAGE] = COMPOUND_STRING("{B_BUTTON}CANCEL"), + [HELPBAR_RIBBONS_MON_LIST] = COMPOUND_STRING("{A_BUTTON}RIBBONS {B_BUTTON}CANCEL"), + [HELPBAR_RIBBONS_LIST] = COMPOUND_STRING("{A_BUTTON}CHECK {B_BUTTON}CANCEL"), + [HELPBAR_RIBBONS_CHECK] = COMPOUND_STRING("{B_BUTTON}CANCEL"), }; static const u8 sHelpBarTextColors[3] = diff --git a/src/pokenav_match_call_data.c b/src/pokenav_match_call_data.c index ca027380d4..a2cf3f93c4 100644 --- a/src/pokenav_match_call_data.c +++ b/src/pokenav_match_call_data.c @@ -179,8 +179,8 @@ static const struct MatchCallStructNPC sMrStoneMatchCallHeader = .type = MC_TYPE_NPC, .mapSec = MAPSEC_RUSTBORO_CITY, .flag = 0xFFFF, - .desc = gText_MrStoneMatchCallDesc, - .name = gText_MrStoneMatchCallName, + .desc = COMPOUND_STRING("DEVON PRES"), + .name = COMPOUND_STRING("MR. STONE"), .textData = sMrStoneTextScripts }; @@ -203,8 +203,8 @@ static const struct MatchCallStructTrainer sNormanMatchCallHeader = .mapSec = MAPSEC_PETALBURG_CITY, .flag = FLAG_ENABLE_NORMAN_MATCH_CALL, .rematchTableIdx = REMATCH_NORMAN, - .desc = gText_NormanMatchCallDesc, - .name = gText_NormanMatchCallName, + .desc = COMPOUND_STRING("RELIABLE ONE"), + .name = COMPOUND_STRING("DAD"), .textData = sNormanTextScripts }; @@ -213,8 +213,8 @@ static const struct MatchCallBirch sProfBirchMatchCallHeader = .type = MC_TYPE_BIRCH, .mapSec = 0, .flag = FLAG_ENABLE_PROF_BIRCH_MATCH_CALL, - .desc = gText_ProfBirchMatchCallDesc, - .name = gText_ProfBirchMatchCallName + .desc = COMPOUND_STRING("{PKMN} PROF."), + .name = COMPOUND_STRING("PROF. BIRCH") }; static const match_call_text_data_t sMomTextScripts[] = { @@ -229,8 +229,8 @@ static const struct MatchCallStructNPC sMomMatchCallHeader = .type = MC_TYPE_NPC, .mapSec = MAPSEC_LITTLEROOT_TOWN, .flag = FLAG_ENABLE_MOM_MATCH_CALL, - .desc = gText_MomMatchCallDesc, - .name = gText_MomMatchCallName, + .desc = COMPOUND_STRING("CALM & KIND"), + .name = COMPOUND_STRING("MOM"), .textData = sMomTextScripts }; @@ -250,11 +250,13 @@ static const struct MatchCallStructNPC sStevenMatchCallHeader = .type = MC_TYPE_NPC, .mapSec = MAPSEC_NONE, .flag = FLAG_REGISTERED_STEVEN_POKENAV, - .desc = gText_StevenMatchCallDesc, - .name = gText_StevenMatchCallName, + .desc = COMPOUND_STRING("HARD AS ROCK"), + .name = COMPOUND_STRING("STEVEN"), .textData = sStevenTextScripts }; +static const u8 gText_MayBrendanMatchCallDesc[] = _("RAD NEIGHBOR"); + static const match_call_text_data_t sMayTextScripts[] = { { MatchCall_Text_May1, 0xFFFF, 0xFFFF }, { MatchCall_Text_May2, FLAG_DEFEATED_DEWFORD_GYM, 0xFFFF }, @@ -337,7 +339,7 @@ static const struct MatchCallWally sWallyMatchCallHeader = .mapSec = 0, .flag = FLAG_ENABLE_WALLY_MATCH_CALL, .rematchTableIdx = REMATCH_WALLY_VR, - .desc = gText_WallyMatchCallDesc, + .desc = COMPOUND_STRING("{PKMN} LOVER"), .textData = sWallyTextScripts, .locationData = sWallyLocationData }; @@ -359,8 +361,8 @@ static const struct MatchCallStructNPC sScottMatchCallHeader = .type = 0, .mapSec = MAPSEC_NONE, .flag = FLAG_ENABLE_SCOTT_MATCH_CALL, - .desc = gText_ScottMatchCallDesc, - .name = gText_ScottMatchCallName, + .desc = COMPOUND_STRING("ELUSIVE EYES"), + .name = COMPOUND_STRING("SCOTT"), .textData = sScottTextScripts }; @@ -378,7 +380,7 @@ static const struct MatchCallStructTrainer sRoxanneMatchCallHeader = .mapSec = MAPSEC_RUSTBORO_CITY, .flag = FLAG_ENABLE_ROXANNE_MATCH_CALL, .rematchTableIdx = REMATCH_ROXANNE, - .desc = gText_RoxanneMatchCallDesc, + .desc = COMPOUND_STRING("ROCKIN' WHIZ"), .name = NULL, .textData = sRoxanneTextScripts }; @@ -397,7 +399,7 @@ static const struct MatchCallStructTrainer sBrawlyMatchCallHeader = .mapSec = MAPSEC_DEWFORD_TOWN, .flag = FLAG_ENABLE_BRAWLY_MATCH_CALL, .rematchTableIdx = REMATCH_BRAWLY, - .desc = gText_BrawlyMatchCallDesc, + .desc = COMPOUND_STRING("THE BIG HIT"), .name = NULL, .textData = sBrawlyTextScripts }; @@ -416,7 +418,7 @@ static const struct MatchCallStructTrainer sWattsonMatchCallHeader = .mapSec = MAPSEC_MAUVILLE_CITY, .flag = FLAG_ENABLE_WATTSON_MATCH_CALL, .rematchTableIdx = REMATCH_WATTSON, - .desc = gText_WattsonMatchCallDesc, + .desc = COMPOUND_STRING("SWELL SHOCK"), .name = NULL, .textData = sWattsonTextScripts }; @@ -435,7 +437,7 @@ static const struct MatchCallStructTrainer sFlanneryMatchCallHeader = .mapSec = MAPSEC_LAVARIDGE_TOWN, .flag = FLAG_ENABLE_FLANNERY_MATCH_CALL, .rematchTableIdx = REMATCH_FLANNERY, - .desc = gText_FlanneryMatchCallDesc, + .desc = COMPOUND_STRING("PASSION BURN"), .name = NULL, .textData = sFlanneryTextScripts }; @@ -454,7 +456,7 @@ static const struct MatchCallStructTrainer sWinonaMatchCallHeader = .mapSec = MAPSEC_FORTREE_CITY, .flag = FLAG_ENABLE_WINONA_MATCH_CALL, .rematchTableIdx = REMATCH_WINONA, - .desc = gText_WinonaMatchCallDesc, + .desc = COMPOUND_STRING("SKY TAMER"), .name = NULL, .textData = sWinonaTextScripts }; @@ -473,7 +475,7 @@ static const struct MatchCallStructTrainer sTateLizaMatchCallHeader = .mapSec = MAPSEC_MOSSDEEP_CITY, .flag = FLAG_ENABLE_TATE_AND_LIZA_MATCH_CALL, .rematchTableIdx = REMATCH_TATE_AND_LIZA, - .desc = gText_TateLizaMatchCallDesc, + .desc = COMPOUND_STRING("MYSTIC DUO"), .name = NULL, .textData = sTateLizaTextScripts }; @@ -492,11 +494,13 @@ static const struct MatchCallStructTrainer sJuanMatchCallHeader = .mapSec = MAPSEC_SOOTOPOLIS_CITY, .flag = FLAG_ENABLE_JUAN_MATCH_CALL, .rematchTableIdx = REMATCH_JUAN, - .desc = gText_JuanMatchCallDesc, + .desc = COMPOUND_STRING("DANDY CHARM"), .name = NULL, .textData = sJuanTextScripts }; +static const u8 gText_EliteFourMatchCallDesc[] = _("ELITE FOUR"); + static const match_call_text_data_t sSidneyTextScripts[] = { { MatchCall_Text_Sidney, 0xFFFF, 0xFFFF }, { NULL, 0xFFFF, 0xFFFF } @@ -572,7 +576,7 @@ static const struct MatchCallStructTrainer sWallaceMatchCallHeader = .mapSec = MAPSEC_EVER_GRANDE_CITY, .flag = FLAG_REMATCH_WALLACE, .rematchTableIdx = REMATCH_WALLACE, - .desc = gText_ChampionMatchCallDesc, + .desc = COMPOUND_STRING("CHAMPION"), .name = NULL, .textData = sWallaceTextScripts }; @@ -657,6 +661,19 @@ static void (*const sMatchCall_GetNameAndDescFunctions[])(match_call_t, const u8 MatchCall_GetNameAndDesc_Birch }; +static const u8 gText_MatchCallSteven_Strategy[] = _("Attack the weak points!"); +static const u8 gText_MatchCallSteven_Pokemon[] = _("Ultimate STEEL POKéMON."); + +static const u8 gText_MatchCallBrendan_Strategy[] = _("Battle with knowledge!"); +static const u8 gText_MatchCallBrendan_Pokemon[] = _("I will use various POKéMON."); +static const u8 gText_MatchCallBrendan_Intro1[] = _("I'll be a better POKéMON"); +static const u8 gText_MatchCallBrendan_Intro2[] = _("prof than my father is!"); + +static const u8 gText_MatchCallMay_Strategy[] = _("I'm not so good at battles."); +static const u8 gText_MatchCallMay_Pokemon[] = _("I'll use any POKéMON!"); +static const u8 gText_MatchCallMay_Intro1[] = _("My POKéMON and I help"); +static const u8 gText_MatchCallMay_Intro2[] = _("my father's research."); + static const struct MatchCallCheckPageOverride sCheckPageOverrides[] = { { .idx = MC_HEADER_STEVEN, @@ -665,8 +682,8 @@ static const struct MatchCallCheckPageOverride sCheckPageOverrides[] = { .flavorTexts = { [CHECK_PAGE_STRATEGY] = gText_MatchCallSteven_Strategy, [CHECK_PAGE_POKEMON] = gText_MatchCallSteven_Pokemon, - [CHECK_PAGE_INTRO_1] = gText_MatchCallSteven_Intro1_BeforeMeteorFallsBattle, - [CHECK_PAGE_INTRO_2] = gText_MatchCallSteven_Intro2_BeforeMeteorFallsBattle + [CHECK_PAGE_INTRO_1] = COMPOUND_STRING("I'd climb even waterfalls"), + [CHECK_PAGE_INTRO_2] = COMPOUND_STRING("to find a rare stone!") } }, { @@ -676,8 +693,8 @@ static const struct MatchCallCheckPageOverride sCheckPageOverrides[] = { .flavorTexts = { [CHECK_PAGE_STRATEGY] = gText_MatchCallSteven_Strategy, [CHECK_PAGE_POKEMON] = gText_MatchCallSteven_Pokemon, - [CHECK_PAGE_INTRO_1] = gText_MatchCallSteven_Intro1_AfterMeteorFallsBattle, - [CHECK_PAGE_INTRO_2] = gText_MatchCallSteven_Intro2_AfterMeteorFallsBattle + [CHECK_PAGE_INTRO_1] = COMPOUND_STRING("I'm the strongest and most"), + [CHECK_PAGE_INTRO_2] = COMPOUND_STRING("energetic after all!") } }, { diff --git a/src/pokenav_match_call_gfx.c b/src/pokenav_match_call_gfx.c index 594b4d83d4..80e2709cf0 100755 --- a/src/pokenav_match_call_gfx.c +++ b/src/pokenav_match_call_gfx.c @@ -124,6 +124,11 @@ static const u16 sListWindow_Pal[] = INCBIN_U16("graphics/pokenav/match_call/lis static const u16 sPokeball_Pal[] = INCBIN_U16("graphics/pokenav/match_call/pokeball.gbapal"); static const u32 sPokeball_Gfx[] = INCBIN_U32("graphics/pokenav/match_call/pokeball.4bpp.lz"); +static const u8 gText_NumberRegistered[] = _("No. registered"); +static const u8 gText_NumberOfBattles[] = _("No. of battles"); +static const u8 gText_TrainerCloseBy[] = _("That TRAINER is close by.\nTalk to the TRAINER in person!"); +static const u8 gText_Unknown[] = _("UNKNOWN"); + static const struct BgTemplate sMatchCallBgTemplates[3] = { { @@ -199,9 +204,9 @@ static const struct WindowTemplate sMatchCallInfoBoxWindowTemplate = static const u8 *const sMatchCallOptionTexts[MATCH_CALL_OPTION_COUNT] = { - [MATCH_CALL_OPTION_CALL] = gText_Call, - [MATCH_CALL_OPTION_CHECK] = gText_Check, - [MATCH_CALL_OPTION_CANCEL] = gText_Cancel6 + [MATCH_CALL_OPTION_CALL] = COMPOUND_STRING("CALL"), + [MATCH_CALL_OPTION_CHECK] = COMPOUND_STRING("CHECK"), + [MATCH_CALL_OPTION_CANCEL] = COMPOUND_STRING("CANCEL") }; // The series of 5 dots that appear when someone is called with Match Call diff --git a/src/pokenav_match_call_list.c b/src/pokenav_match_call_list.c index 43cd5220dd..94a13031da 100755 --- a/src/pokenav_match_call_list.c +++ b/src/pokenav_match_call_list.c @@ -36,6 +36,8 @@ static u32 CB2_HandleCallExitInput(struct Pokenav_MatchCallMenu *); static u32 LoopedTask_BuildMatchCallList(s32); static bool32 ShouldDoNearbyMessage(void); +static const u8 gText_CallCantBeMadeHere[] = _("A call can't be made from here."); + #include "data/text/match_call_messages.h" static const u8 sMatchCallOptionsNoCheckPage[] = diff --git a/src/pokenav_menu_handler_gfx.c b/src/pokenav_menu_handler_gfx.c index b0128d385d..09fb96f3dc 100644 --- a/src/pokenav_menu_handler_gfx.c +++ b/src/pokenav_menu_handler_gfx.c @@ -108,6 +108,8 @@ static const u32 sPokenavDeviceBgTilemap[] = INCBIN_U32("graphics/pokenav/device static const u16 sMatchCallBlueLightPal[] = INCBIN_U16("graphics/pokenav/blue_light.gbapal"); static const u32 sMatchCallBlueLightTiles[] = INCBIN_U32("graphics/pokenav/blue_light.4bpp.lz"); +static const u8 gText_NoRibbonWinners[] = _("There are no RIBBON winners."); + static const struct BgTemplate sPokenavMainMenuBgTemplates[] = { { .bg = 1, @@ -267,20 +269,20 @@ static const struct WindowTemplate sOptionDescWindowTemplate = static const u8 *const sPageDescriptions[] = { - [POKENAV_MENUITEM_MAP] = gText_CheckMapOfHoenn, - [POKENAV_MENUITEM_CONDITION] = gText_CheckPokemonInDetail, - [POKENAV_MENUITEM_MATCH_CALL] = gText_CallRegisteredTrainer, - [POKENAV_MENUITEM_RIBBONS] = gText_CheckObtainedRibbons, - [POKENAV_MENUITEM_SWITCH_OFF] = gText_PutAwayPokenav, - [POKENAV_MENUITEM_CONDITION_PARTY] = gText_CheckPartyPokemonInDetail, - [POKENAV_MENUITEM_CONDITION_SEARCH] = gText_CheckAllPokemonInDetail, - [POKENAV_MENUITEM_CONDITION_CANCEL] = gText_ReturnToPokenavMenu, - [POKENAV_MENUITEM_CONDITION_SEARCH_COOL] = gText_FindCoolPokemon, - [POKENAV_MENUITEM_CONDITION_SEARCH_BEAUTY] = gText_FindBeautifulPokemon, - [POKENAV_MENUITEM_CONDITION_SEARCH_CUTE] = gText_FindCutePokemon, - [POKENAV_MENUITEM_CONDITION_SEARCH_SMART] = gText_FindSmartPokemon, - [POKENAV_MENUITEM_CONDITION_SEARCH_TOUGH] = gText_FindToughPokemon, - [POKENAV_MENUITEM_CONDITION_SEARCH_CANCEL] = gText_ReturnToConditionMenu + [POKENAV_MENUITEM_MAP] = COMPOUND_STRING("Check the map of the HOENN region"), + [POKENAV_MENUITEM_CONDITION] = COMPOUND_STRING("Check POKéMON in detail."), + [POKENAV_MENUITEM_MATCH_CALL] = COMPOUND_STRING("Call a registered TRAINER."), + [POKENAV_MENUITEM_RIBBONS] = COMPOUND_STRING("Check obtained RIBBONS."), + [POKENAV_MENUITEM_SWITCH_OFF] = COMPOUND_STRING("Put away the POKéNAV."), + [POKENAV_MENUITEM_CONDITION_PARTY] = COMPOUND_STRING("Check party POKéMON in detail."), + [POKENAV_MENUITEM_CONDITION_SEARCH] = COMPOUND_STRING("Check all POKéMON in detail."), + [POKENAV_MENUITEM_CONDITION_CANCEL] = COMPOUND_STRING("Return to the POKéNAV menu."), + [POKENAV_MENUITEM_CONDITION_SEARCH_COOL] = COMPOUND_STRING("Find cool POKéMON."), + [POKENAV_MENUITEM_CONDITION_SEARCH_BEAUTY] = COMPOUND_STRING("Find beautiful POKéMON."), + [POKENAV_MENUITEM_CONDITION_SEARCH_CUTE] = COMPOUND_STRING("Find cute POKéMON."), + [POKENAV_MENUITEM_CONDITION_SEARCH_SMART] = COMPOUND_STRING("Find smart POKéMON."), + [POKENAV_MENUITEM_CONDITION_SEARCH_TOUGH] = COMPOUND_STRING("Find tough POKéMON."), + [POKENAV_MENUITEM_CONDITION_SEARCH_CANCEL] = COMPOUND_STRING("Return to the CONDITION menu.") }; static const u8 sOptionDescTextColors[] = {TEXT_COLOR_GREEN, TEXT_COLOR_BLUE, TEXT_COLOR_LIGHT_GREEN}; diff --git a/src/pokenav_ribbons_summary.c b/src/pokenav_ribbons_summary.c index bba1c3600c..9a5eafeea5 100644 --- a/src/pokenav_ribbons_summary.c +++ b/src/pokenav_ribbons_summary.c @@ -40,6 +40,8 @@ enum #define MON_SPRITE_X_OFF -32 #define MON_SPRITE_Y 104 +static const u8 gText_RibbonsF700[] = _("RIBBONS {DYNAMIC 0}"); + struct Pokenav_RibbonsSummaryList { u8 unused1[8]; diff --git a/src/random.c b/src/random.c index 9d43ae3740..969aa6d404 100644 --- a/src/random.c +++ b/src/random.c @@ -8,7 +8,6 @@ rng_value_t gRngValue; rng_value_t gRng2Value; -#if HQ_RANDOM == TRUE EWRAM_DATA static volatile bool8 sRngLoopUnlocked; @@ -112,39 +111,6 @@ void AdvanceRandom(void) #define LOOP_RANDOM ((u16)(_SFC32_Next(state) >> 16)) -#else -EWRAM_DATA static u32 sRandCount = 0; - -u16 Random(void) -{ - gRngValue = ISO_RANDOMIZE1(gRngValue); - sRandCount++; - return gRngValue >> 16; -} - -void SeedRng(u16 seed) -{ - gRngValue = seed; -} - -void SeedRng2(u16 seed) -{ - gRng2Value = seed; -} - -u16 Random2(void) -{ - gRng2Value = ISO_RANDOMIZE1(gRng2Value); - return gRng2Value >> 16; -} - -#define LOOP_RANDOM_START -#define LOOP_RANDOM_END - -#define LOOP_RANDOM (Random()) - -#endif - #define SHUFFLE_IMPL \ u32 tmp; \ LOOP_RANDOM_START; \ diff --git a/src/recorded_battle.c b/src/recorded_battle.c index 2ac33a08a0..c32e86b525 100644 --- a/src/recorded_battle.c +++ b/src/recorded_battle.c @@ -741,7 +741,7 @@ void RecordedBattle_CheckMovesetChanges(u8 mode) movePp.moves[j] = gBattleMons[battlerId].moves[moveSlots[j]]; movePp.currentPp[j] = gBattleMons[battlerId].pp[moveSlots[j]]; movePp.maxPp[j] = ppBonuses[moveSlots[j]]; - mimickedMoveSlots[j] = (gDisableStructs[battlerId].mimickedMoves & gBitTable[j]) >> j; + mimickedMoveSlots[j] = (gDisableStructs[battlerId].mimickedMoves & (1u << j)) >> j; } for (j = 0; j < MAX_MON_MOVES; j++) { diff --git a/src/script_menu.c b/src/script_menu.c index b78f1ef112..706c4ac715 100644 --- a/src/script_menu.c +++ b/src/script_menu.c @@ -487,7 +487,7 @@ static void Task_HandleScrollingMultichoiceInput(u8 taskId) { bool32 done = FALSE; s32 input = ListMenu_ProcessInput(gTasks[taskId].data[0]); - + switch (input) { case LIST_HEADER: diff --git a/src/script_movement.c b/src/script_movement.c index 10517dfc8e..d67afd9972 100644 --- a/src/script_movement.c +++ b/src/script_movement.c @@ -142,19 +142,19 @@ static void LoadObjectEventIdFromMovementScript(u8 taskId, u8 moveScrId, u8 *obj static void ClearMovementScriptFinished(u8 taskId, u8 moveScrId) { - u16 mask = ~gBitTable[moveScrId]; + u16 mask = ~(1u << moveScrId); gTasks[taskId].data[0] &= mask; } static void SetMovementScriptFinished(u8 taskId, u8 moveScrId) { - gTasks[taskId].data[0] |= gBitTable[moveScrId]; + gTasks[taskId].data[0] |= (1u << moveScrId); } static bool8 IsMovementScriptFinished(u8 taskId, u8 moveScrId) { - u16 moveScriptFinished = (u16)gTasks[taskId].data[0] & gBitTable[moveScrId]; + u16 moveScriptFinished = (u16)gTasks[taskId].data[0] & (1u << moveScrId); if (moveScriptFinished != 0) return TRUE; diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c index e732dc7aa2..3d2c7d640c 100644 --- a/src/script_pokemon_util.c +++ b/src/script_pokemon_util.c @@ -466,7 +466,7 @@ u32 ScriptGiveMon(u16 species, u8 level, u16 item) #define PARSE_FLAG(n, default_) (flags & (1 << (n))) ? VarGet(ScriptReadHalfword(ctx)) : (default_) -/* Give or create a mon to either player or opponent +/* Give or create a mon to either player or opponent */ void ScrCmd_createmon(struct ScriptContext *ctx) { diff --git a/src/strings.c b/src/strings.c index a5533731ed..54a08f32e2 100644 --- a/src/strings.c +++ b/src/strings.c @@ -20,7 +20,6 @@ const u8 gText_ExpandedPlaceholder_Brendan[] = _("BRENDAN"); const u8 gText_ExpandedPlaceholder_May[] = _("MAY"); const u8 gText_EggNickname[] = _("EGG"); const u8 gText_Pokemon[] = _("POKéMON"); -const u8 gText_ProfBirchMatchCallName[] = _("PROF. BIRCH"); const u8 gText_Player[] = _("PLAYER"); // Unused const u8 gText_Pokedex[] = _("POKéDEX"); // Unused const u8 gText_Time[] = _("TIME"); @@ -897,57 +896,11 @@ const u8 gText_SeeYaDescription[] = _("Return to the previous menu."); const u8 gText_JustOnePkmn[] = _("There is just one POKéMON with you."); const u8 gText_PartyFull[] = _("Your party is full!"); const u8 gText_Box[] = _("BOX"); -const u8 gText_CheckMapOfHoenn[] = _("Check the map of the HOENN region."); -const u8 gText_CheckPokemonInDetail[] = _("Check POKéMON in detail."); -const u8 gText_CallRegisteredTrainer[] = _("Call a registered TRAINER."); -const u8 gText_CheckObtainedRibbons[] = _("Check obtained RIBBONS."); -const u8 gText_PutAwayPokenav[] = _("Put away the POKéNAV."); -const u8 gText_NoRibbonWinners[] = _("There are no RIBBON winners."); -const u8 gText_NoTrainersRegistered[] = _("No TRAINERS are registered."); // Unused -const u8 gText_CheckPartyPokemonInDetail[] = _("Check party POKéMON in detail."); -const u8 gText_CheckAllPokemonInDetail[] = _("Check all POKéMON in detail."); -const u8 gText_ReturnToPokenavMenu[] = _("Return to the POKéNAV menu."); -const u8 gText_FindCoolPokemon[] = _("Find cool POKéMON."); -const u8 gText_FindBeautifulPokemon[] = _("Find beautiful POKéMON."); -const u8 gText_FindCutePokemon[] = _("Find cute POKéMON."); -const u8 gText_FindSmartPokemon[] = _("Find smart POKéMON."); -const u8 gText_FindToughPokemon[] = _("Find tough POKéMON."); -const u8 gText_ReturnToConditionMenu[] = _("Return to the CONDITION menu."); -const u8 gText_NumberRegistered[] = _("No. registered"); -const u8 gText_NumberOfBattles[] = _("No. of battles"); -const u8 gText_Detail[] = _("DETAIL"); // Unused -const u8 gText_Call2[] = _("CALL"); // Unused -const u8 gText_UnusedExit[] = _("EXIT"); // Unused -const u8 gText_CantCallOpponentHere[] = _("Can't call opponent here."); // Unused -const u8 gText_PokenavMatchCall_Strategy[] = _("STRATEGY"); -const u8 gText_PokenavMatchCall_TrainerPokemon[] = _("TRAINER'S POKéMON"); -const u8 gText_PokenavMatchCall_SelfIntroduction[] = _("SELF-INTRODUCTION"); -const u8 gText_Pokenav_ClearButtonList[] = _("{CLEAR 0x80}"); -const u8 gText_PokenavMap_ZoomedOutButtons[] = _("{A_BUTTON}ZOOM {B_BUTTON}CANCEL"); -const u8 gText_PokenavMap_ZoomedInButtons[] = _("{A_BUTTON}FULL {B_BUTTON}CANCEL"); -const u8 gText_PokenavCondition_MonListButtons[] = _("{A_BUTTON}CONDITION {B_BUTTON}CANCEL"); -const u8 gText_PokenavCondition_MonStatusButtons[] = _("{A_BUTTON}MARKINGS {B_BUTTON}CANCEL"); -const u8 gText_PokenavCondition_MarkingButtons[] = _("{A_BUTTON}SELECT MARK {B_BUTTON}CANCEL"); -const u8 gText_PokenavMatchCall_TrainerListButtons[] = _("{A_BUTTON}MENU {B_BUTTON}CANCEL"); -const u8 gText_PokenavMatchCall_CallMenuButtons[] = _("{A_BUTTON}OK {B_BUTTON}CANCEL"); -const u8 gText_PokenavMatchCall_CheckTrainerButtons[] = _("{B_BUTTON}CANCEL"); -const u8 gText_PokenavRibbons_MonListButtons[] = _("{A_BUTTON}RIBBONS {B_BUTTON}CANCEL"); -const u8 gText_PokenavRibbons_RibbonListButtons[] = _("{A_BUTTON}CHECK {B_BUTTON}CANCEL"); -const u8 gText_PokenavRibbons_RibbonCheckButtons[] = _("{B_BUTTON}CANCEL"); const u8 gText_NatureSlash[] = _("NATURE/"); -const u8 gText_TrainerCloseBy[] = _("That TRAINER is close by.\nTalk to the TRAINER in person!"); const u8 gText_InParty[] = _("IN PARTY"); -const u8 gText_Number2[] = _("No. "); -const u8 gText_Ribbons[] = _("RIBBONS"); // Unused const u8 gText_PokemonMaleLv[] = _("{DYNAMIC 0}{COLOR_HIGHLIGHT_SHADOW LIGHT_RED WHITE GREEN}♂{COLOR_HIGHLIGHT_SHADOW DARK_GRAY WHITE LIGHT_GRAY}/{LV}{DYNAMIC 1}"); // Unused const u8 gText_PokemonFemaleLv[] = _("{DYNAMIC 0}{COLOR_HIGHLIGHT_SHADOW LIGHT_GREEN WHITE BLUE}♀{COLOR_HIGHLIGHT_SHADOW DARK_GRAY WHITE LIGHT_GRAY}/{LV}{DYNAMIC 1}"); // Unused const u8 gText_PokemonNoGenderLv[] = _("{DYNAMIC 0}/{LV}{DYNAMIC 1}"); // Unused -const u8 gText_Unknown[] = _("UNKNOWN"); -const u8 gText_Call[] = _("CALL"); -const u8 gText_Check[] = _("CHECK"); -const u8 gText_Cancel6[] = _("CANCEL"); -const u8 gText_NumberIndex[] = _("No. {DYNAMIC 0}"); -const u8 gText_RibbonsF700[] = _("RIBBONS {DYNAMIC 0}"); const u8 gText_PokemonMaleLv2[] = _("{DYNAMIC 0}{COLOR_HIGHLIGHT_SHADOW LIGHT_RED WHITE GREEN}♂{COLOR_HIGHLIGHT_SHADOW DARK_GRAY WHITE LIGHT_GRAY}/{LV}{DYNAMIC 1}{DYNAMIC 2}"); // Unused const u8 gText_PokemonFemaleLv2[] = _("{DYNAMIC 0}{COLOR_HIGHLIGHT_SHADOW LIGHT_GREEN WHITE BLUE}♀{COLOR_HIGHLIGHT_SHADOW DARK_GRAY WHITE LIGHT_GRAY}/{LV}{DYNAMIC 1}{DYNAMIC 2}"); // Unused const u8 gText_PokemonNoGenderLv2[] = _("{DYNAMIC 0}/{LV}{DYNAMIC 1}{DYNAMIC 2}"); // Unused @@ -1240,20 +1193,6 @@ const u8 gText_ThankYou[] = _("THANK YOU"); const u8 gText_ByeBye[] = _("BYE-BYE!"); const u8 gText_PlayerScurriedToCenter[] = _("{PLAYER} scurried to a POKéMON CENTER,\nprotecting the exhausted and fainted\nPOKéMON from further harm…\p"); const u8 gText_PlayerScurriedBackHome[] = _("{PLAYER} scurried back home, protecting\nthe exhausted and fainted POKéMON from\nfurther harm…\p"); -const u8 gText_MatchCallSteven_Strategy[] = _("Attack the weak points!"); -const u8 gText_MatchCallSteven_Pokemon[] = _("Ultimate STEEL POKéMON."); -const u8 gText_MatchCallSteven_Intro1_BeforeMeteorFallsBattle[] = _("I'd climb even waterfalls"); -const u8 gText_MatchCallSteven_Intro2_BeforeMeteorFallsBattle[] = _("to find a rare stone!"); -const u8 gText_MatchCallSteven_Intro1_AfterMeteorFallsBattle[] = _("I'm the strongest and most"); -const u8 gText_MatchCallSteven_Intro2_AfterMeteorFallsBattle[] = _("energetic after all!"); -const u8 gText_MatchCallBrendan_Strategy[] = _("Battle with knowledge!"); -const u8 gText_MatchCallBrendan_Pokemon[] = _("I will use various POKéMON."); -const u8 gText_MatchCallBrendan_Intro1[] = _("I'll be a better POKéMON"); -const u8 gText_MatchCallBrendan_Intro2[] = _("prof than my father is!"); -const u8 gText_MatchCallMay_Strategy[] = _("I'm not so good at battles."); -const u8 gText_MatchCallMay_Pokemon[] = _("I'll use any POKéMON!"); -const u8 gText_MatchCallMay_Intro1[] = _("My POKéMON and I help"); -const u8 gText_MatchCallMay_Intro2[] = _("my father's research."); const u8 gText_HatchedFromEgg[] = _("{STR_VAR_1} hatched from the EGG!"); const u8 gText_NicknameHatchPrompt[] = _("Would you like to nickname the newly\nhatched {STR_VAR_1}?"); ALIGNED(4) const u8 gText_ReadyPickBerry[] = _("Are you ready to BERRY-CRUSH?\nPlease pick a BERRY for use.\p"); @@ -1549,7 +1488,6 @@ const u8 gText_BoxName[] = _("BOX NAME?"); const u8 gText_PkmnsNickname[] = _("{STR_VAR_1}'s nickname?"); const u8 gText_TellHimTheWords[] = _("Tell him the words."); const u8 gText_MoveOkBack[] = _("{DPAD_NONE}MOVE {A_BUTTON}OK {B_BUTTON}BACK"); -const u8 gText_CallCantBeMadeHere[] = _("A call can't be made from here."); const u8 gText_RentalPkmn2[] = _("RENTAL POKéMON"); const u8 gText_SelectFirstPkmn[] = _("Select the first POKéMON."); const u8 gText_SelectSecondPkmn[] = _("Select the second POKéMON."); @@ -1720,28 +1658,6 @@ const u8 gText_ClearingData[] = _("Clearing data…\nPlease wait."); const u8 gText_IsThisTheCorrectTime[] = _("Is this the correct time?"); const u8 gText_Confirm3[] = _("CONFIRM"); const u8 gText_Cancel4[] = _("CANCEL"); -const u8 gText_MrStoneMatchCallDesc[] = _("DEVON PRES"); -const u8 gText_MrStoneMatchCallName[] = _("MR. STONE"); -const u8 gText_StevenMatchCallDesc[] = _("HARD AS ROCK"); -const u8 gText_StevenMatchCallName[] = _("STEVEN"); -const u8 gText_MayBrendanMatchCallDesc[] = _("RAD NEIGHBOR"); -const u8 gText_NormanMatchCallDesc[] = _("RELIABLE ONE"); -const u8 gText_MomMatchCallDesc[] = _("CALM & KIND"); -const u8 gText_WallyMatchCallDesc[] = _("{PKMN} LOVER"); -const u8 gText_NormanMatchCallName[] = _("DAD"); -const u8 gText_MomMatchCallName[] = _("MOM"); -const u8 gText_ScottMatchCallDesc[] = _("ELUSIVE EYES"); -const u8 gText_ScottMatchCallName[] = _("SCOTT"); -const u8 gText_RoxanneMatchCallDesc[] = _("ROCKIN' WHIZ"); -const u8 gText_BrawlyMatchCallDesc[] = _("THE BIG HIT"); -const u8 gText_WattsonMatchCallDesc[] = _("SWELL SHOCK"); -const u8 gText_FlanneryMatchCallDesc[] = _("PASSION BURN"); -const u8 gText_WinonaMatchCallDesc[] = _("SKY TAMER"); -const u8 gText_TateLizaMatchCallDesc[] = _("MYSTIC DUO"); -const u8 gText_JuanMatchCallDesc[] = _("DANDY CHARM"); -const u8 gText_EliteFourMatchCallDesc[] = _("ELITE FOUR"); -const u8 gText_ChampionMatchCallDesc[] = _("CHAMPION"); -const u8 gText_ProfBirchMatchCallDesc[] = _("{PKMN} PROF."); const u8 gText_CommStandbyAwaitingOtherPlayer[] = _("Communication standby…\nAwaiting another player to choose."); const u8 gText_BattleWasRefused[] = _("The battle was refused.{PAUSE 60}"); const u8 gText_RefusedBattle[] = _("Refused the battle.{PAUSE 60}"); diff --git a/src/trainer_hill.c b/src/trainer_hill.c index aa7c8ee930..c89803ffb2 100644 --- a/src/trainer_hill.c +++ b/src/trainer_hill.c @@ -852,7 +852,7 @@ bool8 GetHillTrainerFlag(u8 objectEventId) u32 trainerIndexStart = GetFloorId() * HILL_TRAINERS_PER_FLOOR; u8 bitId = gObjectEvents[objectEventId].localId - 1 + trainerIndexStart; - return gSaveBlock2Ptr->frontier.trainerFlags & gBitTable[bitId]; + return gSaveBlock2Ptr->frontier.trainerFlags & (1u << bitId); } void SetHillTrainerFlag(void) @@ -864,7 +864,7 @@ void SetHillTrainerFlag(void) { if (gSaveBlock2Ptr->frontier.trainerIds[i] == gTrainerBattleOpponent_A) { - gSaveBlock2Ptr->frontier.trainerFlags |= gBitTable[trainerIndexStart + i]; + gSaveBlock2Ptr->frontier.trainerFlags |= 1u << (trainerIndexStart + i); break; } } @@ -875,7 +875,7 @@ void SetHillTrainerFlag(void) { if (gSaveBlock2Ptr->frontier.trainerIds[i] == gTrainerBattleOpponent_B) { - gSaveBlock2Ptr->frontier.trainerFlags |= gBitTable[trainerIndexStart + i]; + gSaveBlock2Ptr->frontier.trainerFlags |= 1u << (trainerIndexStart + i); break; } } diff --git a/src/tv.c b/src/tv.c index e0f910eaaf..c0e207ce8a 100644 --- a/src/tv.c +++ b/src/tv.c @@ -1262,7 +1262,7 @@ void PutBattleUpdateOnTheAir(u8 opponentLinkPlayerId, u16 move, u16 speciesPlaye if (gBattleTypeFlags & BATTLE_TYPE_MULTI) show->battleUpdate.battleType = 2; - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + else if (IsDoubleBattle()) show->battleUpdate.battleType = 1; else show->battleUpdate.battleType = 0; diff --git a/src/type_icons.c b/src/type_icons.c new file mode 100644 index 0000000000..361312ab91 --- /dev/null +++ b/src/type_icons.c @@ -0,0 +1,552 @@ +#include "global.h" +#include "battle.h" +#include "battle_anim.h" +#include "battle_controllers.h" +#include "battle_gimmick.h" +#include "decompress.h" +#include "graphics.h" +#include "pokedex.h" +#include "sprite.h" +#include "type_icons.h" + +static void LoadTypeSpritesAndPalettes(void); +static void LoadTypeIconsPerBattler(u32, u32); + +static bool32 UseDoubleBattleCoords(u32); + +static u32 GetMonPublicType(u32, u32); +static bool32 ShouldHideUncaughtType(u32); +static u32 GetMonDefensiveTeraType(struct Pokemon *, struct Pokemon*, u32, u32, u32, u32); +static u32 IsIllusionActiveAndTypeUnchanged(struct Pokemon*, u32, u32); + +static void CreateSpriteFromType(u32, bool32, u32[], u32, u32); +static bool32 ShouldSkipSecondType(u32[], u32); +static void SetTypeIconXY(s32*, s32*, u32, bool32, u32); + +static void CreateSpriteAndSetTypeSpriteAttributes(u32, u32 x, u32 y, u32, u32, bool32); +static bool32 ShouldFlipTypeIcon(bool32, u32, u32); + +static void SpriteCB_TypeIcon(struct Sprite*); +static void DestroyTypeIcon(struct Sprite*); +static void FreeAllTypeIconResources(void); +static bool32 ShouldHideTypeIcon(u32); +static s32 GetTypeIconHideMovement(bool32, u32); +static s32 GetTypeIconSlideMovement(bool32, u32, s32); +static s32 GetTypeIconBounceMovement(s32, u32); + +const struct Coords16 sTypeIconPositions[][2] = +{ + [B_POSITION_PLAYER_LEFT] = + { + [FALSE] = {221, 86}, + [TRUE] = {144, 71}, + }, + [B_POSITION_OPPONENT_LEFT] = + { + [FALSE] = {20, 26}, + [TRUE] = {97, 14}, + }, + [B_POSITION_PLAYER_RIGHT] = + { + [TRUE] = {156, 96}, + }, + [B_POSITION_OPPONENT_RIGHT] = + { + [TRUE] = {85, 39}, + }, +}; + +const union AnimCmd sSpriteAnim_TypeIcon_Normal[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_NORMAL), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Fighting[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_FIGHTING), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Flying[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_FLYING), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Poison[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_POISON), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Ground[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_GROUND), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Rock[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_ROCK), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Bug[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_BUG), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Ghost[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_GHOST), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Steel[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_STEEL), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Mystery[] = +{ + ANIMCMD_FRAME(TYPE_ICON_1_FRAME(TYPE_MYSTERY), 0), + ANIMCMD_END +}; + +const union AnimCmd sSpriteAnim_TypeIcon_Fire[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_FIRE), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Water[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_WATER), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Grass[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_GRASS), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Electric[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_ELECTRIC), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Psychic[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_PSYCHIC), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Ice[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_ICE), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Dragon[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_DRAGON), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Dark[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_DARK), 0), + ANIMCMD_END +}; +const union AnimCmd sSpriteAnim_TypeIcon_Fairy[] = +{ + ANIMCMD_FRAME(TYPE_ICON_2_FRAME(TYPE_FAIRY), 0), + ANIMCMD_END +}; + +const union AnimCmd *const sSpriteAnimTable_TypeIcons[] = +{ + [TYPE_NONE] = sSpriteAnim_TypeIcon_Mystery, + [TYPE_NORMAL] = sSpriteAnim_TypeIcon_Normal, + [TYPE_FIGHTING] = sSpriteAnim_TypeIcon_Fighting, + [TYPE_FLYING] = sSpriteAnim_TypeIcon_Flying, + [TYPE_POISON] = sSpriteAnim_TypeIcon_Poison, + [TYPE_GROUND] = sSpriteAnim_TypeIcon_Ground, + [TYPE_ROCK] = sSpriteAnim_TypeIcon_Rock, + [TYPE_BUG] = sSpriteAnim_TypeIcon_Bug, + [TYPE_GHOST] = sSpriteAnim_TypeIcon_Ghost, + [TYPE_STEEL] = sSpriteAnim_TypeIcon_Steel, + [TYPE_MYSTERY] = sSpriteAnim_TypeIcon_Mystery, + [TYPE_FIRE] = sSpriteAnim_TypeIcon_Fire, + [TYPE_WATER] = sSpriteAnim_TypeIcon_Water, + [TYPE_GRASS] = sSpriteAnim_TypeIcon_Grass, + [TYPE_ELECTRIC] = sSpriteAnim_TypeIcon_Electric, + [TYPE_PSYCHIC] = sSpriteAnim_TypeIcon_Psychic, + [TYPE_ICE] = sSpriteAnim_TypeIcon_Ice, + [TYPE_DRAGON] = sSpriteAnim_TypeIcon_Dragon, + [TYPE_DARK] = sSpriteAnim_TypeIcon_Dark, + [TYPE_FAIRY] = sSpriteAnim_TypeIcon_Fairy, + [TYPE_STELLAR] = sSpriteAnim_TypeIcon_Mystery, +}; + +const struct CompressedSpritePalette sTypeIconPal1 = +{ + .data = gBattleIcons_Pal1, + .tag = TYPE_ICON_TAG +}; + +const struct CompressedSpritePalette sTypeIconPal2 = +{ + .data = gBattleIcons_Pal2, + .tag = TYPE_ICON_TAG_2 +}; + +const struct OamData sOamData_TypeIcons = +{ + .affineMode = ST_OAM_AFFINE_OFF, + .objMode = ST_OAM_OBJ_NORMAL, + .shape = SPRITE_SHAPE(8x16), + .size = SPRITE_SIZE(8x16), + .priority = 1, +}; + +const struct CompressedSpriteSheet sSpriteSheet_TypeIcons2 = +{ + .data = gBattleIcons_Gfx2, + .size = (8*16) * 9, + .tag = TYPE_ICON_TAG_2, +}; + +const struct CompressedSpriteSheet sSpriteSheet_TypeIcons1 = +{ + .data = gBattleIcons_Gfx1, + .size = (8*16) * 10, + .tag = TYPE_ICON_TAG, +}; + +const struct SpriteTemplate sSpriteTemplate_TypeIcons1 = +{ + .tileTag = TYPE_ICON_TAG, + .paletteTag = TYPE_ICON_TAG, + .oam = &sOamData_TypeIcons, + .anims = sSpriteAnimTable_TypeIcons, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_TypeIcon +}; + +const struct SpriteTemplate sSpriteTemplate_TypeIcons2 = +{ + .tileTag = TYPE_ICON_TAG_2, + .paletteTag = TYPE_ICON_TAG_2, + .oam = &sOamData_TypeIcons, + .anims = sSpriteAnimTable_TypeIcons, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_TypeIcon +}; + +void LoadTypeIcons(u32 battler) +{ + u32 position; + + if (B_SHOW_TYPES == SHOW_TYPES_NEVER) + return; + + LoadTypeSpritesAndPalettes(); + + for (position = 0; position < gBattlersCount; ++position) + LoadTypeIconsPerBattler(battler, position); +} + +static void LoadTypeSpritesAndPalettes(void) +{ + if (IndexOfSpritePaletteTag(TYPE_ICON_TAG) != UCHAR_MAX) + return; + + LoadCompressedSpriteSheet(&sSpriteSheet_TypeIcons1); + LoadCompressedSpriteSheet(&sSpriteSheet_TypeIcons2); + LoadCompressedSpritePalette(&sTypeIconPal1); + LoadCompressedSpritePalette(&sTypeIconPal2); +} + +static void LoadTypeIconsPerBattler(u32 battler, u32 position) +{ + u32 typeNum, types[2]; + u32 battlerId = GetBattlerAtPosition(position); + bool32 useDoubleBattleCoords = UseDoubleBattleCoords(battlerId); + + if (!IsBattlerAlive(battlerId)) + return; + + for (typeNum = 0; typeNum < 2; ++typeNum) + types[typeNum] = GetMonPublicType(battlerId, typeNum); + + for (typeNum = 0; typeNum < 2; ++typeNum) + CreateSpriteFromType(position, useDoubleBattleCoords, types, typeNum, battler); +} + +static bool32 UseDoubleBattleCoords(u32 position) +{ + if (!IsDoubleBattle()) + return FALSE; + + if ((position == B_POSITION_PLAYER_LEFT) && (gBattleMons[B_POSITION_PLAYER_RIGHT].species == SPECIES_NONE)) + return FALSE; + + if ((position == B_POSITION_OPPONENT_LEFT) && (gBattleMons[B_POSITION_OPPONENT_RIGHT].species == SPECIES_NONE)) + return FALSE; + + return TRUE; +} + +static u32 GetMonPublicType(u32 battlerId, u32 typeNum) +{ + struct Pokemon* mon = GetBattlerData(battlerId); + u32 monSpecies = GetMonData(mon,MON_DATA_SPECIES,NULL); + struct Pokemon* monIllusion; + u32 illusionSpecies; + + if (ShouldHideUncaughtType(monSpecies)) + return TYPE_MYSTERY; + + monIllusion = GetIllusionMonPtr(battlerId); + illusionSpecies = GetMonData(monIllusion,MON_DATA_SPECIES,NULL); + + if (GetActiveGimmick(battlerId) == GIMMICK_TERA) + return GetMonDefensiveTeraType(mon,monIllusion,battlerId,typeNum,illusionSpecies,monSpecies); + + if (IsIllusionActiveAndTypeUnchanged(monIllusion,monSpecies, battlerId)) + return gSpeciesInfo[illusionSpecies].types[typeNum]; + + return gBattleMons[battlerId].types[typeNum]; +} + +static bool32 ShouldHideUncaughtType(u32 species) +{ + if (B_SHOW_TYPES != SHOW_TYPES_CAUGHT) + return FALSE; + + if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(species),FLAG_GET_CAUGHT)) + return FALSE; + + return TRUE; +} + +static u32 GetMonDefensiveTeraType(struct Pokemon * mon, struct Pokemon* monIllusion, u32 battlerId, u32 typeNum, u32 illusionSpecies, u32 monSpecies) +{ + u32 teraType = GetBattlerTeraType(battlerId); + u32 targetSpecies; + + if (teraType != TYPE_STELLAR) + return teraType; + + targetSpecies = (monIllusion != NULL) ? illusionSpecies : monSpecies; + + return gSpeciesInfo[targetSpecies].types[typeNum]; +} + +static u32 IsIllusionActiveAndTypeUnchanged(struct Pokemon* monIllusion, u32 monSpecies, u32 battlerId) +{ + u32 typeNum; + + if (monIllusion == NULL) + return FALSE; + + for (typeNum = 0; typeNum < 2; typeNum++) + if (gSpeciesInfo[monSpecies].types[typeNum] != gBattleMons[battlerId].types[typeNum]) + return FALSE; + + return TRUE; +} + +static void CreateSpriteFromType(u32 position, bool32 useDoubleBattleCoords, u32 types[], u32 typeNum, u32 battler) +{ + s32 x = 0, y = 0; + + if (ShouldSkipSecondType(types, typeNum)) + return; + + SetTypeIconXY(&x, &y, position, useDoubleBattleCoords, typeNum); + + CreateSpriteAndSetTypeSpriteAttributes(types[typeNum], x, y, position, battler, useDoubleBattleCoords); +} + +static bool32 ShouldSkipSecondType(u32 types[], u32 typeNum) +{ + if (!typeNum) + return FALSE; + + if (types[0] != types[1]) + return FALSE; + + return TRUE; +} + +static void SetTypeIconXY(s32* x, s32* y, u32 position, bool32 useDoubleBattleCoords, u32 typeNum) +{ + *x = sTypeIconPositions[position][useDoubleBattleCoords].x; + *y = sTypeIconPositions[position][useDoubleBattleCoords].y + (11 * typeNum); +} + +static void CreateSpriteAndSetTypeSpriteAttributes(u32 type, u32 x, u32 y, u32 position, u32 battler, bool32 useDoubleBattleCoords) +{ + struct Sprite* sprite; + const struct SpriteTemplate* spriteTemplate = gTypesInfo[type].useSecondTypeIconPalette ? &sSpriteTemplate_TypeIcons2 : &sSpriteTemplate_TypeIcons1; + u32 spriteId = CreateSpriteAtEnd(spriteTemplate, x, y, UCHAR_MAX); + + if (spriteId == MAX_SPRITES) + return; + + sprite = &gSprites[spriteId]; + sprite->tMonPosition = position; + sprite->tBattlerId = battler; + sprite->tVerticalPosition = y; + + sprite->hFlip = ShouldFlipTypeIcon(useDoubleBattleCoords, position, type); + + StartSpriteAnim(sprite, type); +} + +static bool32 ShouldFlipTypeIcon(bool32 useDoubleBattleCoords, u32 position, u32 typeId) +{ + bool32 side = (useDoubleBattleCoords) ? B_SIDE_OPPONENT : B_SIDE_PLAYER; + + if (GetBattlerSide(GetBattlerAtPosition(position)) != side) + return FALSE; + + return !gTypesInfo[typeId].isSpecialCaseType; +} + +static void SpriteCB_TypeIcon(struct Sprite* sprite) +{ + u32 position = sprite->tMonPosition; + u32 battlerId = sprite->tBattlerId; + bool32 useDoubleBattleCoords = UseDoubleBattleCoords(GetBattlerAtPosition(position)); + + if (sprite->tHideIconTimer == NUM_FRAMES_HIDE_TYPE_ICON) + { + DestroyTypeIcon(sprite); + return; + } + + if (ShouldHideTypeIcon(battlerId)) + { + sprite->x += GetTypeIconHideMovement(useDoubleBattleCoords, position); + ++sprite->tHideIconTimer; + return; + } + + sprite->x += GetTypeIconSlideMovement(useDoubleBattleCoords,position, sprite->x); + sprite->y = GetTypeIconBounceMovement(sprite->tVerticalPosition,position); +} + +static const u32 typeIconTags[] = +{ + TYPE_ICON_TAG, + TYPE_ICON_TAG_2 +}; + +static void DestroyTypeIcon(struct Sprite* sprite) +{ + u32 spriteId, tag; + + DestroySpriteAndFreeResources(sprite); + + for (spriteId = 0; spriteId < MAX_SPRITES; ++spriteId) + { + if (!gSprites[spriteId].inUse) + continue; + + for (tag = 0; tag < 2; tag++) + { + if (gSprites[spriteId].template->paletteTag == typeIconTags[tag]) + return; + + if (gSprites[spriteId].template->tileTag == typeIconTags[tag]) + return; + } + } + + FreeAllTypeIconResources(); +} + +static void FreeAllTypeIconResources(void) +{ + u32 tag; + + for (tag = 0; tag < 2; tag++) + { + FreeSpriteTilesByTag(typeIconTags[tag]); + FreeSpritePaletteByTag(typeIconTags[tag]); + } +} + +static void (* const sShowTypesControllerFuncs[])(u32 battler) = +{ + PlayerHandleChooseMove, + HandleChooseMoveAfterDma3, + HandleInputChooseTarget, + HandleInputShowTargets, + HandleInputShowEntireFieldTargets, + HandleMoveSwitching, + HandleInputChooseMove, +}; + + +static bool32 ShouldHideTypeIcon(u32 battlerId) +{ + u32 funcIndex; + + for (funcIndex = 0; funcIndex < ARRAY_COUNT(sShowTypesControllerFuncs); funcIndex++) + if (gBattlerControllerFuncs[battlerId] == sShowTypesControllerFuncs[funcIndex]) + return FALSE; + + return TRUE; +} + +static s32 GetTypeIconHideMovement(bool32 useDoubleBattleCoords, u32 position) +{ + if (useDoubleBattleCoords) + { + if (position == B_POSITION_PLAYER_LEFT || position == B_POSITION_PLAYER_RIGHT) + return 1; + else + return -1; + } + + if (position == B_POSITION_PLAYER_LEFT) + return -1; + else + return 1; +} + +static s32 GetTypeIconSlideMovement(bool32 useDoubleBattleCoords, u32 position, s32 xPos) +{ + if (useDoubleBattleCoords) + { + switch (position) + { + case B_POSITION_PLAYER_LEFT: + case B_POSITION_PLAYER_RIGHT: + if (xPos > sTypeIconPositions[position][useDoubleBattleCoords].x - 10) + return -1; + break; + default: + case B_POSITION_OPPONENT_LEFT: + case B_POSITION_OPPONENT_RIGHT: + if (xPos < sTypeIconPositions[position][useDoubleBattleCoords].x + 10) + return 1; + break; + } + return 0; + } + + if (position == B_POSITION_PLAYER_LEFT) + { + if (xPos < sTypeIconPositions[position][useDoubleBattleCoords].x + 10) + return 1; + } + else + { + if (xPos > sTypeIconPositions[position][useDoubleBattleCoords].x - 10) + return -1; + } + return 0; +} + +static s32 GetTypeIconBounceMovement(s32 originalY, u32 position) +{ + struct Sprite* healthbox = &gSprites[gHealthboxSpriteIds[GetBattlerAtPosition(position)]]; + return originalY + healthbox->y2; +} + diff --git a/src/util.c b/src/util.c index 77d9cde2f1..002b2fabf0 100644 --- a/src/util.c +++ b/src/util.c @@ -4,42 +4,6 @@ #include "palette.h" #include "constants/rgb.h" -const u32 gBitTable[] = -{ - 1 << 0, - 1 << 1, - 1 << 2, - 1 << 3, - 1 << 4, - 1 << 5, - 1 << 6, - 1 << 7, - 1 << 8, - 1 << 9, - 1 << 10, - 1 << 11, - 1 << 12, - 1 << 13, - 1 << 14, - 1 << 15, - 1 << 16, - 1 << 17, - 1 << 18, - 1 << 19, - 1 << 20, - 1 << 21, - 1 << 22, - 1 << 23, - 1 << 24, - 1 << 25, - 1 << 26, - 1 << 27, - 1 << 28, - 1 << 29, - 1 << 30, - 1 << 31, -}; - static const struct SpriteTemplate sInvisibleSpriteTemplate = { .tileTag = 0, diff --git a/src/vs_seeker.c b/src/vs_seeker.c index 30dcb74ce0..771c01dc72 100644 --- a/src/vs_seeker.c +++ b/src/vs_seeker.c @@ -581,7 +581,7 @@ bool32 IsVsSeekerEnabled(void) { if (I_VS_SEEKER_CHARGING == 0) return FALSE; - + return (CheckBagHasItem(ITEM_VS_SEEKER, 1)); } diff --git a/src/wild_encounter.c b/src/wild_encounter.c index ae7770aa3a..033eec56da 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -1002,14 +1002,10 @@ static bool8 IsWildLevelAllowedByRepel(u8 wildLevel) for (i = 0; i < PARTY_SIZE; i++) { - if (GetMonData(&gPlayerParty[i], MON_DATA_HP) && !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG)) + if (I_REPEL_INCLUDE_FAINTED == GEN_1 || I_REPEL_INCLUDE_FAINTED >= GEN_6 || GetMonData(&gPlayerParty[i], MON_DATA_HP)) { - u8 ourLevel = GetMonData(&gPlayerParty[i], MON_DATA_LEVEL); - - if (wildLevel < ourLevel) - return FALSE; - else - return TRUE; + if (!GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG)) + return wildLevel >= GetMonData(&gPlayerParty[i], MON_DATA_LEVEL); } } diff --git a/sym_bss.txt b/sym_bss.txt deleted file mode 100644 index 3a23e74789..0000000000 --- a/sym_bss.txt +++ /dev/null @@ -1,63 +0,0 @@ - .include "src/main.o" - .include "gflib/malloc.o" - .include "gflib/dma3_manager.o" - .include "gflib/gpu_regs.o" - .include "gflib/bg.o" - .include "gflib/text.o" - .include "gflib/sprite.o" - .include "src/link.o" - .include "src/AgbRfu_LinkManager.o" - .include "src/link_rfu_3.o" - .include "src/link_rfu_2.o" - .include "src/union_room.o" - .include "src/wireless_communication_status_screen.o" - .include "src/union_room_battle.o" - .include "src/dodrio_berry_picking.o" - .include "src/rtc.o" - .include "src/main_menu.o" - .include "src/digit_obj_util.o" - .include "src/egg_hatch.o" - .include "src/berry_blender.o" - .include "src/play_time.o" - .include "src/overworld.o" - .include "src/field_camera.o" - .include "src/script.o" - .include "src/scrcmd.o" - .include "src/tileset_anims.o" - .include "src/palette.o" - .include "src/sound.o" - .include "src/field_weather.o" - .include "src/field_effect.o" - .include "src/pokemon_storage_system.o" - .include "src/fldeff_cut.o" - .include "src/script_menu.o" - .include "src/record_mixing.o" - .include "src/tv.o" - .include "src/mauville_old_man.o" - .include "src/menu_helpers.o" - .include "src/region_map.o" - .include "src/slot_machine.o" - .include "src/contest_painting.o" - .include "src/starter_choose.o" - .include "src/pokedex_area_screen.o" - .include "src/battle_transition.o" - .include "src/pokemon_animation.o" - .include "src/recorded_battle.o" - .include "src/battle_factory_screen.o" - .include "src/battle_factory.o" - .include "src/battle_pike.o" - .include "src/battle_tent.o" - .include "src/multiboot.o" - .include "src/mirage_tower.o" - .include "src/berry_fix_program.o" - .include "src/pokenav_conditions_gfx.o" - .include "src/pokenav_ribbons_summary.o" - .include "src/ereader_helpers.o" - .include "src/faraway_island.o" - .include "src/m4a_1.o" - .include "data/sound_data.o" - .include "src/agb_flash.o" - .include "src/siirtc.o" - .include "*libgcc.a:dp-bit.o" - .include "*libgcc.a:fp-bit.o" - .include "*libc.a:syscalls.o" diff --git a/sym_common.txt b/sym_common.txt deleted file mode 100644 index 170aee2f42..0000000000 --- a/sym_common.txt +++ /dev/null @@ -1,83 +0,0 @@ - .space 0x8 - .include "main.o" - @ ../gflib/bg.o - .align 2 -gWindowTileAutoAllocEnabled: - .space 4 - @ ../gflib/window.o - .align 4 -gTransparentTileNumber: - .space 1 - .align 4 -gWindowBgTilemapBuffers: - .space 16 - @ ../gflib/text.o - .align 4 -gFonts: - .space 4 - .align 2 -gDisableTextPrinters: - .space 1 - .align 4 -gCurGlyph: - .space 132 - .align 2 -gTextFlags: - .space 4 - @ ../gflib/sprite.o - .align 2 -gOamMatrixAllocBitmap: - .space 4 - .align 2 -gReservedSpritePaletteCount: - .space 1 - .align 4 - .include "link.o" - .include "AgbRfu_LinkManager.o" - .include "link_rfu_2.o" - .include "rtc.o" - .include "battle_main.o" - .include "battle_controllers.o" - .include "random.o" - .include "load_save.o" - .include "berry_blender.o" - .include "overworld.o" - .include "fieldmap.o" - .include "field_camera.o" - .include "field_control_avatar.o" - .include "start_menu.o" - .include "sound.o" - .include "task.o" - .include "trainer_see.o" - .include "pokedex.o" - .include "contest.o" - .include "tv.o" - .include "mauville_old_man.o" - .include "image_processing_effects.o" - - .space 0x4 - - .include "contest_painting.o" - .include "field_specials.o" - .include "evolution_scene.o" - .include "pokedex_cry_screen.o" - .include "save.o" - .include "battle_tower.o" - .include "intro.o" - .include "battle_anim_throw.o" - .include "battle_factory_screen.o" - .include "apprentice.o" - - .space 0x8 - - .include "list_menu.o" - .include "party_menu.o" - - .space 0x44 - - .include "ereader_screen.o" - .include "m4a.o" - .include "agb_flash.o" - .include "librfu_stwi.o" - .include "librfu_rfu.o" - .include "librfu_sio32id.o" diff --git a/sym_ewram.txt b/sym_ewram.txt deleted file mode 100644 index 3123b3388a..0000000000 --- a/sym_ewram.txt +++ /dev/null @@ -1,154 +0,0 @@ - .include "gflib/malloc.o" - .include "src/decompress.o" - .include "src/main.o" - .include "gflib/window.o" - .include "gflib/text.o" - .include "gflib/sprite.o" - .include "gflib/string_util.o" - .include "src/link.o" - .include "src/AgbRfu_LinkManager.o" - .include "src/link_rfu_3.o" - .include "src/link_rfu_2.o" - .include "src/union_room.o" - .include "src/mystery_gift_menu.o" - .include "src/union_room_player_avatar.o" - .include "src/wireless_communication_status_screen.o" - .include "src/union_room_battle.o" - .include "src/mystery_gift.o" - .include "src/mystery_gift_view.o" - .include "src/mystery_gift_server.o" - .include "src/mystery_gift_client.o" - .include "src/union_room_chat.o" - .include "src/berry_crush.o" - .include "src/berry_powder.o" - .include "src/dodrio_berry_picking.o" - .include "src/pokemon_jump.o" - .include "src/main_menu.o" - .include "src/battle_controllers.o" - .include "src/digit_obj_util.o" - .include "src/battle_main.o" - .include "src/pokemon.o" - .include "src/random.o" - .include "src/daycare.o" - .include "src/load_save.o" - .include "src/trade.o" - .include "src/berry_blender.o" - .include "src/new_game.o" - .include "src/overworld.o" - .include "src/fieldmap.o" - .include "src/field_camera.o" - .include "src/field_player_avatar.o" - .include "src/event_object_movement.o" - .include "src/field_message_box.o" - .include "src/scrcmd.o" - .include "src/field_control_avatar.o" - .include "src/event_data.o" - .include "src/start_menu.o" - .include "src/tileset_anims.o" - .include "src/palette.o" - .include "src/sound.o" - .include "src/battle_anim.o" - .include "src/battle_anim_mons.o" - - .space 0xC - .include "src/field_weather.o" - .include "src/field_weather_effect.o" - .include "src/battle_setup.o" - .include "src/trainer_see.o" - .include "src/wild_encounter.o" - .include "src/field_effect.o" - .include "src/scanline_effect.o" - .include "src/option_menu.o" - .include "src/pokedex.o" - .include "src/trainer_card.o" - .include "src/frontier_pass.o" - .include "src/pokemon_storage_system.o" - .include "src/script_movement.o" - .include "src/fldeff_cut.o" - .include "src/map_name_popup.o" - .include "src/item.o" - .include "src/contest.o" - .include "src/shop.o" - .include "src/fldeff_escalator.o" - .include "src/script_menu.o" - .include "src/naming_screen.o" - .include "src/money.o" - .include "src/record_mixing.o" - .include "src/secret_base.o" - .include "src/tv.o" - .include "src/contest_util.o" - .include "src/rotating_gate.o" - .include "src/safari_zone.o" - .include "src/item_use.o" - .include "src/battle_anim_effects_1.o" - .include "src/battle_anim_dragon.o" - .include "src/battle_anim_utility_funcs.o" - .include "src/battle_intro.o" - .include "src/easy_chat.o" - .include "src/mon_markings.o" - .include "src/mauville_old_man.o" - .include "src/mail.o" - .include "src/menu_helpers.o" - .include "src/region_map.o" - .include "src/decoration.o" - .include "src/slot_machine.o" - .include "src/battle_ai_main.o" - .include "src/fldeff_misc.o" - .include "src/pokeblock.o" - .include "src/field_specials.o" - .include "src/battle_records.o" - .include "src/pokedex_area_screen.o" - .include "src/evolution_scene.o" - .include "src/roulette.o" - .include "src/pokedex_cry_screen.o" - .include "src/coins.o" - .include "src/battle_transition.o" - .include "src/battle_message.o" - .include "src/cable_car.o" - .include "src/confetti_util.o" - .include "src/save.o" - .include "src/mystery_event_script.o" - .include "src/move_relearner.o" - .include "src/decoration_inventory.o" - .include "src/roamer.o" - .include "src/battle_tower.o" - .include "src/use_pokeblock.o" - .include "src/player_pc.o" - .include "src/intro.o" - .include "src/field_region_map.o" - .include "src/hall_of_fame.o" - .include "src/credits.o" - .include "src/lottery_corner.o" - .include "src/diploma.o" - .include "src/berry_tag_screen.o" - .include "src/mystery_event_menu.o" - .include "src/save_failed_screen.o" - .include "src/braille_puzzles.o" - .include "src/pokeblock_feed.o" - .include "src/intro_credits_graphics.o" - .include "src/recorded_battle.o" - .include "src/trainer_pokemon_sprites.o" - .include "src/lilycove_lady.o" - .include "src/battle_dome.o" - .include "src/match_call.o" - .include "src/menu.o" - .include "src/battle_factory_screen.o" - .include "src/rotating_tile_puzzle.o" - .include "src/item_menu.o" - .include "src/list_menu.o" - .include "src/dynamic_placeholder_text_util.o" - .include "src/item_icon.o" - .include "src/party_menu.o" - .include "src/mirage_tower.o" - .include "src/pokemon_summary_screen.o" - .include "src/pokedex_area_region_map.o" - .include "src/battle_pyramid_bag.o" - .include "src/pokenav.o" - .include "src/pokenav_list.o" - .include "src/menu_specialized.o" - .include "src/faraway_island.o" - .include "src/trainer_hill.o" - .include "src/rayquaza_scene.o" - .include "src/debug.o" - .include "src/battle_controller_player.o" - .include "src/pokedex_plus_hgss.o" diff --git a/test/battle/ability/adaptability.c b/test/battle/ability/adaptability.c new file mode 100644 index 0000000000..4c1c8439b7 --- /dev/null +++ b/test/battle/ability/adaptability.c @@ -0,0 +1,64 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Adaptability increases same-type attack bonus from x1.5 to x2", s16 damage) +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_HYPER_CUTTER; } + PARAMETRIZE { ability = ABILITY_ADAPTABILITY; } + GIVEN { + PLAYER(SPECIES_CRAWDAUNT) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_WATER_GUN); } + } SCENE { + MESSAGE("Crawdaunt used Water Gun!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + // The jump from 1.5x STAB to 2.0x STAB is a 1.33x boost. + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.33), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("(TERA) Terastallizing into a different type with Adaptability gives 2.0x STAB", s16 damage) +{ + bool32 tera; + PARAMETRIZE { tera = GIMMICK_NONE; } + PARAMETRIZE { tera = GIMMICK_TERA; } + GIVEN { + PLAYER(SPECIES_CRAWDAUNT) { Ability(ABILITY_ADAPTABILITY); TeraType(TYPE_NORMAL); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_HEADBUTT, gimmick: tera); } + } SCENE { + MESSAGE("Crawdaunt used Headbutt!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_HEADBUTT, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + // The jump from no STAB to 2.0x STAB is a 2.0x boost. + EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("(TERA) Terastallizing into the same type with Adaptability gives 2.25x STAB", s16 damage) +{ + bool32 tera; + PARAMETRIZE { tera = GIMMICK_NONE; } + PARAMETRIZE { tera = GIMMICK_TERA; } + GIVEN { + PLAYER(SPECIES_CRAWDAUNT) { Ability(ABILITY_ADAPTABILITY); TeraType(TYPE_WATER); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_WATER_PULSE, gimmick: tera); } + } SCENE { + MESSAGE("Crawdaunt used Water Pulse!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_PULSE, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + // The jump from 2x STAB to 2.25x STAB is a 1.125x boost. + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.125), results[1].damage); + } +} + +TO_DO_BATTLE_TEST("Adaptability does not affect Stellar-type moves"); diff --git a/test/battle/ability/aerilate.c b/test/battle/ability/aerilate.c new file mode 100644 index 0000000000..4386034a59 --- /dev/null +++ b/test/battle/ability/aerilate.c @@ -0,0 +1,56 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_TACKLE].type == TYPE_NORMAL); + ASSUME(gMovesInfo[MOVE_TACKLE].power > 0); +} + +SINGLE_BATTLE_TEST("Aerilate turns a Normal-type move into Flying-type move") +{ + GIVEN { + PLAYER(SPECIES_MEGANIUM); + OPPONENT(SPECIES_SALAMENCE) { Item(ITEM_SALAMENCITE); } + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE, gimmick: GIMMICK_MEGA); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_MEGA_EVOLUTION, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + MESSAGE("It's super effective!"); + } +} + +SINGLE_BATTLE_TEST("Aerilate can not turn certain moves into Flying type moves") +{ + u32 move; + PARAMETRIZE { move = MOVE_WEATHER_BALL; } + // PARAMETRIZE { move = MOVE_NATURAL_GIFT; } TODO: handle this case via Skill Swap + PARAMETRIZE { move = MOVE_JUDGMENT; } + PARAMETRIZE { move = MOVE_TECHNO_BLAST; } + PARAMETRIZE { move = MOVE_REVELATION_DANCE; } + PARAMETRIZE { move = MOVE_MULTI_ATTACK; } + PARAMETRIZE { move = MOVE_TERRAIN_PULSE; } + GIVEN { + PLAYER(SPECIES_MEGANIUM); + OPPONENT(SPECIES_SALAMENCE) { Item(ITEM_SALAMENCITE); } + } WHEN { + TURN { MOVE(opponent, move, gimmick: GIMMICK_MEGA); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_MEGA_EVOLUTION, opponent); + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + NONE_OF { + MESSAGE("It's super effective!"); + } + } +} + +TO_DO_BATTLE_TEST("Aerilate boosts power of affected moves by 20% (Gen7+)"); +TO_DO_BATTLE_TEST("Aerilate boosts power of affected moves by 30% (Gen6)"); + +// Gen 6-7 +TO_DO_BATTLE_TEST("Aerilate overrides Electrify (Gen6-7)"); +TO_DO_BATTLE_TEST("Aerilate overrides Ion Deluge (Gen6-7)"); +// Gen 8+ +//TO_DO_BATTLE_TEST("Aerilate doesn't override Electrify (Gen8+)"); // No mon with Aerilate exists in Gen8+, but probably behaves similar to Pixilate, which does. +//TO_DO_BATTLE_TEST("Aerilate doesn't override Ion Deluge (Gen8+)"); // Ion Deluge doesn't exist in Gen 8+, but we probably could assume it behaves similar to under Electrify. TODO: Test by hacking SV. diff --git a/test/battle/ability/aftermath.c b/test/battle/ability/aftermath.c new file mode 100644 index 0000000000..5cfd5ef034 --- /dev/null +++ b/test/battle/ability/aftermath.c @@ -0,0 +1,22 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Aftermath damages the attacker by 1/4th of its max HP if fainted by a contact move") +{ + s16 aftermathDamage; + + GIVEN { + PLAYER(SPECIES_VOLTORB) { HP(1); Ability(ABILITY_AFTERMATH); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN {MOVE(opponent, MOVE_TACKLE);} + } SCENE { + MESSAGE("Foe Wobbuffet used Tackle!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + MESSAGE("Voltorb fainted!"); + ABILITY_POPUP(player, ABILITY_AFTERMATH); + HP_BAR(opponent, captureDamage: &aftermathDamage); + } THEN { + EXPECT_EQ(aftermathDamage, opponent->maxHP / 4); + } +} diff --git a/test/battle/ability/air_lock.c b/test/battle/ability/air_lock.c new file mode 100644 index 0000000000..0201e86a20 --- /dev/null +++ b/test/battle/ability/air_lock.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +// Tests for Air Lock are handled in test/battle/ability/cloud_nine.c diff --git a/test/battle/ability/analytic.c b/test/battle/ability/analytic.c new file mode 100644 index 0000000000..44c42ae2d5 --- /dev/null +++ b/test/battle/ability/analytic.c @@ -0,0 +1,11 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Analytic increases the power of moves by 30% if it's the last one that uses its move"); +TO_DO_BATTLE_TEST("Analytic takes into account modifications to speeed an priority (Gen 5-8)"); //Eg. Paralysis, Power Weight, Stall +TO_DO_BATTLE_TEST("Analytic does not take into account modifications to speeed an priority (Gen 8)"); //Eg. Paralysis, Power Weight, Stall +TO_DO_BATTLE_TEST("Analytic takes into account the turn order of what fainted Pokémon would've moved"); + +// Triple Battles needed to test +//TO_DO_BATTLE_TEST("If the Pokémon with Analytic is targeting a Pokémon in a flank position that chooses to switch with its ally in the middle, its move's power will always be normal when it attacks the Pokémon that is shifted into the flank position"); +//TO_DO_BATTLE_TEST("If the Pokémon with Analytic targets a Pokémon in the middle whose ally on a flank chooses to shift into the middle position, its move's power still depends on whether the Pokémon that was in the middle (and is now on a flank) has acted when the Pokémon with Analytic uses its move"); diff --git a/test/battle/ability/anger_point.c b/test/battle/ability/anger_point.c index 0b13b9df4b..270d66f28e 100644 --- a/test/battle/ability/anger_point.c +++ b/test/battle/ability/anger_point.c @@ -37,7 +37,7 @@ SINGLE_BATTLE_TEST("Anger Point does not trigger when already at maximum Attack MESSAGE("Primeape cut its own HP and maximized ATTACK!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_FROST_BREATH, opponent); MESSAGE("A critical hit!"); - NONE_OF { + NONE_OF { ABILITY_POPUP(player, ABILITY_ANGER_POINT); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); MESSAGE("Primeape's Anger Point maxed its Attack!"); @@ -47,7 +47,9 @@ SINGLE_BATTLE_TEST("Anger Point does not trigger when already at maximum Attack } } -SINGLE_BATTLE_TEST("Anger Point does not trigger when a substitute takes the hit") +TO_DO_BATTLE_TEST("Anger Point triggers when a substitute takes the hit (Gen4)"); + +SINGLE_BATTLE_TEST("Anger Point does not trigger when a substitute takes the hit (Gen5+)") { ASSUME(gMovesInfo[MOVE_FROST_BREATH].alwaysCriticalHit); ASSUME(gMovesInfo[MOVE_SUBSTITUTE].effect == EFFECT_SUBSTITUTE); @@ -62,7 +64,7 @@ SINGLE_BATTLE_TEST("Anger Point does not trigger when a substitute takes the hit MESSAGE("Primeape made a SUBSTITUTE!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_FROST_BREATH, opponent); MESSAGE("A critical hit!"); - NONE_OF { + NONE_OF { ABILITY_POPUP(player, ABILITY_ANGER_POINT); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); MESSAGE("Primeape's Anger Point maxed its Attack!"); diff --git a/test/battle/ability/anger_shell.c b/test/battle/ability/anger_shell.c index f0d11d7576..c5b490216b 100644 --- a/test/battle/ability/anger_shell.c +++ b/test/battle/ability/anger_shell.c @@ -1,7 +1,7 @@ #include "global.h" #include "test/battle.h" -SINGLE_BATTLE_TEST("Anger Shell activates only if the target had more than 50% of its hp") +SINGLE_BATTLE_TEST("Anger Shell activates only if the target had more than 50% of its HP") { bool32 activates = FALSE; u16 maxHp = 500, hp = 0; diff --git a/test/battle/ability/anticipation.c b/test/battle/ability/anticipation.c new file mode 100644 index 0000000000..a15ff153d9 --- /dev/null +++ b/test/battle/ability/anticipation.c @@ -0,0 +1,24 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Anticipation causes notifies if an opponent has a super-effective move"); +TO_DO_BATTLE_TEST("Anticipation causes notifies if an opponent has a One-hit KO move"); +TO_DO_BATTLE_TEST("Anticipation causes notifies if an opponent has a Self-Destruct or Explosion (Gen4)"); +TO_DO_BATTLE_TEST("Anticipation treats Self-Destruct and Explosion like all other Normal types (Gen5+)"); + +TO_DO_BATTLE_TEST("Anticipation considers Scrappy and Normalize into their effectiveness (Gen4)"); +TO_DO_BATTLE_TEST("Anticipation doesn't consider Scrappy and Normalize into their effectiveness (Gen5+)"); +TO_DO_BATTLE_TEST("Anticipation considers Gravity into their effectiveness (Gen4)"); +TO_DO_BATTLE_TEST("Anticipation doesn't consider Gravity into their effectiveness (Gen5+)"); +TO_DO_BATTLE_TEST("Anticipation doesn't trigger from Counter, Metal Burst or Mirror Coat (Gen4)"); +TO_DO_BATTLE_TEST("Anticipation counts Counter, Metal Burst or Mirror Coat as attacking moves of their types (Gen5+)"); +TO_DO_BATTLE_TEST("Anticipation considers Synchronoise as an ordinary Psychic-type move"); +TO_DO_BATTLE_TEST("Anticipation considers Freeze-Dry as an ordinary Ice-type move"); +TO_DO_BATTLE_TEST("Anticipation considers Flying Press as an ordinary Fighting-type move"); +TO_DO_BATTLE_TEST("Anticipation considers Aura Wheel as an ordinary Electric-type move"); +TO_DO_BATTLE_TEST("Anticipation considers Inverse Battle types"); //Check with Normal-type moves +TO_DO_BATTLE_TEST("Anticipation treats dynamic move types as their base type (Normal)"); // Judgment, Weather Ball, Natural Gift, Techno Blast, Revelation Dance, Multi Attack +TO_DO_BATTLE_TEST("Anticipation treats Hidden Power as Normal Type (Gen4-5)"); +TO_DO_BATTLE_TEST("Anticipation treats Hidden Power as its dynamic type (Gen6+)"); +TO_DO_BATTLE_TEST("Anticipation does not consider Strong Winds on type matchups"); +TO_DO_BATTLE_TEST("Anticipation does not consider ate-abilities"); diff --git a/test/battle/ability/arena_trap.c b/test/battle/ability/arena_trap.c new file mode 100644 index 0000000000..ef0d5b7d8c --- /dev/null +++ b/test/battle/ability/arena_trap.c @@ -0,0 +1,11 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Arena Trap prevents grounded adjacent opponents from switching out"); +TO_DO_BATTLE_TEST("Arena Trap doesn't prevent switch outs if the Pokémon is switched in the same turn the opponent decided to switch out"); +TO_DO_BATTLE_TEST("Arena Trap doesn't prevent switch outs via moves that switch out"); // Baton Pass, U-Turn, Volt Switch, Flip Turn, Parting Shot +TO_DO_BATTLE_TEST("Arena Trap doesn't prevent switch outs via Shed Shell, but not via Teleport"); +TO_DO_BATTLE_TEST("Arena Trap doesn't prevent switch outs via Run Away"); +TO_DO_BATTLE_TEST("Arena Trap doesn't prevent switch outs via Smoke Ball"); +TO_DO_BATTLE_TEST("Arena Trap prevents switch outs from Ghost-type Pokémon (Gen3-5)"); +TO_DO_BATTLE_TEST("Arena Trap doesn't prevent switch outs from Ghost-type Pokémon (Gen6+)"); diff --git a/test/battle/ability/aroma_veil.c b/test/battle/ability/aroma_veil.c new file mode 100644 index 0000000000..dc53fa1492 --- /dev/null +++ b/test/battle/ability/aroma_veil.c @@ -0,0 +1,15 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Aroma Veil protects the Pokémon's side from Taunt"); +TO_DO_BATTLE_TEST("Aroma Veil protects the Pokémon's side from Torment"); +TO_DO_BATTLE_TEST("Aroma Veil protects the Pokémon's side from Encore"); +TO_DO_BATTLE_TEST("Aroma Veil protects the Pokémon's side from Disable"); +TO_DO_BATTLE_TEST("Aroma Veil protects the Pokémon's side from Cursed Body"); +TO_DO_BATTLE_TEST("Aroma Veil protects the Pokémon's side from Heal Block"); +TO_DO_BATTLE_TEST("Aroma Veil protects the Pokémon's side from Infatuation"); +TO_DO_BATTLE_TEST("Aroma Veil does not protect the Pokémon's side from Imprison"); + +// Marked in Bulbapedia as need of research +//TO_DO_BATTLE_TEST("Aroma Veil prevents G-Max Meltdown's effect"); +//TO_DO_BATTLE_TEST("Aroma Veil prevents Psychic Noise's effect"); diff --git a/test/battle/ability/as_one.c b/test/battle/ability/as_one.c new file mode 100644 index 0000000000..0d5367bf37 --- /dev/null +++ b/test/battle/ability/as_one.c @@ -0,0 +1,7 @@ +#include "global.h" +#include "test/battle.h" + +// Tests for the individual ability effects are handled in the following times: +// - Unnerve: test/battle/ability/unnerve.c +// - Chilling Neigh: test/battle/ability/chilling_neigh.c +// - Grim Neigh: test/battle/ability/grim_neigh.c diff --git a/test/battle/ability/aura_break.c b/test/battle/ability/aura_break.c new file mode 100644 index 0000000000..93b21421e4 --- /dev/null +++ b/test/battle/ability/aura_break.c @@ -0,0 +1,6 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Aura Break inverts Fairy Aura's effect"); +TO_DO_BATTLE_TEST("Aura Break inverts Dark Aura's effect"); +TO_DO_BATTLE_TEST("Aura Break ignores Mold Breaker abilities"); diff --git a/test/battle/ability/chilling_neigh.c b/test/battle/ability/chilling_neigh.c new file mode 100644 index 0000000000..03be77000b --- /dev/null +++ b/test/battle/ability/chilling_neigh.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +// Tests for Chilling Neigh are handled in test/battle/ability/moxie.c diff --git a/test/battle/ability/chlorophyll.c b/test/battle/ability/chlorophyll.c new file mode 100644 index 0000000000..493a197638 --- /dev/null +++ b/test/battle/ability/chlorophyll.c @@ -0,0 +1,6 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Chlorophyll doubles speed if it's sunny"); +TO_DO_BATTLE_TEST("Chlorophyll doesn't double speed if Cloud Nine/Air Lock is on the field"); +TO_DO_BATTLE_TEST("Chlorophyll doesn't double speed if they have an Utility Umbrella"); diff --git a/test/battle/ability/clear_body.c b/test/battle/ability/clear_body.c index 1379506a72..dc82be67b4 100644 --- a/test/battle/ability/clear_body.c +++ b/test/battle/ability/clear_body.c @@ -127,7 +127,7 @@ SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent s } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_SUPERPOWER, opponent); NONE_OF { - ABILITY_POPUP(opponent, ability); + ABILITY_POPUP(opponent, ability); MESSAGE("Foe Solgaleo's Full Metal Body prevents stat loss!"); MESSAGE("Foe Torkoal's White Smoke prevents stat loss!"); MESSAGE("Foe Metang's Clear Body prevents stat loss!"); @@ -186,7 +186,7 @@ SINGLE_BATTLE_TEST("Mold Breaker, Teravolt, and Turboblaze ignore Clear Body and else{ ANIMATION(ANIM_TYPE_MOVE, move, player); NONE_OF { - ABILITY_POPUP(opponent, ability); + ABILITY_POPUP(opponent, ability); MESSAGE("Foe Solgaleo's Full Metal Body prevents stat loss!"); MESSAGE("Foe Torkoal's White Smoke prevents stat loss!"); MESSAGE("Foe Metang's Clear Body prevents stat loss!"); diff --git a/test/battle/ability/cloud_nine.c b/test/battle/ability/cloud_nine.c index dfe5611fc4..887769a5ec 100644 --- a/test/battle/ability/cloud_nine.c +++ b/test/battle/ability/cloud_nine.c @@ -1,16 +1,41 @@ #include "global.h" #include "test/battle.h" -SINGLE_BATTLE_TEST("Cloud Nine prevents weather effects") +SINGLE_BATTLE_TEST("Cloud Nine/Air Lock prevent basic weather effects, but without them disappearing - Sandstorm") { + u32 species = 0, ability = 0; + PARAMETRIZE { species = SPECIES_PSYDUCK; ability = ABILITY_CLOUD_NINE; } + PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } GIVEN { ASSUME(gMovesInfo[MOVE_SANDSTORM].effect == EFFECT_SANDSTORM); - PLAYER(SPECIES_PSYDUCK) { Ability(ABILITY_CLOUD_NINE); } + PLAYER(species) { Ability(ability); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(opponent, MOVE_SANDSTORM); } TURN {} } SCENE { - NONE_OF { HP_BAR(player); } + ABILITY_POPUP(player, ability); + MESSAGE("The effects of weather disappeared."); + MESSAGE("Foe Wobbuffet used Sandstorm!"); + MESSAGE("The sandstorm rages."); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SANDSTORM_CONTINUES); + NONE_OF { + HP_BAR(player); + HP_BAR(opponent); + MESSAGE("Foe Wobbuffet is buffeted by the sandstorm!"); + } + MESSAGE("The sandstorm rages."); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SANDSTORM_CONTINUES); } } + +TO_DO_BATTLE_TEST("Cloud Nine/Air Lock prevent basic weather effects, but without them disappearing - Sun"); +TO_DO_BATTLE_TEST("Cloud Nine/Air Lock prevent basic weather effects, but without them disappearing - Rain"); +TO_DO_BATTLE_TEST("Cloud Nine/Air Lock prevent basic weather effects, but without them disappearing - Hail"); +TO_DO_BATTLE_TEST("Cloud Nine/Air Lock prevent basic weather effects, but without them disappearing - Snow"); +TO_DO_BATTLE_TEST("Cloud Nine/Air Lock prevent basic weather effects, but without them disappearing - Fog"); +TO_DO_BATTLE_TEST("Cloud Nine/Air Lock prevent basic weather effects, but without them disappearing - Primal Sun"); +TO_DO_BATTLE_TEST("Cloud Nine/Air Lock prevent basic weather effects, but without them disappearing - Primal Rain"); +TO_DO_BATTLE_TEST("Cloud Nine/Air Lock prevent basic weather effects, but without them disappearing - Strong Winds"); + +// Moves and abilities that are affected by weather should have new tests that check for Clould Nine/Air Lock, like Mold-Breaker Abilities diff --git a/test/battle/ability/damp.c b/test/battle/ability/damp.c index 9a3b795f2a..b567293aa0 100644 --- a/test/battle/ability/damp.c +++ b/test/battle/ability/damp.c @@ -57,7 +57,7 @@ SINGLE_BATTLE_TEST("Damp prevents explosion-like moves from self") } } -SINGLE_BATTLE_TEST("Damp prevents damage from aftermath") +SINGLE_BATTLE_TEST("Damp prevents damage from Aftermath") { GIVEN { ASSUME(gMovesInfo[MOVE_TACKLE].makesContact); diff --git a/test/battle/ability/dancer.c b/test/battle/ability/dancer.c index f54f7ab76a..660a719c69 100644 --- a/test/battle/ability/dancer.c +++ b/test/battle/ability/dancer.c @@ -126,3 +126,22 @@ DOUBLE_BATTLE_TEST("Dancer still triggers if another dancer flinches") ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); } } + +SINGLE_BATTLE_TEST("Dancer-called attacks have their type updated") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_REVELATION_DANCE].danceMove == TRUE); + ASSUME(gMovesInfo[MOVE_REVELATION_DANCE].effect == EFFECT_REVELATION_DANCE); + PLAYER(SPECIES_TANGROWTH); + OPPONENT(SPECIES_ORICORIO_BAILE); + } WHEN { + TURN { MOVE(player, MOVE_REVELATION_DANCE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVELATION_DANCE, player); + MESSAGE("It's not very effective…"); + ABILITY_POPUP(opponent, ABILITY_DANCER); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVELATION_DANCE, opponent); + NOT MESSAGE("It's not very effective…"); + MESSAGE("It's super effective!"); + } +} diff --git a/test/battle/ability/disguise.c b/test/battle/ability/disguise.c index c4f79d8fe3..5ab2035325 100644 --- a/test/battle/ability/disguise.c +++ b/test/battle/ability/disguise.c @@ -134,3 +134,42 @@ SINGLE_BATTLE_TEST("Disguised Mimikyu is ignored by Mold Breaker") NOT ABILITY_POPUP(player, ABILITY_DISGUISE); } } + +SINGLE_BATTLE_TEST("Disguised Mimikyu's types revert back to Ghost/Fairy when Disguise is broken") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_SHADOW_CLAW].type == TYPE_GHOST); + PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SOAK); } + TURN { MOVE(opponent, MOVE_TACKLE); } + TURN { MOVE(opponent, MOVE_SHADOW_CLAW); } + } SCENE { + MESSAGE("Foe Wobbuffet used Soak!"); + MESSAGE("Mimikyu transformed into the Water type!"); + MESSAGE("Foe Wobbuffet used Tackle!"); + ABILITY_POPUP(player, ABILITY_DISGUISE); + MESSAGE("Foe Wobbuffet used Shadow Claw!"); + MESSAGE("It's super effective!"); + } +} + +SINGLE_BATTLE_TEST("Disguised Mimikyu blocks a move after getting Gastro Acid Batton Passed") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_BATON_PASS].effect == EFFECT_BATON_PASS); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_GASTRO_ACID); MOVE(player, MOVE_BATON_PASS); SEND_OUT(player, 1); } + TURN { MOVE(opponent, MOVE_SHADOW_CLAW); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_GASTRO_ACID, opponent); + MESSAGE("Wobbuffet's ability was suppressed!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BATON_PASS, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHADOW_CLAW, opponent); + ABILITY_POPUP(player, ABILITY_DISGUISE); + } +} diff --git a/test/battle/ability/drought.c b/test/battle/ability/drought.c new file mode 100644 index 0000000000..bbe4dbe853 --- /dev/null +++ b/test/battle/ability/drought.c @@ -0,0 +1,5 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Drought sets up sun for 5 turns (Gen6+)"); +TO_DO_BATTLE_TEST("Drought sets up permanent sun (Gen3-5)"); diff --git a/test/battle/ability/dry_skin.c b/test/battle/ability/dry_skin.c index 368e4b8047..5709a58a94 100644 --- a/test/battle/ability/dry_skin.c +++ b/test/battle/ability/dry_skin.c @@ -15,6 +15,8 @@ SINGLE_BATTLE_TEST("Dry Skin causes 1/8th Max HP damage in Sun") } } +TO_DO_BATTLE_TEST("Dry Skin doesn't get damaged in Sun if Cloud Nine/Air Lock is on the field"); + SINGLE_BATTLE_TEST("Dry Skin heals 1/8th Max HP in Rain") { GIVEN { @@ -29,6 +31,8 @@ SINGLE_BATTLE_TEST("Dry Skin heals 1/8th Max HP in Rain") } } +TO_DO_BATTLE_TEST("Dry Skin doesn't heal in Rain if Cloud Nine/Air Lock is on the field"); + SINGLE_BATTLE_TEST("Dry Skin increases damage taken from Fire-type moves by 25%", s16 damage) { u32 ability; diff --git a/test/battle/ability/flower_gift.c b/test/battle/ability/flower_gift.c index 69a76b8e81..68712641e0 100644 --- a/test/battle/ability/flower_gift.c +++ b/test/battle/ability/flower_gift.c @@ -17,6 +17,8 @@ SINGLE_BATTLE_TEST("Flower Gift transforms Cherrim in harsh sunlight") } } +TO_DO_BATTLE_TEST("Flower Gift doesn't transform Cherrim if Cloud Nine/Air Lock is on the field"); + SINGLE_BATTLE_TEST("Flower Gift transforms Cherrim back to normal when weather changes") { GIVEN { @@ -61,6 +63,8 @@ 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"); + DOUBLE_BATTLE_TEST("Flower Gift increases the attack of Cherrim and its allies by 1.5x", s16 damageL, s16 damageR) { bool32 sunny; diff --git a/test/battle/ability/forecast.c b/test/battle/ability/forecast.c index 427a8e6807..24a0eed957 100644 --- a/test/battle/ability/forecast.c +++ b/test/battle/ability/forecast.c @@ -264,12 +264,15 @@ SINGLE_BATTLE_TEST("Forecast transforms Castform back to normal when Sandstorm i } } -SINGLE_BATTLE_TEST("Forecast transforms Castform back to normal under Air Lock") +SINGLE_BATTLE_TEST("Forecast transforms Castform 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_CASTFORM_NORMAL) { Ability(ABILITY_FORECAST); } OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_RAYQUAZA); + OPPONENT(species) { Ability(ability); } } WHEN { TURN { MOVE(player, MOVE_RAIN_DANCE); } TURN { SWITCH(opponent, 1); } @@ -279,7 +282,7 @@ SINGLE_BATTLE_TEST("Forecast transforms Castform back to normal under Air Lock") ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); MESSAGE("Castform transformed!"); // back to normal - ABILITY_POPUP(opponent, ABILITY_AIR_LOCK); + ABILITY_POPUP(opponent, ability); ABILITY_POPUP(player, ABILITY_FORECAST); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); MESSAGE("Castform transformed!"); @@ -394,3 +397,25 @@ SINGLE_BATTLE_TEST("Forecast transforms Castform back when it uses a move that f EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_CASTFORM); } } + +SINGLE_BATTLE_TEST("Forecast transforms Castform when Cloud Nine ability user leaves the field") +{ + u32 species = 0, ability = 0; + PARAMETRIZE { species = SPECIES_PSYDUCK; ability = ABILITY_CLOUD_NINE; } + PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } + + GIVEN { + PLAYER(SPECIES_CASTFORM) { Ability(ABILITY_FORECAST); } + OPPONENT(species) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, MOVE_CELEBRATE); } + TURN { SWITCH(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + MESSAGE("2 sent out Wobbuffet!"); + ABILITY_POPUP(player, ABILITY_FORECAST); + MESSAGE("Castform transformed!"); + } +} diff --git a/test/battle/ability/ate_abilities.c b/test/battle/ability/galvanize.c similarity index 50% rename from test/battle/ability/ate_abilities.c rename to test/battle/ability/galvanize.c index 203452cc01..55dfd7287a 100644 --- a/test/battle/ability/ate_abilities.c +++ b/test/battle/ability/galvanize.c @@ -7,6 +7,19 @@ ASSUMPTIONS ASSUME(gMovesInfo[MOVE_TACKLE].power > 0); } +SINGLE_BATTLE_TEST("Galvanize turns a normal type move into Electric") +{ + GIVEN { + PLAYER(SPECIES_KRABBY); + OPPONENT(SPECIES_GEODUDE_ALOLAN) { Ability(ABILITY_GALVANIZE); } + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + MESSAGE("It's super effective!"); + } +} + SINGLE_BATTLE_TEST("Galvanize can not turn certain moves into Electric type moves") { u32 move; @@ -29,56 +42,7 @@ SINGLE_BATTLE_TEST("Galvanize can not turn certain moves into Electric type move } } -SINGLE_BATTLE_TEST("Galvanize turns a normal type move into Electric") -{ - GIVEN { - PLAYER(SPECIES_KRABBY); - OPPONENT(SPECIES_GEODUDE_ALOLAN) { Ability(ABILITY_GALVANIZE); } - } WHEN { - TURN { MOVE(opponent, MOVE_TACKLE); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); - MESSAGE("It's super effective!"); - } -} - -SINGLE_BATTLE_TEST("Pixilate turns a normal type move into Fairy") -{ - GIVEN { - PLAYER(SPECIES_DRAGONITE); - OPPONENT(SPECIES_ALTARIA) { Item(ITEM_ALTARIANITE); } - } WHEN { - TURN { MOVE(opponent, MOVE_TACKLE, gimmick: GIMMICK_MEGA); } - } SCENE { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_MEGA_EVOLUTION, opponent); - ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); - MESSAGE("It's super effective!"); - } -} - -SINGLE_BATTLE_TEST("Refrigerate turns a normal type move into Ice") -{ - GIVEN { - PLAYER(SPECIES_MEGANIUM); - OPPONENT(SPECIES_AMAURA) { Ability(ABILITY_REFRIGERATE); } - } WHEN { - TURN { MOVE(opponent, MOVE_TACKLE); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); - MESSAGE("It's super effective!"); - } -} - -SINGLE_BATTLE_TEST("Aerilate turns a normal type move into Flying") -{ - GIVEN { - PLAYER(SPECIES_MEGANIUM); - OPPONENT(SPECIES_SALAMENCE) { Item(ITEM_SALAMENCITE); } - } WHEN { - TURN { MOVE(opponent, MOVE_TACKLE, gimmick: GIMMICK_MEGA); } - } SCENE { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_MEGA_EVOLUTION, opponent); - ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); - MESSAGE("It's super effective!"); - } -} +TO_DO_BATTLE_TEST("Galvanize boosts power of affected moves by 20% (Gen7+)"); +TO_DO_BATTLE_TEST("Galvanize boosts power of affected moves by 30% (Gen6)"); +TO_DO_BATTLE_TEST("(DYNAMAX) Galvanize turns Max Strike into Max Lightning when not used by Gigantamax Pikachu/Toxtricity"); +//TO_DO_BATTLE_TEST("(DYNAMAX) Galvanize doesn't turn Max Strike into Max Lightning when used by Gigantamax Pikachu/Toxtricity, instead becoming G-Max Volt Crash/Stun Shock"); // Marked in Bulbapedia as "needs research", so this assumes that it behaves like Pixilate. diff --git a/test/battle/ability/grim_neigh.c b/test/battle/ability/grim_neigh.c new file mode 100644 index 0000000000..b4d82487d8 --- /dev/null +++ b/test/battle/ability/grim_neigh.c @@ -0,0 +1,109 @@ +#include "global.h" +#include "test/battle.h" + +DOUBLE_BATTLE_TEST("Grim Neigh raises Sp. Attack by one stage after directly causing a Pokemon to faint") +{ + u32 species = 0, ability = 0, abilityPopUp = 0; + PARAMETRIZE { species = SPECIES_SPECTRIER; ability = ABILITY_GRIM_NEIGH; abilityPopUp = ABILITY_GRIM_NEIGH; } + PARAMETRIZE { species = SPECIES_CALYREX_SHADOW_RIDER; ability = ABILITY_AS_ONE_SHADOW_RIDER; abilityPopUp = ABILITY_GRIM_NEIGH; } + GIVEN { + ASSUME(gMovesInfo[MOVE_DISCHARGE].target == MOVE_TARGET_FOES_AND_ALLY); + PLAYER(species) { Ability(ability); } + PLAYER(SPECIES_SNORUNT) { HP(1); } + OPPONENT(SPECIES_GLALIE) { HP(1); } + OPPONENT(SPECIES_ABRA) { HP(1); } + OPPONENT(SPECIES_ABRA); + } WHEN { + TURN { MOVE(playerLeft, MOVE_DISCHARGE); SEND_OUT(opponentLeft, 2); } + } SCENE { + int i; + + ANIMATION(ANIM_TYPE_MOVE, MOVE_DISCHARGE, playerLeft); + for (i = 0; i < 3; i++) { + ONE_OF { + MESSAGE("Snorunt fainted!"); + MESSAGE("Foe Glalie fainted!"); + MESSAGE("Foe Abra fainted!"); + } + ABILITY_POPUP(playerLeft, abilityPopUp); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + if (species == SPECIES_SPECTRIER) + MESSAGE("Spectrier's Grim Neigh raised its Sp. Atk!"); + else + MESSAGE("Calyrex's Grim Neigh raised its Sp. Atk!"); + } + } THEN { + EXPECT_EQ(playerLeft->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 3); + } +} + +DOUBLE_BATTLE_TEST("Grim Neigh does not trigger if Pokemon faint to indirect damage or damage from other Pokemon") +{ + u32 species = 0, ability = 0, abilityPopUp = 0; + PARAMETRIZE { species = SPECIES_SPECTRIER; ability = ABILITY_GRIM_NEIGH; abilityPopUp = ABILITY_GRIM_NEIGH; } + PARAMETRIZE { species = SPECIES_CALYREX_SHADOW_RIDER; ability = ABILITY_AS_ONE_SHADOW_RIDER; abilityPopUp = ABILITY_GRIM_NEIGH; } + GIVEN { + PLAYER(species) { Ability(ability); } + PLAYER(SPECIES_SNORUNT) { HP(1); Status1(STATUS1_POISON); } + OPPONENT(SPECIES_GLALIE) { HP(1); Status1(STATUS1_BURN); } + OPPONENT(SPECIES_ABRA) { HP(1); } + OPPONENT(SPECIES_ABRA); + } WHEN { + TURN { MOVE(playerRight, MOVE_QUICK_ATTACK, target: opponentRight); SEND_OUT(opponentLeft, 2); } + } SCENE { + int i; + + ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, playerRight); + for (i = 0; i < 3; i++) { + ONE_OF { + MESSAGE("Snorunt fainted!"); + MESSAGE("Foe Glalie fainted!"); + MESSAGE("Foe Abra fainted!"); + } + NONE_OF { + ABILITY_POPUP(playerLeft, abilityPopUp); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + MESSAGE("Salamence's Moxie raised its Sp. Atk!"); + MESSAGE("Spectrier's Grim Neigh raised its Sp. Atk!"); + MESSAGE("Calyrex's Grim Neigh raised its Sp. Atk!"); + } + } + } THEN { + EXPECT_EQ(playerLeft->statStages[STAT_SPATK], DEFAULT_STAT_STAGE); + } +} + +DOUBLE_BATTLE_TEST("Grim Neigh does not increase damage done by the same move that causes another Pokemon to faint") +{ + s16 damage[2]; + u32 species = 0, ability = 0, abilityPopUp = 0; + PARAMETRIZE { species = SPECIES_SPECTRIER; ability = ABILITY_GRIM_NEIGH; abilityPopUp = ABILITY_GRIM_NEIGH; } + PARAMETRIZE { species = SPECIES_CALYREX_SHADOW_RIDER; ability = ABILITY_AS_ONE_SHADOW_RIDER; abilityPopUp = ABILITY_GRIM_NEIGH; } + + KNOWN_FAILING; // Requires simultaneous damage implementation + GIVEN { + ASSUME(gMovesInfo[MOVE_DISCHARGE].target == MOVE_TARGET_FOES_AND_ALLY); + PLAYER(species) { Ability(ability); } + PLAYER(SPECIES_ABRA) { HP(1); } + OPPONENT(SPECIES_GLALIE); + OPPONENT(SPECIES_GLALIE); + OPPONENT(SPECIES_ABRA); + } WHEN { + TURN { MOVE(playerLeft, MOVE_DISCHARGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DISCHARGE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[0]); + HP_BAR(playerRight); + MESSAGE("Abra fainted!"); + ABILITY_POPUP(playerLeft, abilityPopUp); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + if (species == SPECIES_SPECTRIER) + MESSAGE("Spectrier's Grim Neigh raised its Sp. Atk!"); + else + MESSAGE("Calyrex's Grim Neigh raised its Sp. Atk!"); + HP_BAR(opponentRight, captureDamage: &damage[1]); + } THEN { + EXPECT_EQ(playerLeft->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(damage[0], damage[1]); + } +} diff --git a/test/battle/ability/gulp_missile.c b/test/battle/ability/gulp_missile.c index 2ec9acc61b..7ccf1063b5 100644 --- a/test/battle/ability/gulp_missile.c +++ b/test/battle/ability/gulp_missile.c @@ -116,7 +116,7 @@ SINGLE_BATTLE_TEST("(Gulp Missile) Cramorant in Gorging paralyzes the target if } SINGLE_BATTLE_TEST("(Gulp Missile) triggers even if the user is fainted by opposing mon") -{ +{ GIVEN { PLAYER(SPECIES_CRAMORANT) { HP(1); MaxHP(250); Ability(ABILITY_GULP_MISSILE); } PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/ability/harvest.c b/test/battle/ability/harvest.c index 9fb969b036..f19e0715de 100644 --- a/test/battle/ability/harvest.c +++ b/test/battle/ability/harvest.c @@ -1,17 +1,264 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Harvest has a 50% chance to restore a Berry at the end of the turn"); -TO_DO_BATTLE_TEST("Harvest always restores a Berry in Sunlight"); -TO_DO_BATTLE_TEST("Harvest restores a Berry even after being switched out and back in"); -TO_DO_BATTLE_TEST("Harvest restores a Berry consumed by Fling"); -TO_DO_BATTLE_TEST("Harvest restores a Berry consumed by Natural Gift"); +ASSUMPTIONS +{ + ASSUME(gItemsInfo[ITEM_SITRUS_BERRY].holdEffect == HOLD_EFFECT_RESTORE_PCT_HP); + ASSUME(I_SITRUS_BERRY_HEAL >= GEN_4); + ASSUME(gMovesInfo[MOVE_SUNNY_DAY].effect == EFFECT_SUNNY_DAY); +} + +SINGLE_BATTLE_TEST("Harvest has a 50% chance to restore a Berry at the end of the turn") +{ + PASSES_RANDOMLY(1, 2, RNG_HARVEST); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_EXEGGUTOR) { Ability(ABILITY_HARVEST); MaxHP(500); HP(251); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + ABILITY_POPUP(opponent, ABILITY_HARVEST); + } THEN { + EXPECT_EQ(opponent->item, ITEM_SITRUS_BERRY); + } +} + +SINGLE_BATTLE_TEST("Harvest always restores a Berry in Sunlight") +{ + PASSES_RANDOMLY(1, 1, RNG_HARVEST); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_EXEGGUTOR) { Ability(ABILITY_HARVEST); MaxHP(500); HP(251); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_SUNNY_DAY); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, opponent); + ABILITY_POPUP(opponent, ABILITY_HARVEST); + } THEN { + EXPECT_EQ(opponent->item, ITEM_SITRUS_BERRY); + } +} + +SINGLE_BATTLE_TEST("Harvest doesn't always restore a Berry if Cloud Nine/Air Lock is on the field") +{ + PASSES_RANDOMLY(1, 2, RNG_HARVEST); + GIVEN { + PLAYER(SPECIES_GOLDUCK) { Ability(ABILITY_CLOUD_NINE); } + OPPONENT(SPECIES_EXEGGUTOR) { Ability(ABILITY_HARVEST); MaxHP(500); HP(251); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_SUNNY_DAY); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, opponent); + NOT ABILITY_POPUP(opponent, ABILITY_HARVEST); + } THEN { + EXPECT_EQ(opponent->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Harvest restores a Berry even after being switched out and back in") +{ + ASSUME(gMovesInfo[MOVE_PARTING_SHOT].effect == EFFECT_PARTING_SHOT); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_EXEGGUTOR) { Ability(ABILITY_HARVEST); MaxHP(500); HP(251); Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_PARTING_SHOT); SEND_OUT(opponent, 1); } + TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, MOVE_PARTING_SHOT); SEND_OUT(opponent, 0); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, player); + ABILITY_POPUP(opponent, ABILITY_HARVEST); + } THEN { + EXPECT_EQ(opponent->item, ITEM_SITRUS_BERRY); + } +} + +SINGLE_BATTLE_TEST("Harvest restores a Berry consumed by Fling") +{ + ASSUME(gMovesInfo[MOVE_FLING].effect == EFFECT_FLING); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_EXEGGUTOR) { Ability(ABILITY_HARVEST); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, MOVE_FLING); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, opponent); + ABILITY_POPUP(opponent, ABILITY_HARVEST); + } THEN { + EXPECT_EQ(opponent->item, ITEM_SITRUS_BERRY); + } +} + +SINGLE_BATTLE_TEST("Harvest restores a Berry consumed by Natural Gift") +{ + ASSUME(gMovesInfo[MOVE_NATURAL_GIFT].effect == EFFECT_NATURAL_GIFT); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_EXEGGUTOR) { Ability(ABILITY_HARVEST); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, MOVE_NATURAL_GIFT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_NATURAL_GIFT, opponent); + ABILITY_POPUP(opponent, ABILITY_HARVEST); + } THEN { + EXPECT_EQ(opponent->item, ITEM_SITRUS_BERRY); + } +} + TO_DO_BATTLE_TEST("Harvest only works once per turn"); // Check for berries that are consumed immediately, like Pecha Berry -TO_DO_BATTLE_TEST("Harvest doesn't restore a Berry when destroyed by Incinerate"); -TO_DO_BATTLE_TEST("Harvest doesn't restore a Berry when knocked off by Knock Off"); -TO_DO_BATTLE_TEST("Harvest doesn't restore a Berry when eaten by Bug Bite/Pluck"); -TO_DO_BATTLE_TEST("Harvest doesn't restore a Berry that's collected via Pickup"); -TO_DO_BATTLE_TEST("Harvest order is affected by speed"); -TO_DO_BATTLE_TEST("Harvest doesn't restore a Berry when transfered to another Pokémon"); -TO_DO_BATTLE_TEST("Harvest can restore a Berry that was transferred from another Pokémon"); -TO_DO_BATTLE_TEST("Harvest can only restore the newest berry consumed that was transferred from another Pokémon instead of its original Berry"); + +SINGLE_BATTLE_TEST("Harvest doesn't restore a Berry when destroyed by Incinerate") +{ + PASSES_RANDOMLY(1, 1, RNG_HARVEST); + ASSUME(MoveHasAdditionalEffect(MOVE_INCINERATE, MOVE_EFFECT_INCINERATE)); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_EXEGGUTOR) { Ability(ABILITY_HARVEST); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_INCINERATE); MOVE(opponent, MOVE_SUNNY_DAY); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_INCINERATE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, opponent); + NOT ABILITY_POPUP(opponent, ABILITY_HARVEST); + } THEN { + EXPECT_EQ(opponent->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Harvest doesn't restore a Berry when knocked off by Knock Off") +{ + PASSES_RANDOMLY(1, 1, RNG_HARVEST); + ASSUME(MoveHasAdditionalEffect(MOVE_KNOCK_OFF, MOVE_EFFECT_KNOCK_OFF)); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_EXEGGUTOR) { Ability(ABILITY_HARVEST); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_KNOCK_OFF); MOVE(opponent, MOVE_SUNNY_DAY); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_KNOCK_OFF, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, opponent); + NOT ABILITY_POPUP(opponent, ABILITY_HARVEST); + } THEN { + EXPECT_EQ(opponent->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Harvest doesn't restore a Berry when eaten by Bug Bite/Pluck") +{ + PASSES_RANDOMLY(1, 1, RNG_HARVEST); + ASSUME(MoveHasAdditionalEffect(MOVE_BUG_BITE, MOVE_EFFECT_BUG_BITE)); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_EXEGGUTOR) { Ability(ABILITY_HARVEST); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_BUG_BITE); MOVE(opponent, MOVE_SUNNY_DAY); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BUG_BITE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, opponent); + NOT ABILITY_POPUP(opponent, ABILITY_HARVEST); + } THEN { + EXPECT_EQ(opponent->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Harvest doesn't restore a Berry that's collected via Pickup") +{ + GIVEN { + PLAYER(SPECIES_ZIGZAGOON) { Speed(50); Ability(ABILITY_PICKUP); } + OPPONENT(SPECIES_EXEGGUTOR) { Speed(10); Ability(ABILITY_HARVEST); MaxHP(500); HP(251); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_SUNNY_DAY); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, opponent); + ABILITY_POPUP(player, ABILITY_PICKUP); + MESSAGE("Zigzagoon found one Sitrus Berry!"); + NOT ABILITY_POPUP(opponent, ABILITY_HARVEST); + } THEN { + EXPECT_EQ(player->item, ITEM_SITRUS_BERRY); + EXPECT_EQ(opponent->item, ITEM_NONE); + } +} + +DOUBLE_BATTLE_TEST("Harvest order is affected by speed") +{ + GIVEN { + PLAYER(SPECIES_EXEGGUTOR) { Speed(2); Ability(ABILITY_HARVEST); MaxHP(500); HP(251); Item(ITEM_SITRUS_BERRY); } + PLAYER(SPECIES_WOBBUFFET) { Speed(5); } + OPPONENT(SPECIES_EXEGGUTOR) { Speed(10); Ability(ABILITY_HARVEST); MaxHP(500); HP(251); Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(50); } + } WHEN { + TURN { MOVE(playerRight, MOVE_BULLDOZE); MOVE(playerLeft, MOVE_SUNNY_DAY); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BULLDOZE, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, playerLeft); + ABILITY_POPUP(opponentLeft, ABILITY_HARVEST); + ABILITY_POPUP(playerLeft, ABILITY_HARVEST); + } THEN { + EXPECT_EQ(opponentLeft->item, ITEM_SITRUS_BERRY); + EXPECT_EQ(playerLeft->item, ITEM_SITRUS_BERRY); + } +} + +SINGLE_BATTLE_TEST("Harvest doesn't restore a Berry when transfered to another Pokémon") +{ + ASSUME(gMovesInfo[MOVE_TRICK].effect == EFFECT_TRICK); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_EXEGGUTOR) { Ability(ABILITY_HARVEST); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, MOVE_TRICK); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TRICK, opponent); + NOT ABILITY_POPUP(opponent, ABILITY_HARVEST); + } THEN { + EXPECT_EQ(opponent->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Harvest can restore a Berry that was transferred from another Pokémon") +{ + ASSUME(gMovesInfo[MOVE_TRICK].effect == EFFECT_TRICK); + GIVEN { + PLAYER(SPECIES_TORKOAL) { Ability(ABILITY_DROUGHT); Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_EXEGGUTOR) { Ability(ABILITY_HARVEST); HP(100); MaxHP(500); } + } WHEN { + TURN { MOVE(opponent, MOVE_TRICK); MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TRICK, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + ABILITY_POPUP(opponent, ABILITY_HARVEST); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + } THEN { + EXPECT_GT(opponent->hp, opponent->maxHP / 2); // eats 2 Sitrus + } +} + +SINGLE_BATTLE_TEST("Harvest can only restore the newest berry consumed that was transferred from another Pokémon instead of its original Berry") +{ + ASSUME(gMovesInfo[MOVE_TRICK].effect == EFFECT_TRICK); + ASSUME(gItemsInfo[ITEM_APICOT_BERRY].holdEffect == HOLD_EFFECT_SP_DEFENSE_UP); + GIVEN { + PLAYER(SPECIES_TORKOAL) { Ability(ABILITY_DROUGHT); Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_EXEGGUTOR) { Ability(ABILITY_HARVEST); HP(100); MaxHP(500); Item(ITEM_APICOT_BERRY); } + } WHEN { + TURN { MOVE(opponent, MOVE_TRICK); MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TRICK, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + ABILITY_POPUP(opponent, ABILITY_HARVEST); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + } THEN { + EXPECT_GT(opponent->hp, opponent->maxHP / 2); // eats 2 Sitrus + } +} diff --git a/test/battle/ability/hydration.c b/test/battle/ability/hydration.c index 2dca490c02..7d16ad04ae 100644 --- a/test/battle/ability/hydration.c +++ b/test/battle/ability/hydration.c @@ -14,3 +14,5 @@ SINGLE_BATTLE_TEST("Hydration cures non-volatile Status conditions if it is rain STATUS_ICON(player, none: TRUE); } } + +TO_DO_BATTLE_TEST("Hydration doesn't cure status conditions if Cloud Nine/Air Lock is on the field"); diff --git a/test/battle/ability/ice_body.c b/test/battle/ability/ice_body.c index 1aa7c80a4d..3f278a50cd 100644 --- a/test/battle/ability/ice_body.c +++ b/test/battle/ability/ice_body.c @@ -1,13 +1,21 @@ #include "global.h" #include "test/battle.h" +ASSUMPTIONS { + ASSUME(gMovesInfo[MOVE_HAIL].effect == EFFECT_HAIL); + ASSUME(gMovesInfo[MOVE_SNOWSCAPE].effect == EFFECT_SNOWSCAPE); +} + SINGLE_BATTLE_TEST("Ice Body prevents damage from hail") { + u32 move; + PARAMETRIZE { move = MOVE_HAIL; } + PARAMETRIZE { move = MOVE_SNOWSCAPE; } GIVEN { PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_GLALIE) { Ability(ABILITY_ICE_BODY); } } WHEN { - TURN { MOVE(player, MOVE_HAIL); MOVE(opponent, MOVE_SKILL_SWAP); } + TURN { MOVE(player, move); MOVE(opponent, MOVE_SKILL_SWAP); } } SCENE { NONE_OF { HP_BAR(player); } } @@ -15,14 +23,32 @@ SINGLE_BATTLE_TEST("Ice Body prevents damage from hail") SINGLE_BATTLE_TEST("Ice Body recovers 1/16th of Max HP in hail.") { + u32 move; + PARAMETRIZE { move = MOVE_HAIL; } + PARAMETRIZE { move = MOVE_SNOWSCAPE; } GIVEN { PLAYER(SPECIES_GLALIE) { Ability(ABILITY_ICE_BODY); HP(1); MaxHP(100); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(opponent, MOVE_HAIL); } + TURN { MOVE(opponent, move); } } SCENE { ABILITY_POPUP(player, ABILITY_ICE_BODY); HP_BAR(player, damage: -(100 / 16)); MESSAGE("Glalie's Ice Body healed it a little bit!"); } } + +SINGLE_BATTLE_TEST("Ice Body doesn't recover HP if Cloud Nine/Air Lock is on the field") +{ + u32 move; + PARAMETRIZE { move = MOVE_HAIL; } + PARAMETRIZE { move = MOVE_SNOWSCAPE; } + GIVEN { + PLAYER(SPECIES_GLALIE) { Ability(ABILITY_ICE_BODY); HP(1); MaxHP(100); } + OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_CLOUD_NINE); } + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + NOT ABILITY_POPUP(player, ABILITY_ICE_BODY); + } +} diff --git a/test/battle/ability/ice_face.c b/test/battle/ability/ice_face.c new file mode 100644 index 0000000000..54a307754c --- /dev/null +++ b/test/battle/ability/ice_face.c @@ -0,0 +1,137 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Ice Face blocks physical moves, changing Eiscue into its Noice Face form") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL); + PLAYER(SPECIES_EISCUE); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ABILITY_POPUP(player, ABILITY_ICE_FACE); + MESSAGE("Eiscue transformed!"); + } +} + +SINGLE_BATTLE_TEST("Ice Face does not block special moves, Eiscue stays in Ice Face form") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL); + ASSUME(gMovesInfo[MOVE_EMBER].category == DAMAGE_CATEGORY_SPECIAL); + PLAYER(SPECIES_EISCUE); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_EMBER); } + } SCENE { + NOT ABILITY_POPUP(player, ABILITY_ICE_FACE); + } +} + +SINGLE_BATTLE_TEST("Ice Face is restored if hail or snow begins while Noice Face Eiscue is out") +{ + u32 move; + PARAMETRIZE { move = MOVE_SNOWSCAPE; } + PARAMETRIZE { move = MOVE_HAIL; } + GIVEN { + ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL); + ASSUME(gMovesInfo[MOVE_SNOWSCAPE].effect == EFFECT_SNOWSCAPE); + ASSUME(gMovesInfo[MOVE_HAIL].effect == EFFECT_HAIL); + PLAYER(SPECIES_EISCUE); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + TURN { MOVE(opponent, move); } + TURN { MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ABILITY_POPUP(player, ABILITY_ICE_FACE); + MESSAGE("Eiscue transformed!"); + ABILITY_POPUP(player, ABILITY_ICE_FACE); + MESSAGE("Eiscue transformed!"); + ABILITY_POPUP(player, ABILITY_ICE_FACE); + MESSAGE("Eiscue transformed!"); + } +} + +SINGLE_BATTLE_TEST("Ice Face is restored if Noice Face Eiscue is sent in while hail or snow is active") +{ + u32 move; + PARAMETRIZE { move = MOVE_SNOWSCAPE; } + PARAMETRIZE { move = MOVE_HAIL; } + GIVEN { + ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL); + ASSUME(gMovesInfo[MOVE_SNOWSCAPE].effect == EFFECT_SNOWSCAPE); + ASSUME(gMovesInfo[MOVE_HAIL].effect == EFFECT_HAIL); + PLAYER(SPECIES_EISCUE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_TACKLE); } + TURN { SWITCH(player, 1); MOVE(opponent, move); } + TURN { SWITCH(player, 0); MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ABILITY_POPUP(player, ABILITY_ICE_FACE); + MESSAGE("Eiscue transformed!"); + ABILITY_POPUP(player, ABILITY_ICE_FACE); + MESSAGE("Eiscue transformed!"); + ABILITY_POPUP(player, ABILITY_ICE_FACE); + MESSAGE("Eiscue transformed!"); + } +} + +SINGLE_BATTLE_TEST("Ice Face is not restored if Eiscue changes into Noice Face form while there's already hail or snow") +{ + u32 move; + PARAMETRIZE { move = MOVE_SNOWSCAPE; } + PARAMETRIZE { move = MOVE_HAIL; } + GIVEN { + ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL); + ASSUME(gMovesInfo[MOVE_SNOWSCAPE].effect == EFFECT_SNOWSCAPE); + ASSUME(gMovesInfo[MOVE_HAIL].effect == EFFECT_HAIL); + PLAYER(SPECIES_EISCUE) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, move); MOVE(opponent, MOVE_TACKLE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ABILITY_POPUP(player, ABILITY_ICE_FACE); + MESSAGE("Eiscue transformed!"); + MESSAGE("Eiscue used Celebrate!"); + MESSAGE("Eiscue fainted!"); + } +} + +SINGLE_BATTLE_TEST("Ice Face form change persists after switching out") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL); + PLAYER(SPECIES_EISCUE) { HP(1); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_CELEBRATE); } + TURN { SWITCH(player, 0); MOVE(opponent, MOVE_TACKLE); SEND_OUT(player, 1); } + } SCENE { + ABILITY_POPUP(player, ABILITY_ICE_FACE); + MESSAGE("Eiscue transformed!"); + MESSAGE("Eiscue fainted!"); + } +} + +SINGLE_BATTLE_TEST("Ice Face doesn't transform Eiscue if Cloud Nine/Air Lock is on the field") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL); + PLAYER(SPECIES_EISCUE) { HP(1); } + OPPONENT(SPECIES_RAYQUAZA) { Ability(ABILITY_AIR_LOCK); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_TACKLE); } + TURN { MOVE(player, MOVE_SNOWSCAPE); MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ABILITY_POPUP(player, ABILITY_ICE_FACE); + MESSAGE("Eiscue transformed!"); + MESSAGE("Eiscue fainted!"); + } +} diff --git a/test/battle/ability/leaf_guard.c b/test/battle/ability/leaf_guard.c index 6c559ea48a..2c55236def 100644 --- a/test/battle/ability/leaf_guard.c +++ b/test/battle/ability/leaf_guard.c @@ -27,6 +27,8 @@ SINGLE_BATTLE_TEST("Leaf Guard prevents non-volatile status conditions in sun") } } +TO_DO_BATTLE_TEST("Leaf Guard doesn't prevent non-volatile status conditions if Cloud Nine/Air Lock is on the field"); + SINGLE_BATTLE_TEST("Leaf Guard prevents status conditions from Flame Orb and Toxic Orb") { u32 item; @@ -49,6 +51,8 @@ SINGLE_BATTLE_TEST("Leaf Guard prevents status conditions from Flame Orb and Tox } } +TO_DO_BATTLE_TEST("Leaf Guard doesn't prevent status conditions from Flame Orb and Toxic Orb if Cloud Nine/Air Lock is on the field"); + SINGLE_BATTLE_TEST("Leaf Guard prevents Rest during sun") { GIVEN { @@ -66,3 +70,5 @@ SINGLE_BATTLE_TEST("Leaf Guard prevents Rest during sun") } } } + +TO_DO_BATTLE_TEST("Leaf Guard doesn't prevent Rest if Cloud Nine/Air Lock is on the field"); diff --git a/test/battle/ability/magic_guard.c b/test/battle/ability/magic_guard.c index 69e8bac9c7..5579652265 100644 --- a/test/battle/ability/magic_guard.c +++ b/test/battle/ability/magic_guard.c @@ -13,5 +13,5 @@ SINGLE_BATTLE_TEST("Magic Guard prevents recoil damage to the user") ANIMATION(ANIM_TYPE_MOVE, MOVE_DOUBLE_EDGE, player); HP_BAR(opponent); NOT HP_BAR(player); - } + } } diff --git a/test/battle/ability/moxie.c b/test/battle/ability/moxie.c index b60a11507a..79b1fc989f 100644 --- a/test/battle/ability/moxie.c +++ b/test/battle/ability/moxie.c @@ -1,12 +1,15 @@ #include "global.h" #include "test/battle.h" -DOUBLE_BATTLE_TEST("Moxie raises Attack by one stage after directly causing a Pokemon to faint") +DOUBLE_BATTLE_TEST("Moxie/Chilling Neigh raises Attack by one stage after directly causing a Pokemon to faint") { - ASSUME(gMovesInfo[MOVE_EARTHQUAKE].target == MOVE_TARGET_FOES_AND_ALLY); - + u32 species = 0, ability = 0, abilityPopUp = 0; + PARAMETRIZE { species = SPECIES_SALAMENCE; ability = ABILITY_MOXIE; abilityPopUp = ABILITY_MOXIE; } + PARAMETRIZE { species = SPECIES_GLASTRIER; ability = ABILITY_CHILLING_NEIGH; abilityPopUp = ABILITY_CHILLING_NEIGH; } + PARAMETRIZE { species = SPECIES_CALYREX_ICE_RIDER; ability = ABILITY_AS_ONE_ICE_RIDER; abilityPopUp = ABILITY_CHILLING_NEIGH; } GIVEN { - PLAYER(SPECIES_SALAMENCE) { Ability(ABILITY_MOXIE); } + ASSUME(gMovesInfo[MOVE_EARTHQUAKE].target == MOVE_TARGET_FOES_AND_ALLY); + PLAYER(species) { Ability(ability); } PLAYER(SPECIES_SNORUNT) { HP(1); } OPPONENT(SPECIES_GLALIE) { HP(1); } OPPONENT(SPECIES_ABRA) { HP(1); } @@ -23,19 +26,28 @@ DOUBLE_BATTLE_TEST("Moxie raises Attack by one stage after directly causing a Po MESSAGE("Foe Glalie fainted!"); MESSAGE("Foe Abra fainted!"); } - ABILITY_POPUP(playerLeft, ABILITY_MOXIE); + ABILITY_POPUP(playerLeft, abilityPopUp); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); - MESSAGE("Salamence's Moxie raised its Attack!"); + if (species == SPECIES_SALAMENCE) + MESSAGE("Salamence's Moxie raised its Attack!"); + else if (species == SPECIES_GLASTRIER) + MESSAGE("Glastrier's Chilling Neigh raised its Attack!"); + else + MESSAGE("Calyrex's Chilling Neigh raised its Attack!"); } } THEN { EXPECT_EQ(playerLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 3); } } -DOUBLE_BATTLE_TEST("Moxie does not trigger if Pokemon faint to indirect damage or damage from other Pokemon") +DOUBLE_BATTLE_TEST("Moxie/Chilling Neigh does not trigger if Pokemon faint to indirect damage or damage from other Pokemon") { + u32 species = 0, ability = 0, abilityPopUp = 0; + PARAMETRIZE { species = SPECIES_SALAMENCE; ability = ABILITY_MOXIE; abilityPopUp = ABILITY_MOXIE; } + PARAMETRIZE { species = SPECIES_GLASTRIER; ability = ABILITY_CHILLING_NEIGH; abilityPopUp = ABILITY_CHILLING_NEIGH; } + PARAMETRIZE { species = SPECIES_CALYREX_ICE_RIDER; ability = ABILITY_AS_ONE_ICE_RIDER; abilityPopUp = ABILITY_CHILLING_NEIGH; } GIVEN { - PLAYER(SPECIES_SALAMENCE) { Ability(ABILITY_MOXIE); } + PLAYER(species) { Ability(ability); } PLAYER(SPECIES_SNORUNT) { HP(1); Status1(STATUS1_POISON); } OPPONENT(SPECIES_GLALIE) { HP(1); Status1(STATUS1_BURN); } OPPONENT(SPECIES_ABRA) { HP(1); } @@ -53,9 +65,11 @@ DOUBLE_BATTLE_TEST("Moxie does not trigger if Pokemon faint to indirect damage o MESSAGE("Foe Abra fainted!"); } NONE_OF { - ABILITY_POPUP(playerLeft, ABILITY_MOXIE); + ABILITY_POPUP(playerLeft, abilityPopUp); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); MESSAGE("Salamence's Moxie raised its Attack!"); + MESSAGE("Glastrier's Chilling Neigh raised its Attack!"); + MESSAGE("Calyrex's Chilling Neigh raised its Attack!"); } } } THEN { @@ -63,12 +77,15 @@ DOUBLE_BATTLE_TEST("Moxie does not trigger if Pokemon faint to indirect damage o } } -SINGLE_BATTLE_TEST("Moxie does not trigger when already at maximum Attack stage") +SINGLE_BATTLE_TEST("Moxie/Chilling Neigh does not trigger when already at maximum Attack stage") { - ASSUME(gMovesInfo[MOVE_BELLY_DRUM].effect == EFFECT_BELLY_DRUM); - + u32 species = 0, ability = 0, abilityPopUp = 0; + PARAMETRIZE { species = SPECIES_SALAMENCE; ability = ABILITY_MOXIE; abilityPopUp = ABILITY_MOXIE; } + PARAMETRIZE { species = SPECIES_GLASTRIER; ability = ABILITY_CHILLING_NEIGH; abilityPopUp = ABILITY_CHILLING_NEIGH; } + PARAMETRIZE { species = SPECIES_CALYREX_ICE_RIDER; ability = ABILITY_AS_ONE_ICE_RIDER; abilityPopUp = ABILITY_CHILLING_NEIGH; } GIVEN { - PLAYER(SPECIES_SALAMENCE) { Ability(ABILITY_MOXIE); } + ASSUME(gMovesInfo[MOVE_BELLY_DRUM].effect == EFFECT_BELLY_DRUM); + PLAYER(species) { Ability(ability); } OPPONENT(SPECIES_SNORUNT) { HP(1); } OPPONENT(SPECIES_SNORUNT); } WHEN { @@ -77,28 +94,38 @@ SINGLE_BATTLE_TEST("Moxie does not trigger when already at maximum Attack stage" } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_BELLY_DRUM, player); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Salamence cut its own HP and maximized ATTACK!"); + if (species == SPECIES_SALAMENCE) + MESSAGE("Salamence cut its own HP and maximized ATTACK!"); + else if (species == SPECIES_GLASTRIER) + MESSAGE("Glastrier cut its own HP and maximized ATTACK!"); + else + MESSAGE("Calyrex cut its own HP and maximized ATTACK!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, player); MESSAGE("Foe Snorunt fainted!"); - NONE_OF { - ABILITY_POPUP(player, ABILITY_MOXIE); + NONE_OF { + ABILITY_POPUP(player, abilityPopUp); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); MESSAGE("Salamence's Moxie raised its Attack!"); + MESSAGE("Glastrier's Chilling Neigh raised its Attack!"); + MESSAGE("Calyrex's Chilling Neigh raised its Attack!"); } } THEN { EXPECT_EQ(player->statStages[STAT_ATK], MAX_STAT_STAGE); } } -DOUBLE_BATTLE_TEST("Moxie does not increase damage done by the same move that causes another Pokemon to faint") +DOUBLE_BATTLE_TEST("Moxie/Chilling Neigh does not increase damage done by the same move that causes another Pokemon to faint") { s16 damage[2]; - - ASSUME(gMovesInfo[MOVE_EARTHQUAKE].target == MOVE_TARGET_FOES_AND_ALLY); + u32 species = 0, ability = 0, abilityPopUp = 0; + PARAMETRIZE { species = SPECIES_SALAMENCE; ability = ABILITY_MOXIE; abilityPopUp = ABILITY_MOXIE; } + PARAMETRIZE { species = SPECIES_GLASTRIER; ability = ABILITY_CHILLING_NEIGH; abilityPopUp = ABILITY_CHILLING_NEIGH; } + PARAMETRIZE { species = SPECIES_CALYREX_ICE_RIDER; ability = ABILITY_AS_ONE_ICE_RIDER; abilityPopUp = ABILITY_CHILLING_NEIGH; } KNOWN_FAILING; // Requires simultaneous damage implementation GIVEN { - PLAYER(SPECIES_SALAMENCE) { Ability(ABILITY_MOXIE); } + ASSUME(gMovesInfo[MOVE_EARTHQUAKE].target == MOVE_TARGET_FOES_AND_ALLY); + PLAYER(species) { Ability(ability); } PLAYER(SPECIES_ABRA) { HP(1); } OPPONENT(SPECIES_GLALIE); OPPONENT(SPECIES_GLALIE); @@ -110,9 +137,14 @@ DOUBLE_BATTLE_TEST("Moxie does not increase damage done by the same move that ca HP_BAR(opponentLeft, captureDamage: &damage[0]); HP_BAR(playerRight); MESSAGE("Abra fainted!"); - ABILITY_POPUP(playerLeft, ABILITY_MOXIE); + ABILITY_POPUP(playerLeft, abilityPopUp); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); - MESSAGE("Salamence's Moxie raised its Attack!"); + if (species == SPECIES_SALAMENCE) + MESSAGE("Salamence's Moxie raised its Attack!"); + else if (species == SPECIES_GLASTRIER) + MESSAGE("Glastrier's Chilling Neigh raised its Attack!"); + else + MESSAGE("Calyrex's Chilling Neigh raised its Attack!"); HP_BAR(opponentRight, captureDamage: &damage[1]); } THEN { EXPECT_EQ(playerLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); diff --git a/test/battle/ability/normalize.c b/test/battle/ability/normalize.c new file mode 100644 index 0000000000..d3e8df6bee --- /dev/null +++ b/test/battle/ability/normalize.c @@ -0,0 +1,16 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Normalize tuns a move into a Normal-type move"); +TO_DO_BATTLE_TEST("Normalize boosts power of both affected and originally Normal-type moves by 20% (Gen7+)"); +TO_DO_BATTLE_TEST("Normalize affects status moves"); // Eg. Thunder Wave can affect Ground types +TO_DO_BATTLE_TEST("Normalize makes Flying Press do Normal/Flying damage"); +TO_DO_BATTLE_TEST("Normalize still makes Freeze-Dry do super effective damage to Water-type Pokémon"); +TO_DO_BATTLE_TEST("Normalize-affected moves become Electric-type under Electrify's effect"); +TO_DO_BATTLE_TEST("Normalize-affected moves become Electric-type under Ion Deluge's effect"); +TO_DO_BATTLE_TEST("Normalize doesn't affect Hidden Power's type"); +TO_DO_BATTLE_TEST("Normalize doesn't affect Weather Ball's type"); +TO_DO_BATTLE_TEST("Normalize doesn't affect Natural Gift's type"); +TO_DO_BATTLE_TEST("Normalize doesn't affect Judgment/Techno Blast/Multi-Attack's type"); +TO_DO_BATTLE_TEST("Normalize doesn't affect Terrain Pulse's type"); +TO_DO_BATTLE_TEST("Normalize doesn't affect damaging Z-Move types"); diff --git a/test/battle/ability/orichalcum_pulse.c b/test/battle/ability/orichalcum_pulse.c new file mode 100644 index 0000000000..295e0db23c --- /dev/null +++ b/test/battle/ability/orichalcum_pulse.c @@ -0,0 +1,5 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Orichalcum Pulse sets up sun for 5 turns"); +TO_DO_BATTLE_TEST("Orichalcum Pulse boosts the Pokémon's Attack by 33% in sun, even if it's holding an Utility Umbrella"); diff --git a/test/battle/ability/pickup.c b/test/battle/ability/pickup.c new file mode 100644 index 0000000000..57f6429feb --- /dev/null +++ b/test/battle/ability/pickup.c @@ -0,0 +1,295 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItemsInfo[ITEM_SITRUS_BERRY].holdEffect == HOLD_EFFECT_RESTORE_PCT_HP); + ASSUME(I_SITRUS_BERRY_HEAL >= GEN_4); +} + +SINGLE_BATTLE_TEST("Pickup grants an item used by another Pokémon") +{ + GIVEN { + PLAYER(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); } + OPPONENT(SPECIES_WOBBUFFET) { MaxHP(100); HP(51); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + ABILITY_POPUP(player, ABILITY_PICKUP); + MESSAGE("Zigzagoon found one Sitrus Berry!"); + } THEN { + EXPECT_EQ(player->item, ITEM_SITRUS_BERRY); + } +} + +SINGLE_BATTLE_TEST("Pickup doesn't grant the user their item") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); MaxHP(500); HP(251); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_PICKUP); + MESSAGE("Zigzagoon found one Sitrus Berry!"); + } + } THEN { + EXPECT_EQ(opponent->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Pickup doesn't grant another Pokémon's popped Air Balloon") +{ + ASSUME(gItemsInfo[ITEM_AIR_BALLOON].holdEffect == HOLD_EFFECT_AIR_BALLOON); + GIVEN { + PLAYER(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_AIR_BALLOON); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + NONE_OF { + ABILITY_POPUP(player, ABILITY_PICKUP); + MESSAGE("Zigzagoon found one Air Balloon!"); + } + } THEN { + EXPECT_EQ(opponent->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Pickup doesn't grant an item not used that turn") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); } + OPPONENT(SPECIES_WOBBUFFET) { MaxHP(100); HP(51); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + TURN { SWITCH(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + NONE_OF { + ABILITY_POPUP(player, ABILITY_PICKUP); + MESSAGE("Zigzagoon found one Sitrus Berry!"); + } + } THEN { + EXPECT_EQ(player->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Pickup doesn't grant an item after its holder faints") +{ + GIVEN { + PLAYER(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); } + OPPONENT(SPECIES_WOBBUFFET) { MaxHP(100); HP(51); Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { MaxHP(100); HP(51); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_MEMENTO); SEND_OUT(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + NONE_OF { + ABILITY_POPUP(player, ABILITY_PICKUP); + MESSAGE("Zigzagoon found one Sitrus Berry!"); + } + } THEN { + EXPECT_EQ(player->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Pickup doesn't grant an used item if holder is replaced") +{ + ASSUME(gMovesInfo[MOVE_PARTING_SHOT].effect == EFFECT_PARTING_SHOT); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); } + OPPONENT(SPECIES_WOBBUFFET) { MaxHP(300); HP(151); Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { MaxHP(300); HP(151); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_PARTING_SHOT); SEND_OUT(opponent, 1); } + TURN { MOVE(player, MOVE_U_TURN); SEND_OUT(player, 1); MOVE(opponent, MOVE_PARTING_SHOT); SEND_OUT(opponent, 0); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PARTING_SHOT, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PARTING_SHOT, opponent); + NONE_OF { + ABILITY_POPUP(player, ABILITY_PICKUP); + MESSAGE("Zigzagoon found one Sitrus Berry!"); + } + } THEN { + EXPECT_EQ(player->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Pickup doesn't grant an item if it destroyed the item with Incinerate") +{ + ASSUME(MoveHasAdditionalEffect(MOVE_INCINERATE, MOVE_EFFECT_INCINERATE)); + GIVEN { + PLAYER(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_INCINERATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_INCINERATE, player); + NONE_OF { + ABILITY_POPUP(player, ABILITY_PICKUP); + MESSAGE("Zigzagoon found one Sitrus Berry!"); + } + } THEN { + EXPECT_EQ(player->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Pickup doesn't grant an item if it knocked off that item") +{ + ASSUME(MoveHasAdditionalEffect(MOVE_KNOCK_OFF, MOVE_EFFECT_KNOCK_OFF)); + GIVEN { + PLAYER(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_KNOCK_OFF); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_KNOCK_OFF, player); + NONE_OF { + ABILITY_POPUP(player, ABILITY_PICKUP); + MESSAGE("Zigzagoon found one Sitrus Berry!"); + } + } THEN { + EXPECT_EQ(player->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Pickup doesn't grant an item if the user eats it with Bug Bite/Pluck") +{ + ASSUME(MoveHasAdditionalEffect(MOVE_BUG_BITE, MOVE_EFFECT_BUG_BITE)); + GIVEN { + PLAYER(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_BUG_BITE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BUG_BITE, player); + NONE_OF { + ABILITY_POPUP(player, ABILITY_PICKUP); + MESSAGE("Zigzagoon found one Sitrus Berry!"); + } + } THEN { + EXPECT_EQ(player->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Pickup doesn't grant an used item if its user already restored it") +{ + ASSUME(gMovesInfo[MOVE_RECYCLE].effect == EFFECT_RECYCLE); + GIVEN { + PLAYER(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); } + OPPONENT(SPECIES_WOBBUFFET) { MaxHP(100); HP(51); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_RECYCLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_RECYCLE, opponent); + NONE_OF { + ABILITY_POPUP(player, ABILITY_PICKUP); + MESSAGE("Zigzagoon found one Sitrus Berry!"); + } + } THEN { + EXPECT_EQ(player->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Pickup restores an item that has been Flinged") +{ + ASSUME(gMovesInfo[MOVE_FLING].effect == EFFECT_FLING); + GIVEN { + PLAYER(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(opponent, MOVE_FLING); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, opponent); + ABILITY_POPUP(player, ABILITY_PICKUP); + MESSAGE("Zigzagoon found one Sitrus Berry!"); + } THEN { + EXPECT_EQ(player->item, ITEM_SITRUS_BERRY); + } +} + +SINGLE_BATTLE_TEST("Pickup restores an item that was used by Natural Gift") +{ + ASSUME(gMovesInfo[MOVE_NATURAL_GIFT].effect == EFFECT_NATURAL_GIFT); + GIVEN { + PLAYER(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(opponent, MOVE_NATURAL_GIFT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_NATURAL_GIFT, opponent); + ABILITY_POPUP(player, ABILITY_PICKUP); + MESSAGE("Zigzagoon found one Sitrus Berry!"); + } THEN { + EXPECT_EQ(player->item, ITEM_SITRUS_BERRY); + } +} + +DOUBLE_BATTLE_TEST("Pickup triggers based on Speed order") +{ + GIVEN { + PLAYER(SPECIES_ZIGZAGOON) { Speed(1); Ability(ABILITY_PICKUP); } + PLAYER(SPECIES_WOBBUFFET) { Speed(2); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(3); MaxHP(100); HP(51); Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_ZIGZAGOON) { Speed(50); Ability(ABILITY_PICKUP); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_TACKLE, target: opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerLeft); + ABILITY_POPUP(opponentRight, ABILITY_PICKUP); + NOT ABILITY_POPUP(playerLeft, ABILITY_PICKUP); + } THEN { + EXPECT_EQ(opponentRight->item, ITEM_SITRUS_BERRY); + EXPECT_EQ(playerLeft->item, ITEM_NONE); + } +} + +DOUBLE_BATTLE_TEST("Pickup grants a random item used by another Pokémon") +{ + PASSES_RANDOMLY(1, 3, RNG_PICKUP); + ASSUME(gItemsInfo[ITEM_WHITE_HERB].holdEffect == HOLD_EFFECT_RESTORE_STATS); + GIVEN { + PLAYER(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); } + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_WHITE_HERB); } + OPPONENT(SPECIES_WOBBUFFET) { MaxHP(100); HP(51); Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_WHITE_HERB); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_BULLDOZE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BULLDOZE, playerLeft); + ABILITY_POPUP(playerLeft, ABILITY_PICKUP); + } THEN { + EXPECT_EQ(playerLeft->item, ITEM_SITRUS_BERRY); + } +} + +DOUBLE_BATTLE_TEST("Pickup doesn't trigger more than once per turn") +{ + GIVEN { + PLAYER(SPECIES_ZIGZAGOON) { HP(1); Ability(ABILITY_PICKUP); } + PLAYER(SPECIES_WOBBUFFET) { MaxHP(100); HP(51); Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { MaxHP(100); HP(51); Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { MaxHP(100); HP(51); Item(ITEM_SITRUS_BERRY); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_BULLDOZE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BULLDOZE, playerLeft); + ABILITY_POPUP(playerLeft, ABILITY_PICKUP); + NOT ABILITY_POPUP(playerLeft, ABILITY_PICKUP); + } THEN { + EXPECT_EQ(playerLeft->item, ITEM_NONE); + EXPECT_GT(playerLeft->hp, 1); + EXPECT_LT(playerLeft->hp, playerLeft->maxHP/2); + } +} diff --git a/test/battle/ability/pixilate.c b/test/battle/ability/pixilate.c new file mode 100644 index 0000000000..97c9c37a0c --- /dev/null +++ b/test/battle/ability/pixilate.c @@ -0,0 +1,35 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_TACKLE].type == TYPE_NORMAL); + ASSUME(gMovesInfo[MOVE_TACKLE].power > 0); +} + +SINGLE_BATTLE_TEST("Pixilate turns a Normal-type move into a Fairy-type move") +{ + GIVEN { + PLAYER(SPECIES_DRAGONITE); + OPPONENT(SPECIES_ALTARIA) { Item(ITEM_ALTARIANITE); } + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE, gimmick: GIMMICK_MEGA); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_MEGA_EVOLUTION, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + MESSAGE("It's super effective!"); + } +} + +TO_DO_BATTLE_TEST("Pixilate can not turn certain moves into Fairy type moves"); +TO_DO_BATTLE_TEST("Pixilate boosts power of affected moves by 20% (Gen7+)"); +TO_DO_BATTLE_TEST("Pixilate boosts power of affected moves by 30% (Gen6)"); +TO_DO_BATTLE_TEST("(DYNAMAX) Pixilate turns Max Strike into Max Starfall when not used by Gigantamax Alcremie"); +TO_DO_BATTLE_TEST("(DYNAMAX) Pixilate doesn't turn Max Strike into Max Starfall when used by Gigantamax Alcremie, instead becoming G-Max Finale"); + +// Gen 6-7 +TO_DO_BATTLE_TEST("Pixilate overrides Electrify (Gen6-7)"); +TO_DO_BATTLE_TEST("Pixilate overrides Ion Deluge (Gen6-7)"); +// Gen 8+ +TO_DO_BATTLE_TEST("Pixilate doesn't override Electrify (Gen8+)"); +//TO_DO_BATTLE_TEST("Pixilate doesn't override Ion Deluge (Gen8+)"); // Ion Deluge doesn't exist in Gen 8+, but we probably could assume it behaves similar to under Electrify. TODO: Test by hacking SV. diff --git a/test/battle/ability/protosynthesis.c b/test/battle/ability/protosynthesis.c index 3cb35164ec..58f10b366f 100644 --- a/test/battle/ability/protosynthesis.c +++ b/test/battle/ability/protosynthesis.c @@ -99,3 +99,7 @@ SINGLE_BATTLE_TEST("Protosynthesis activates on switch-in") MESSAGE("Roaring Moon's Attack was heightened!"); } } + +TO_DO_BATTLE_TEST("Protosynthesis activates in sun before Booster Energy"); +TO_DO_BATTLE_TEST("Protosynthesis activates even if the Pokémon is holding an Utility Umbrella"); +TO_DO_BATTLE_TEST("Protosynthesis doesn't activate if Cloud Nine/Air Lock is on the field"); diff --git a/test/battle/ability/purifying_salt.c b/test/battle/ability/purifying_salt.c index e188262497..4c25321e5f 100644 --- a/test/battle/ability/purifying_salt.c +++ b/test/battle/ability/purifying_salt.c @@ -19,6 +19,24 @@ SINGLE_BATTLE_TEST("Purifying Salt halves damage from Ghost-type moves", s16 dam } } +SINGLE_BATTLE_TEST("Purifying Salt halves damage from dynamic Ghost-type moves", s16 damage) +{ + u16 ability; + PARAMETRIZE { ability = ABILITY_STURDY; } + PARAMETRIZE { ability = ABILITY_PURIFYING_SALT; } + GIVEN { + ASSUME(gMovesInfo[MOVE_TERA_BLAST].effect == EFFECT_TERA_BLAST); + PLAYER(SPECIES_WOBBUFFET) { TeraType(TYPE_GHOST); } + OPPONENT(SPECIES_GARGANACL) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_TERA_BLAST, gimmick: GIMMICK_TERA); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, UQ_4_12(0.5), results[1].damage); + } +} + SINGLE_BATTLE_TEST("Purifying Salt makes Rest fail") { GIVEN { diff --git a/test/battle/ability/rain_dish.c b/test/battle/ability/rain_dish.c index dd647f0eb9..93f642c633 100644 --- a/test/battle/ability/rain_dish.c +++ b/test/battle/ability/rain_dish.c @@ -1,6 +1,10 @@ #include "global.h" #include "test/battle.h" +ASSUMPTIONS { + ASSUME(gMovesInfo[MOVE_RAIN_DANCE].effect == EFFECT_RAIN_DANCE); +} + SINGLE_BATTLE_TEST("Rain Dish recovers 1/16th of Max HP in Rain") { GIVEN { @@ -11,6 +15,18 @@ SINGLE_BATTLE_TEST("Rain Dish recovers 1/16th of Max HP in Rain") } SCENE { ABILITY_POPUP(player, ABILITY_RAIN_DISH); MESSAGE("Ludicolo's Rain Dish restored its HP a little!"); - HP_BAR(player, damage: -(100 / 16)); + HP_BAR(player, damage: -(100 / 16)); + } +} + +SINGLE_BATTLE_TEST("Rain Dish doesn't recover HP if Cloud Nine/Air Lock is on the field") +{ + GIVEN { + PLAYER(SPECIES_LUDICOLO) { Ability(ABILITY_RAIN_DISH); HP(1); MaxHP(100); } + OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_CLOUD_NINE); } + } WHEN { + TURN { MOVE(opponent, MOVE_RAIN_DANCE); } + } SCENE { + NOT ABILITY_POPUP(player, ABILITY_RAIN_DISH); } } diff --git a/test/battle/ability/refrigerate.c b/test/battle/ability/refrigerate.c new file mode 100644 index 0000000000..dbbaa30eb8 --- /dev/null +++ b/test/battle/ability/refrigerate.c @@ -0,0 +1,34 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_TACKLE].type == TYPE_NORMAL); + ASSUME(gMovesInfo[MOVE_TACKLE].power > 0); +} + +SINGLE_BATTLE_TEST("Refrigerate turns a Normal-type move into a Ice-type move") +{ + GIVEN { + PLAYER(SPECIES_MEGANIUM); + OPPONENT(SPECIES_AMAURA) { Ability(ABILITY_REFRIGERATE); } + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + MESSAGE("It's super effective!"); + } +} + +TO_DO_BATTLE_TEST("Refrigerate can not turn certain moves into Ice type moves"); +TO_DO_BATTLE_TEST("Refrigerate boosts power of affected moves by 20% (Gen7+)"); +TO_DO_BATTLE_TEST("Refrigerate boosts power of affected moves by 30% (Gen6)"); +TO_DO_BATTLE_TEST("(DYNAMAX) Refrigerate turns Max Strike into Max Hailstorm when not used by Gigantamax Lapras"); +//TO_DO_BATTLE_TEST("(DYNAMAX) Refrigerate doesn't turn Max Strike into Max Hailstorm when used by Gigantamax Lapras, instead becoming G-Max Resonance"); // Marked in Bulbapedia as "needs research", so this assumes that it behaves like Pixilate. + +// Gen 6-7 +TO_DO_BATTLE_TEST("Refrigerate overrides Electrify (Gen6-7)"); +TO_DO_BATTLE_TEST("Refrigerate overrides Ion Deluge (Gen6-7)"); +// Gen 8+ +//TO_DO_BATTLE_TEST("Refrigerate doesn't override Electrify (Gen8+)"); // Bulbapedia doesn't list this effect, so it assumes it behaves like Pixilate. +//TO_DO_BATTLE_TEST("Refrigerate doesn't override Ion Deluge (Gen8+)"); // Ion Deluge doesn't exist in Gen 8+, but we probably could assume it behaves similar to under Electrify. TODO: Test by hacking SV. diff --git a/test/battle/ability/sand_force.c b/test/battle/ability/sand_force.c new file mode 100644 index 0000000000..e17722a885 --- /dev/null +++ b/test/battle/ability/sand_force.c @@ -0,0 +1,6 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Sand Force prevents damage from sandstorm"); +TO_DO_BATTLE_TEST("Sand Force increases the power of Rock-, Ground- and Steel-type moves by 30% in sandstorm"); +TO_DO_BATTLE_TEST("Sand Force increases move power if Cloud Nine/Air Lock is on the field"); diff --git a/test/battle/ability/sand_rush.c b/test/battle/ability/sand_rush.c new file mode 100644 index 0000000000..fa7695c129 --- /dev/null +++ b/test/battle/ability/sand_rush.c @@ -0,0 +1,6 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Sand Rush prevents damage from sandstorm"); +TO_DO_BATTLE_TEST("Sand Rush doubles speed from sandstorm"); +TO_DO_BATTLE_TEST("Sand Rush doesn't double speed if Cloud Nine/Air Lock is on the field"); diff --git a/test/battle/ability/sand_veil.c b/test/battle/ability/sand_veil.c index 9e4a634de2..f42c267273 100644 --- a/test/battle/ability/sand_veil.c +++ b/test/battle/ability/sand_veil.c @@ -28,3 +28,6 @@ SINGLE_BATTLE_TEST("Sand Veil increases evasion during sandstorm") HP_BAR(player); } } + +TO_DO_BATTLE_TEST("Sand Veil doesn't prevent Sandstorm damage if Cloud Nine/Air Lock is on the field"); +TO_DO_BATTLE_TEST("Sand Veil doesn't increase evasion if Cloud Nine/Air Lock is on the field"); diff --git a/test/battle/ability/slush_rush.c b/test/battle/ability/slush_rush.c new file mode 100644 index 0000000000..8ae62454bb --- /dev/null +++ b/test/battle/ability/slush_rush.c @@ -0,0 +1,6 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Slush Rush doubles speed from hail"); +TO_DO_BATTLE_TEST("Slush Rush doubles speed from snow"); +TO_DO_BATTLE_TEST("Slush Rush doesn't double speed if Cloud Nine/Air Lock is on the field"); diff --git a/test/battle/ability/snow_cloak.c b/test/battle/ability/snow_cloak.c index f1bfbcb9b0..a4d1acadb7 100644 --- a/test/battle/ability/snow_cloak.c +++ b/test/battle/ability/snow_cloak.c @@ -27,3 +27,6 @@ SINGLE_BATTLE_TEST("Snow Cloak increases evasion during hail") HP_BAR(player); } } + +TO_DO_BATTLE_TEST("Snow Cloak doesn't prevent hail damage if Cloud Nine/Air Lock is on the field"); +TO_DO_BATTLE_TEST("Snow Cloak doesn't increase evasion if Cloud Nine/Air Lock is on the field"); diff --git a/test/battle/ability/solar_power.c b/test/battle/ability/solar_power.c new file mode 100644 index 0000000000..f14ea11ee1 --- /dev/null +++ b/test/battle/ability/solar_power.c @@ -0,0 +1,7 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Solar Power increases a Sp. Attack by x1.5 in Sun"); +TO_DO_BATTLE_TEST("Solar Power doesn't increases a Sp. Attack if Cloud Nine/Air Lock is on the field"); +TO_DO_BATTLE_TEST("Solar Power causes the Pokémon to lose 1/8 max HP in Sun"); +TO_DO_BATTLE_TEST("Solar Power doesn't cause the Pokémon to lose 1/8 max HP if Cloud Nine/Air Lock is on the field"); diff --git a/test/battle/ability/swift_swim.c b/test/battle/ability/swift_swim.c new file mode 100644 index 0000000000..4282ac2741 --- /dev/null +++ b/test/battle/ability/swift_swim.c @@ -0,0 +1,6 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Swift Swim doubles speed if it's raining"); +TO_DO_BATTLE_TEST("Swift Swim doesn't double speed if Cloud Nine/Air Lock is on the field"); +TO_DO_BATTLE_TEST("Swift Swim doesn't double speed if they have an Utility Umbrella"); diff --git a/test/battle/ability/unnerve.c b/test/battle/ability/unnerve.c new file mode 100644 index 0000000000..9ad4ee7e5f --- /dev/null +++ b/test/battle/ability/unnerve.c @@ -0,0 +1,6 @@ +#include "global.h" +#include "test/battle.h" + +// Remember to add a PARAMETRIZE for As One in the following tests: +TO_DO_BATTLE_TEST("Unnerve prevents opposing Pokémon from eating their own berries"); +TO_DO_BATTLE_TEST("Unnerve doesn't prevent opposing Pokémon from using Natural Gift"); diff --git a/test/battle/ability/wind_rider.c b/test/battle/ability/wind_rider.c new file mode 100644 index 0000000000..57e6f0d275 --- /dev/null +++ b/test/battle/ability/wind_rider.c @@ -0,0 +1,127 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_TAILWIND].effect == EFFECT_TAILWIND); + ASSUME(gMovesInfo[MOVE_TAILWIND].windMove == TRUE); +} + +SINGLE_BATTLE_TEST("Wind Rider raises Attack by one stage if it sets up Tailwind") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRAMBLIN) { Ability(ABILITY_WIND_RIDER); } + } WHEN { + TURN { MOVE(opponent, MOVE_TAILWIND); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TAILWIND, opponent); + ABILITY_POPUP(opponent, ABILITY_WIND_RIDER); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Bramblin's Attack rose!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + } +} + +DOUBLE_BATTLE_TEST("Wind Rider raises Attack by one stage if Tailwind is setup by its partner") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRAMBLIN) { Ability(ABILITY_WIND_RIDER); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_TAILWIND); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TAILWIND, opponentLeft); + ABILITY_POPUP(opponentRight, ABILITY_WIND_RIDER); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + MESSAGE("Foe Bramblin's Attack rose!"); + } THEN { + EXPECT_EQ(opponentRight->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Wind Rider doesn't raise Attack if opponent sets up Tailwind") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRAMBLIN) { Ability(ABILITY_WIND_RIDER); } + } WHEN { + TURN { MOVE(player, MOVE_TAILWIND); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TAILWIND, player); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_WIND_RIDER); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Bramblin's Attack rose!"); + } + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + } +} + +SINGLE_BATTLE_TEST("Wind Rider raises Attack by one stage if switched into Tailwind on its side of the field") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_BRAMBLIN) { Ability(ABILITY_WIND_RIDER); } + } WHEN { + TURN { MOVE(opponent, MOVE_TAILWIND); } + TURN { SWITCH(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TAILWIND, opponent); + ABILITY_POPUP(opponent, ABILITY_WIND_RIDER); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Bramblin's Wind Rider raised its Attack!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Wind Rider activates when it's no longer effected by Neutralizing Gas") +{ + GIVEN { + PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRAMBLIN) { Ability(ABILITY_WIND_RIDER); } + } WHEN { + TURN { MOVE(opponent, MOVE_TAILWIND); } + TURN { SWITCH(player, 1); } + } SCENE { + ABILITY_POPUP(player, ABILITY_NEUTRALIZING_GAS); + MESSAGE("Neutralizing Gas filled the area!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TAILWIND, opponent); + SWITCH_OUT_MESSAGE("Weezing"); + MESSAGE("The effects of Neutralizing Gas wore off!"); + ABILITY_POPUP(opponent, ABILITY_WIND_RIDER); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Bramblin's Wind Rider raised its Attack!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Wind Rider absorbs Wind moves and raises Attack by one stage") +{ + ASSUME(gMovesInfo[MOVE_GUST].windMove == TRUE); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRAMBLIN) { Ability(ABILITY_WIND_RIDER); } + } WHEN { + TURN { MOVE(player, MOVE_GUST); } + } SCENE { + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_GUST, player); + HP_BAR(opponent); + } + ABILITY_POPUP(opponent, ABILITY_WIND_RIDER); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Bramblin's Attack rose!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + } +} diff --git a/test/battle/ai/ai_flag_risky.c b/test/battle/ai/ai_flag_risky.c index e6156de5a0..e1ceeb2161 100644 --- a/test/battle/ai/ai_flag_risky.c +++ b/test/battle/ai/ai_flag_risky.c @@ -13,7 +13,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_RISKY: AI will blindly Mirror Coat against specia ASSUME(gSpeciesInfo[SPECIES_GROVYLE].baseSpAttack == 85); ASSUME(gSpeciesInfo[SPECIES_GROVYLE].baseAttack == 65); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiRiskyFlag); - PLAYER(SPECIES_GROVYLE) { Level(20); Moves(MOVE_ENERGY_BALL); } + PLAYER(SPECIES_GROVYLE) { Level(20); Moves(MOVE_ENERGY_BALL); } OPPONENT(SPECIES_CASTFORM) { Level(20); Moves(MOVE_TACKLE, MOVE_MIRROR_COAT); } } WHEN { TURN { MOVE(player, MOVE_ENERGY_BALL) ; EXPECT_MOVE(opponent, aiRiskyFlag ? MOVE_MIRROR_COAT : MOVE_TACKLE); } @@ -32,7 +32,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_RISKY: AI will blindly Counter against physical a ASSUME(gSpeciesInfo[SPECIES_MARSHTOMP].baseAttack == 85); ASSUME(gSpeciesInfo[SPECIES_MARSHTOMP].baseSpAttack == 60); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiRiskyFlag); - PLAYER(SPECIES_MARSHTOMP) { Level(20); Moves(MOVE_WATERFALL); } + PLAYER(SPECIES_MARSHTOMP) { Level(20); Moves(MOVE_WATERFALL); } OPPONENT(SPECIES_CASTFORM) { Level(20); Moves(MOVE_TACKLE, MOVE_COUNTER); } } WHEN { TURN { MOVE(player, MOVE_WATERFALL) ; EXPECT_MOVE(opponent, aiRiskyFlag ? MOVE_COUNTER : MOVE_TACKLE); } @@ -49,7 +49,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_RISKY: AI will prioritize Revenge if slower") GIVEN { ASSUME(gMovesInfo[MOVE_REVENGE].effect == EFFECT_REVENGE); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiRiskyFlag); - PLAYER(SPECIES_GROVYLE) { Level(20); Speed(4); Moves(MOVE_ENERGY_BALL); } + PLAYER(SPECIES_GROVYLE) { Level(20); Speed(4); Moves(MOVE_ENERGY_BALL); } OPPONENT(SPECIES_CASTFORM) { Level(19); Speed(3); Moves(MOVE_TACKLE, MOVE_REVENGE); } } WHEN { TURN { MOVE(player, MOVE_ENERGY_BALL) ; EXPECT_MOVE(opponent, aiRiskyFlag ? MOVE_REVENGE : MOVE_TACKLE); } @@ -83,7 +83,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_RISKY: AI prefers high damage moves at the expens GIVEN { AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiRiskyFlag); - PLAYER(SPECIES_PSYDUCK) { Level(5); Moves(MOVE_TACKLE); } + PLAYER(SPECIES_PSYDUCK) { Level(5); Moves(MOVE_TACKLE); } OPPONENT(SPECIES_CASTFORM) { Level(20); Moves(MOVE_THUNDER, MOVE_THUNDERBOLT); } } WHEN { TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, aiRiskyFlag ? MOVE_THUNDER : MOVE_THUNDERBOLT); } diff --git a/test/battle/ai/ai_flag_sequence_switching.c b/test/battle/ai/ai_flag_sequence_switching.c index 1b4a264a24..7a0f3528bd 100644 --- a/test/battle/ai/ai_flag_sequence_switching.c +++ b/test/battle/ai/ai_flag_sequence_switching.c @@ -64,7 +64,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SEQUENCE_SWITCHING: Roar and Dragon Tail still fo } } -AI_SINGLE_BATTLE_TEST("AI_FLAG_SEQUENCE_SWITCHING: AI will always switch into lowest party index after U-Turn, Parting Shot, and Baton Pass") +AI_SINGLE_BATTLE_TEST("AI_FLAG_SEQUENCE_SWITCHING: AI will always switch into lowest party index after U-Turn, Parting Shot, Baton Pass, and Chilly Reception") { u32 j, aiSequenceSwitchingFlag = 0, move = MOVE_NONE; @@ -72,6 +72,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SEQUENCE_SWITCHING: AI will always switch into lo MOVE_U_TURN, MOVE_PARTING_SHOT, MOVE_BATON_PASS, + MOVE_CHILLY_RECEPTION, }; for (j = 0; j < ARRAY_COUNT(switchMoves); j++) @@ -84,6 +85,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SEQUENCE_SWITCHING: AI will always switch into lo ASSUME(gMovesInfo[MOVE_U_TURN].effect == EFFECT_HIT_ESCAPE); ASSUME(gMovesInfo[MOVE_PARTING_SHOT].effect == EFFECT_PARTING_SHOT); ASSUME(gMovesInfo[MOVE_BATON_PASS].effect == EFFECT_BATON_PASS); + ASSUME(gMovesInfo[MOVE_CHILLY_RECEPTION].effect == EFFECT_CHILLY_RECEPTION); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiSequenceSwitchingFlag); PLAYER(SPECIES_SWELLOW) { Level (50); } OPPONENT(SPECIES_MACHOP) { Level(1); Moves(move); } diff --git a/test/battle/gimmick/dynamax.c b/test/battle/gimmick/dynamax.c index dca175c637..b865ef2f1c 100644 --- a/test/battle/gimmick/dynamax.c +++ b/test/battle/gimmick/dynamax.c @@ -1234,7 +1234,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Replenish recycles allies' berries 50\% of t GIVEN { ASSUME(gMovesInfo[MOVE_G_MAX_REPLENISH].argument == MAX_EFFECT_RECYCLE_BERRIES); PLAYER(SPECIES_SNORLAX) { Item(ITEM_APICOT_BERRY); GigantamaxFactor(TRUE); } - PLAYER(SPECIES_MUNCHLAX) { Item(ITEM_APICOT_BERRY); } + PLAYER(SPECIES_MUNCHLAX) { Item(ITEM_APICOT_BERRY); Ability(ABILITY_THICK_FAT); } OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_APICOT_BERRY); } OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_APICOT_BERRY); } } WHEN { diff --git a/test/battle/gimmick/terastal.c b/test/battle/gimmick/terastal.c index f14c398b64..1b50bc4bcc 100644 --- a/test/battle/gimmick/terastal.c +++ b/test/battle/gimmick/terastal.c @@ -86,46 +86,6 @@ SINGLE_BATTLE_TEST("(TERA) Terastallizing into the same type gives that type 2x } } -SINGLE_BATTLE_TEST("(TERA) Terastallizing into a different type with Adaptability gives 2.0x STAB", s16 damage) -{ - bool32 tera; - PARAMETRIZE { tera = GIMMICK_NONE; } - PARAMETRIZE { tera = GIMMICK_TERA; } - GIVEN { - PLAYER(SPECIES_CRAWDAUNT) { Ability(ABILITY_ADAPTABILITY); TeraType(TYPE_NORMAL); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(player, MOVE_HEADBUTT, gimmick: tera); } - } SCENE { - MESSAGE("Crawdaunt used Headbutt!"); - ANIMATION(ANIM_TYPE_MOVE, MOVE_HEADBUTT, player); - HP_BAR(opponent, captureDamage: &results[i].damage); - } FINALLY { - // The jump from no STAB to 2.0x STAB is a 2.0x boost. - EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage); - } -} - -SINGLE_BATTLE_TEST("(TERA) Terastallizing into the same type with Adaptability gives 2.25x STAB", s16 damage) -{ - bool32 tera; - PARAMETRIZE { tera = GIMMICK_NONE; } - PARAMETRIZE { tera = GIMMICK_TERA; } - GIVEN { - PLAYER(SPECIES_CRAWDAUNT) { Ability(ABILITY_ADAPTABILITY); TeraType(TYPE_WATER); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(player, MOVE_WATER_PULSE, gimmick: tera); } - } SCENE { - MESSAGE("Crawdaunt used Water Pulse!"); - ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_PULSE, player); - HP_BAR(opponent, captureDamage: &results[i].damage); - } FINALLY { - // The jump from 2x STAB to 2.25x STAB is a 1.125x boost. - EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.125), results[1].damage); - } -} - SINGLE_BATTLE_TEST("(TERA) Terastallizing boosts moves of the same type to 60 BP", s16 damage) { bool32 tera; @@ -686,7 +646,7 @@ SINGLE_BATTLE_TEST("(TERA) Protean cannot change the type of a Terastallized Pok PLAYER(SPECIES_GRENINJA) { Ability(ABILITY_PROTEAN); TeraType(TYPE_GRASS); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(player, MOVE_BUBBLE, gimmick: GIMMICK_TERA); + TURN { MOVE(player, MOVE_BUBBLE, gimmick: GIMMICK_TERA); MOVE(opponent, MOVE_EMBER); } } SCENE { MESSAGE("Greninja used Bubble!"); diff --git a/test/battle/gimmick/zmove.c b/test/battle/gimmick/zmove.c index bde241bfd7..51c6516106 100644 --- a/test/battle/gimmick/zmove.c +++ b/test/battle/gimmick/zmove.c @@ -10,7 +10,7 @@ SINGLE_BATTLE_TEST("(Z-MOVE) Z-Moves do not retain priority") PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(opponent, MOVE_TACKLE); + TURN { MOVE(opponent, MOVE_TACKLE); MOVE(player, MOVE_QUICK_ATTACK, gimmick: GIMMICK_Z_MOVE); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); @@ -597,5 +597,24 @@ SINGLE_BATTLE_TEST("(Z-MOVE) Searing Sunraze Smash ignores the target's abilitie ANIMATION(ANIM_TYPE_MOVE, MOVE_SEARING_SUNRAZE_SMASH, player); HP_BAR(opponent); MESSAGE("A critical hit!"); - } + } +} + +SINGLE_BATTLE_TEST("(Z-MOVE) Z-Revelation Dance always transforms into Breakneck Blitz") +{ + u16 species; + PARAMETRIZE { species = SPECIES_ORICORIO_BAILE; } + PARAMETRIZE { species = SPECIES_ORICORIO_PAU; } + PARAMETRIZE { species = SPECIES_ORICORIO_POM_POM; } + PARAMETRIZE { species = SPECIES_ORICORIO_SENSU; } + GIVEN { + ASSUME(gMovesInfo[MOVE_REVELATION_DANCE].type == TYPE_NORMAL); + PLAYER(species) { Item(ITEM_NORMALIUM_Z); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_REVELATION_DANCE, gimmick: GIMMICK_Z_MOVE); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ZMOVE_ACTIVATE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BREAKNECK_BLITZ, player); + } } diff --git a/test/battle/hold_effect/ability_shield.c b/test/battle/hold_effect/ability_shield.c index ee84b2c5e0..e10c3e0887 100644 --- a/test/battle/hold_effect/ability_shield.c +++ b/test/battle/hold_effect/ability_shield.c @@ -69,7 +69,7 @@ SINGLE_BATTLE_TEST("Ability Shield protects against Mycelium Might") } WHEN { TURN { MOVE(opponent, MOVE_SPORE); MOVE(player, MOVE_SPORE); } } SCENE { - + if (item == ITEM_ABILITY_SHIELD) { NONE_OF { ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponent); diff --git a/test/battle/ability/booster_energy.c b/test/battle/hold_effect/booster_energy.c similarity index 100% rename from test/battle/ability/booster_energy.c rename to test/battle/hold_effect/booster_energy.c diff --git a/test/battle/hold_effect/utility_umbrella.c b/test/battle/hold_effect/utility_umbrella.c index e02a4fdef3..f04a773789 100644 --- a/test/battle/hold_effect/utility_umbrella.c +++ b/test/battle/hold_effect/utility_umbrella.c @@ -52,3 +52,5 @@ SINGLE_BATTLE_TEST("Utility Umbrella blocks Rain damage modifiers", s16 damage) EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[3].damage); } } + +// Moves and abilities affected by Utility Umbrella have their tests in the respective files diff --git a/test/battle/move.c b/test/battle/move.c index 228a09a7c6..081a91712d 100644 --- a/test/battle/move.c +++ b/test/battle/move.c @@ -80,57 +80,57 @@ SINGLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie } } -DOUBLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie [doubles]") +DOUBLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie [doubles]", u32 permutations) { - struct BattlePokemon *order[4] = { NULL, NULL, NULL, NULL }; - u32 a, b, c, d; - - // TODO: Test all of these in a single PASSES_RANDOMLY pass rather - // than 24 PARAMETRIZEd passes. - PARAMETRIZE { a = 0; b = 1; c = 2; d = 3; } - PARAMETRIZE { a = 0; b = 1; c = 3; d = 2; } - PARAMETRIZE { a = 0; b = 2; c = 1; d = 3; } - PARAMETRIZE { a = 0; b = 2; c = 3; d = 1; } - PARAMETRIZE { a = 0; b = 3; c = 1; d = 2; } - PARAMETRIZE { a = 0; b = 3; c = 2; d = 1; } - PARAMETRIZE { a = 1; b = 0; c = 2; d = 3; } - PARAMETRIZE { a = 1; b = 0; c = 3; d = 2; } - PARAMETRIZE { a = 1; b = 2; c = 0; d = 3; } - PARAMETRIZE { a = 1; b = 2; c = 3; d = 0; } - PARAMETRIZE { a = 1; b = 3; c = 0; d = 2; } - PARAMETRIZE { a = 1; b = 3; c = 2; d = 0; } - PARAMETRIZE { a = 2; b = 0; c = 1; d = 3; } - PARAMETRIZE { a = 2; b = 0; c = 3; d = 1; } - PARAMETRIZE { a = 2; b = 1; c = 0; d = 3; } - PARAMETRIZE { a = 2; b = 1; c = 3; d = 0; } - PARAMETRIZE { a = 2; b = 3; c = 0; d = 1; } - PARAMETRIZE { a = 2; b = 3; c = 1; d = 0; } - PARAMETRIZE { a = 3; b = 0; c = 1; d = 2; } - PARAMETRIZE { a = 3; b = 0; c = 2; d = 1; } - PARAMETRIZE { a = 3; b = 1; c = 0; d = 2; } - PARAMETRIZE { a = 3; b = 1; c = 2; d = 0; } - PARAMETRIZE { a = 3; b = 2; c = 0; d = 1; } - PARAMETRIZE { a = 3; b = 2; c = 1; d = 0; } - - order[a] = playerLeft; - order[b] = playerRight; - order[c] = opponentLeft; - order[d] = opponentRight; - - PASSES_RANDOMLY(1, 24, RNG_SPEED_TIE); + PARAMETRIZE {} // Hack to make permutations legal. + PASSES_RANDOMLY(24, 24, RNG_SPEED_TIE); + ASSUME(gMovesInfo[MOVE_ENDEAVOR].effect == EFFECT_ENDEAVOR); + ASSUME(gMovesInfo[MOVE_LIFE_DEW].effect == EFFECT_JUNGLE_HEALING); + ASSUME(gMovesInfo[MOVE_CRUSH_GRIP].effect == EFFECT_VARY_POWER_BASED_ON_HP); + ASSUME(gMovesInfo[MOVE_SUPER_FANG].effect == EFFECT_SUPER_FANG); GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Speed(1); } + PLAYER(SPECIES_WOBBUFFET) { MaxHP(480); HP(360); Defense(100); Speed(1); } PLAYER(SPECIES_WYNAUT) { Speed(1); } - OPPONENT(SPECIES_WOBBUFFET) { Speed(1); } + OPPONENT(SPECIES_WOBBUFFET) { Attack(100); Speed(1); } OPPONENT(SPECIES_WYNAUT) { Speed(1); } } WHEN { - TURN { MOVE(playerLeft, MOVE_SPLASH); MOVE(playerRight, MOVE_SPLASH); MOVE(opponentLeft, MOVE_SPLASH); MOVE(opponentRight, MOVE_SPLASH); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, order[0]); - ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, order[1]); - ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, order[2]); - ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, order[3]); + TURN { MOVE(playerLeft, MOVE_ENDEAVOR, target: opponentLeft); MOVE(playerRight, MOVE_LIFE_DEW); MOVE(opponentLeft, MOVE_CRUSH_GRIP, target: playerLeft, WITH_RNG(RNG_DAMAGE_MODIFIER, 0)); MOVE(opponentRight, MOVE_SUPER_FANG, target: playerLeft); } + } THEN { + // This tests for unique combinatins of HP values depending on which order the moves are executed in + // The unique outcomes arise from the specific attacks and HP, Def, and Atk values chosen + // The switch is then set up in such a way that the only way for this test to pass exactly one is for each HP combination to occur exactly once +#define HP_PAIR(a, b) ((a) * 1000 + (b)) + switch (HP_PAIR(playerLeft->hp, opponentLeft->hp)) + { + case HP_PAIR(188, 360): results[i].permutations += 1 << 0; break; + case HP_PAIR(189, 360): results[i].permutations += 1 << 1; break; + case HP_PAIR(261, 360): results[i].permutations += 1 << 2; break; + case HP_PAIR(235, 360): results[i].permutations += 1 << 3; break; + case HP_PAIR(262, 360): results[i].permutations += 1 << 4; break; + case HP_PAIR(202, 360): results[i].permutations += 1 << 5; break; + case HP_PAIR(189, 378): results[i].permutations += 1 << 6; break; + case HP_PAIR(189, 189): results[i].permutations += 1 << 7; break; + case HP_PAIR(189, 480): results[i].permutations += 1 << 8; break; + case HP_PAIR(188, 480): results[i].permutations += 1 << 9; break; + case HP_PAIR(188, 240): results[i].permutations += 1 << 10; break; + case HP_PAIR(188, 188): results[i].permutations += 1 << 11; break; + case HP_PAIR(262, 262): results[i].permutations += 1 << 12; break; + case HP_PAIR(262, 142): results[i].permutations += 1 << 13; break; + case HP_PAIR(202, 403): results[i].permutations += 1 << 14; break; + case HP_PAIR(202, 202): results[i].permutations += 1 << 15; break; + case HP_PAIR(262, 283): results[i].permutations += 1 << 16; break; + case HP_PAIR(202, 283): results[i].permutations += 1 << 17; break; + case HP_PAIR(235, 180): results[i].permutations += 1 << 18; break; + case HP_PAIR(261, 180): results[i].permutations += 1 << 19; break; + case HP_PAIR(235, 235): results[i].permutations += 1 << 20; break; + case HP_PAIR(235, 300): results[i].permutations += 1 << 21; break; + case HP_PAIR(261, 141): results[i].permutations += 1 << 22; break; + case HP_PAIR(261, 261): results[i].permutations += 1 << 23; break; + } +#undef HP_PAIR + } FINALLY { + EXPECT_EQ(results[i].permutations, (1 << 24) - 1); } } diff --git a/test/battle/move_effect/defog.c b/test/battle/move_effect/defog.c index 418d28d97b..80d500d2ee 100644 --- a/test/battle/move_effect/defog.c +++ b/test/battle/move_effect/defog.c @@ -131,7 +131,7 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Mist and Safeguard } } -DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Stealth Rock and Sticky Web from player's side") +DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Stealth Rock and Sticky Web from player's side (Gen 6+)") { u16 move; @@ -154,13 +154,15 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Stealth Rock and S if (move == MOVE_DEFOG) { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); MESSAGE("Foe Wobbuffet's evasiveness fell!"); - MESSAGE("The pointed stones disappeared from around your team!"); - MESSAGE("The sticky web has disappeared from the ground around your team!"); + if (B_DEFOG_EFFECT_CLEARING >= GEN_6) { + MESSAGE("The pointed stones disappeared from around your team!"); + MESSAGE("The sticky web has disappeared from the ground around your team!"); + } } // Switch happens SWITCH_OUT_MESSAGE("Wobbuffet"); SEND_IN_MESSAGE("Wobbuffet"); - if (move != MOVE_DEFOG) { + if (move != MOVE_DEFOG || B_DEFOG_EFFECT_CLEARING <= GEN_5) { HP_BAR(playerLeft); MESSAGE("Pointed stones dug into Wobbuffet!"); MESSAGE("Wobbuffet was caught in a Sticky Web!"); @@ -198,12 +200,13 @@ SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Spikes from player if (move == MOVE_DEFOG) { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); MESSAGE("Foe Wobbuffet's evasiveness fell!"); - MESSAGE("The spikes disappeared from the ground around your team!"); + if (B_DEFOG_EFFECT_CLEARING >= GEN_6) + MESSAGE("The spikes disappeared from the ground around your team!"); } // Switch happens SWITCH_OUT_MESSAGE("Wobbuffet"); SEND_IN_MESSAGE("Wobbuffet"); - if (move != MOVE_DEFOG) { + if (move != MOVE_DEFOG || B_DEFOG_EFFECT_CLEARING <= GEN_5) { HP_BAR(player); MESSAGE("Wobbuffet is hurt by spikes!"); } @@ -216,7 +219,7 @@ SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Spikes from player } } -SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes terrain") +SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes terrain (Gen 8+)") { u16 move; @@ -225,7 +228,6 @@ SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes terrain") PARAMETRIZE { move = MOVE_MISTY_TERRAIN; } PARAMETRIZE { move = MOVE_GRASSY_TERRAIN; } GIVEN { - ASSUME(B_DEFOG_CLEARS_TERRAIN >= GEN_8); PLAYER(SPECIES_WOBBUFFET) { Speed(50); } OPPONENT(SPECIES_WOBBUFFET) { Speed(5); } } WHEN { @@ -235,19 +237,29 @@ SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes terrain") ANIMATION(ANIM_TYPE_MOVE, MOVE_DEFOG, opponent); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); MESSAGE("Wobbuffet's evasiveness fell!"); - if (move == MOVE_PSYCHIC_TERRAIN) { - MESSAGE("The weirdness disappeared from the battlefield."); + if (B_DEFOG_EFFECT_CLEARING >= GEN_8) { + if (move == MOVE_PSYCHIC_TERRAIN) { + MESSAGE("The weirdness disappeared from the battlefield."); + } + else if (move == MOVE_ELECTRIC_TERRAIN) { + MESSAGE("The electricity disappeared from the battlefield."); + } + else if (move == MOVE_MISTY_TERRAIN) { + MESSAGE("The mist disappeared from the battlefield."); + } + else if (move == MOVE_GRASSY_TERRAIN) { + MESSAGE("The grass disappeared from the battlefield."); + } + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_RESTORE_BG, player); + } else { + NONE_OF { + MESSAGE("The weirdness disappeared from the battlefield."); + MESSAGE("The electricity disappeared from the battlefield."); + MESSAGE("The mist disappeared from the battlefield."); + MESSAGE("The grass disappeared from the battlefield."); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_RESTORE_BG, player); + } } - else if (move == MOVE_ELECTRIC_TERRAIN) { - MESSAGE("The electricity disappeared from the battlefield."); - } - else if (move == MOVE_MISTY_TERRAIN) { - MESSAGE("The mist disappeared from the battlefield."); - } - else if (move == MOVE_GRASSY_TERRAIN) { - MESSAGE("The grass disappeared from the battlefield."); - } - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_RESTORE_BG, player); } } @@ -270,11 +282,12 @@ SINGLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Toxic Spikes from if (move == MOVE_DEFOG) { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); MESSAGE("Wobbuffet's evasiveness fell!"); - MESSAGE("The poison spikes disappeared from the ground around the opposing team!"); + if (B_DEFOG_EFFECT_CLEARING >= GEN_6) + MESSAGE("The poison spikes disappeared from the ground around the opposing team!"); } // Switch happens MESSAGE("2 sent out Wobbuffet!"); - if (move != MOVE_DEFOG) { + if (move != MOVE_DEFOG || B_DEFOG_EFFECT_CLEARING <= GEN_5) { MESSAGE("Foe Wobbuffet was poisoned!"); ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); STATUS_ICON(opponent, poison: TRUE); @@ -356,15 +369,17 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes everything it can" MESSAGE("Ally's Aurora Veil wore off!"); MESSAGE("Ally's Safeguard wore off!"); - MESSAGE("The spikes disappeared from the ground around your team!"); - MESSAGE("The pointed stones disappeared from around your team!"); - MESSAGE("The poison spikes disappeared from the ground around your team!"); - MESSAGE("The sticky web has disappeared from the ground around your team!"); + if (B_DEFOG_EFFECT_CLEARING >= GEN_6) { + MESSAGE("The spikes disappeared from the ground around your team!"); + MESSAGE("The pointed stones disappeared from around your team!"); + MESSAGE("The poison spikes disappeared from the ground around your team!"); + MESSAGE("The sticky web has disappeared from the ground around your team!"); - // Opponent side - MESSAGE("The spikes disappeared from the ground around the opposing team!"); - MESSAGE("The pointed stones disappeared from around the opposing team!"); - MESSAGE("The poison spikes disappeared from the ground around the opposing team!"); - MESSAGE("The sticky web has disappeared from the ground around the opposing team!"); + // Opponent side + MESSAGE("The spikes disappeared from the ground around the opposing team!"); + MESSAGE("The pointed stones disappeared from around the opposing team!"); + MESSAGE("The poison spikes disappeared from the ground around the opposing team!"); + MESSAGE("The sticky web has disappeared from the ground around the opposing team!"); + } } } diff --git a/test/battle/move_effect/guard_split.c b/test/battle/move_effect/guard_split.c new file mode 100644 index 0000000000..3f012ab6e2 --- /dev/null +++ b/test/battle/move_effect/guard_split.c @@ -0,0 +1,22 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_GUARD_SPLIT].effect == EFFECT_GUARD_SPLIT); +} + +SINGLE_BATTLE_TEST("Guard Split averages users and targets Def and Sp. Def stats") +{ + GIVEN { + PLAYER(SPECIES_BULBASAUR); + OPPONENT(SPECIES_IVYSAUR); + } WHEN { + TURN { MOVE(player, MOVE_GUARD_SPLIT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_GUARD_SPLIT, player); + } THEN { + EXPECT_EQ(player->defense, opponent->defense); + EXPECT_EQ(player->spDefense, opponent->spDefense); + } +} diff --git a/test/battle/move_effect/heal_bell.c b/test/battle/move_effect/heal_bell.c index 8bd6c1f456..743af905ce 100644 --- a/test/battle/move_effect/heal_bell.c +++ b/test/battle/move_effect/heal_bell.c @@ -10,7 +10,7 @@ ASSUMPTIONS DOUBLE_BATTLE_TEST("Heal Bell cures the entire party") { u32 move; - + PARAMETRIZE { move = MOVE_HEAL_BELL; } PARAMETRIZE { move = MOVE_AROMATHERAPY; } @@ -39,10 +39,10 @@ DOUBLE_BATTLE_TEST("Heal Bell cures the entire party") DOUBLE_BATTLE_TEST("Heal Bell does not cure soundproof partners") { u32 ability; - + PARAMETRIZE { ability = ABILITY_SCRAPPY; } PARAMETRIZE { ability = ABILITY_SOUNDPROOF; } - + ASSUME(B_HEAL_BELL_SOUNDPROOF != GEN_5); GIVEN { @@ -65,10 +65,10 @@ DOUBLE_BATTLE_TEST("Heal Bell does not cure soundproof partners") SINGLE_BATTLE_TEST("Heal Bell cures inactive soundproof Pokemon") { u32 ability; - + PARAMETRIZE { ability = ABILITY_SCRAPPY; } PARAMETRIZE { ability = ABILITY_SOUNDPROOF; } - + ASSUME(B_HEAL_BELL_SOUNDPROOF >= GEN_5); GIVEN { @@ -87,7 +87,7 @@ SINGLE_BATTLE_TEST("Heal Bell cures inactive soundproof Pokemon") SINGLE_BATTLE_TEST("Heal Bell cures a soundproof user") -{ +{ ASSUME(B_HEAL_BELL_SOUNDPROOF == GEN_5 || B_HEAL_BELL_SOUNDPROOF >= GEN_8); GIVEN { diff --git a/test/battle/move_effect/knock_off.c b/test/battle/move_effect/knock_off.c index ba6f9b6fe7..50d8aaa773 100644 --- a/test/battle/move_effect/knock_off.c +++ b/test/battle/move_effect/knock_off.c @@ -90,7 +90,7 @@ SINGLE_BATTLE_TEST("Knock Off does not remove items through Substitute") PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LEFTOVERS); }; } WHEN { - TURN { MOVE(opponent, MOVE_SUBSTITUTE); + TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_KNOCK_OFF); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_KNOCK_OFF, player); @@ -112,7 +112,7 @@ SINGLE_BATTLE_TEST("Recycle cannot recover an item removed by Knock Off") ANIMATION(ANIM_TYPE_MOVE, MOVE_KNOCK_OFF, player); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_KNOCKOFF); MESSAGE("Wobbuffet knocked off Foe Wobbuffet's Leftovers!"); - + MESSAGE("Foe Wobbuffet used Recycle!"); MESSAGE("But it failed!"); } THEN { diff --git a/test/battle/move_effect/power_split.c b/test/battle/move_effect/power_split.c new file mode 100644 index 0000000000..70d1bfd5ea --- /dev/null +++ b/test/battle/move_effect/power_split.c @@ -0,0 +1,22 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_POWER_SPLIT].effect == EFFECT_POWER_SPLIT); +} + +SINGLE_BATTLE_TEST("Power Split averages user and targets Atk and Sp. Atk stats") +{ + GIVEN { + PLAYER(SPECIES_BULBASAUR); + OPPONENT(SPECIES_IVYSAUR); + } WHEN { + TURN { MOVE(player, MOVE_POWER_SPLIT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POWER_SPLIT, player); + } THEN { + EXPECT_EQ(player->attack, opponent->attack); + EXPECT_EQ(player->spAttack, opponent->spAttack); + } +} diff --git a/test/battle/move_effect/protect.c b/test/battle/move_effect/protect.c index 973033bc33..aca5ef859d 100644 --- a/test/battle/move_effect/protect.c +++ b/test/battle/move_effect/protect.c @@ -482,3 +482,68 @@ DOUBLE_BATTLE_TEST("Crafty Shield protects self and ally from status moves") } } } + +SINGLE_BATTLE_TEST("Protect does not block Confide") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_CONFIDE].effect == EFFECT_SPECIAL_ATTACK_DOWN); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_PROTECT); MOVE(player, MOVE_CONFIDE); } + } SCENE { + MESSAGE("Wobbuffet used Confide!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFIDE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + NOT MESSAGE("Foe Wobbuffet protected itself!"); + } +} + +DOUBLE_BATTLE_TEST("Crafty Shield protects self and ally from Confide") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_CONFIDE].effect == EFFECT_SPECIAL_ATTACK_DOWN); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_CRAFTY_SHIELD); MOVE(playerLeft, MOVE_CONFIDE, target: opponentLeft); MOVE(playerRight, MOVE_CONFIDE, target: opponentRight); } + } SCENE { + MESSAGE("Wobbuffet used Confide!"); + MESSAGE("Foe Wobbuffet protected itself!"); + MESSAGE("Wynaut used Confide!"); + MESSAGE("Foe Wynaut protected itself!"); + } +} + +DOUBLE_BATTLE_TEST("Crafty Shield does not protect against moves that target all battlers") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_FLOWER_SHIELD].target == MOVE_TARGET_ALL_BATTLERS); + ASSUME(gSpeciesInfo[SPECIES_TANGELA].types[0] == TYPE_GRASS); + ASSUME(gSpeciesInfo[SPECIES_TANGROWTH].types[0] == TYPE_GRASS); + ASSUME(gSpeciesInfo[SPECIES_SUNKERN].types[0] == TYPE_GRASS); + ASSUME(gSpeciesInfo[SPECIES_SUNFLORA].types[0] == TYPE_GRASS); + PLAYER(SPECIES_TANGELA); + PLAYER(SPECIES_TANGROWTH); + OPPONENT(SPECIES_SUNKERN); + OPPONENT(SPECIES_SUNFLORA); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_CRAFTY_SHIELD); MOVE(opponentRight, MOVE_CELEBRATE); MOVE(playerLeft, MOVE_FLOWER_SHIELD); MOVE(playerRight, MOVE_CELEBRATE); } + } SCENE { + MESSAGE("Tangela used Flower Shield!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLOWER_SHIELD, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + MESSAGE("Tangela's Defense rose!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLOWER_SHIELD, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + MESSAGE("Foe Sunkern's Defense rose!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLOWER_SHIELD, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + MESSAGE("Tangrowth's Defense rose!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLOWER_SHIELD, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + MESSAGE("Foe Sunflora's Defense rose!"); + } +} diff --git a/test/battle/move_effect/retaliate.c b/test/battle/move_effect/retaliate.c new file mode 100644 index 0000000000..581793e854 --- /dev/null +++ b/test/battle/move_effect/retaliate.c @@ -0,0 +1,137 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_RETALIATE].effect == EFFECT_RETALIATE); +} + +SINGLE_BATTLE_TEST("Retaliate doubles in base power the turn after an ally faints") +{ + s16 damage[2]; + GIVEN { + PLAYER(SPECIES_WYNAUT) { HP(1); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); SEND_OUT(player, 1); } + TURN { MOVE(player, MOVE_RETALIATE); } + TURN { MOVE(player, MOVE_RETALIATE); } + } SCENE { + HP_BAR(opponent, captureDamage: &damage[0]); + HP_BAR(opponent, captureDamage: &damage[1]); + } THEN { + EXPECT_MUL_EQ(damage[1], Q_4_12(2), damage[0]); + } +} + +SINGLE_BATTLE_TEST("Retaliate doubles in base power the turn after an ally faints (opponent)") +{ + s16 damage[2]; + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); SEND_OUT(opponent, 1); } + TURN { MOVE(opponent, MOVE_RETALIATE); } + TURN { MOVE(opponent, MOVE_RETALIATE); } + } SCENE { + HP_BAR(player, captureDamage: &damage[0]); + HP_BAR(player, captureDamage: &damage[1]); + } THEN { + EXPECT_MUL_EQ(damage[1], Q_4_12(2), damage[0]); + } +} + +DOUBLE_BATTLE_TEST("Retaliate works with passive damage") +{ + s16 damage[2]; + u32 move; + u32 move2 = MOVE_CELEBRATE; + struct BattlePokemon *moveTarget = playerLeft; + PARAMETRIZE { move = MOVE_TOXIC; moveTarget = playerLeft; } + PARAMETRIZE { move = MOVE_POISON_POWDER; moveTarget = playerLeft; } + PARAMETRIZE { move = MOVE_WILL_O_WISP; moveTarget = playerLeft; } + #if B_USE_FROSTBITE == TRUE + PARAMETRIZE { move = MOVE_ICE_BEAM; moveTarget = playerLeft; } + #endif + PARAMETRIZE { move = MOVE_SANDSTORM; moveTarget = playerLeft; } + PARAMETRIZE { move = MOVE_HAIL; moveTarget = playerLeft; } + PARAMETRIZE { move = MOVE_LEECH_SEED; moveTarget = playerLeft; } + PARAMETRIZE { move = MOVE_MAGMA_STORM; moveTarget = playerLeft; } + PARAMETRIZE { move = MOVE_FLAME_BURST; moveTarget = playerRight; } + PARAMETRIZE { move = MOVE_FIRE_PLEDGE; moveTarget = playerRight; move2 = MOVE_GRASS_PLEDGE; } + GIVEN { + ASSUME(gMovesInfo[MOVE_TOXIC].effect == EFFECT_TOXIC); + ASSUME(gMovesInfo[MOVE_POISON_POWDER].effect == EFFECT_POISON); + ASSUME(gMovesInfo[MOVE_WILL_O_WISP].effect == EFFECT_WILL_O_WISP); + #if B_USE_FROSTBITE == TRUE + ASSUME(gMovesInfo[MOVE_ICE_BEAM].additionalEffects[0].moveEffect == MOVE_EFFECT_FREEZE_OR_FROSTBITE); + #endif + ASSUME(gMovesInfo[MOVE_SANDSTORM].effect == EFFECT_SANDSTORM); + ASSUME(gMovesInfo[MOVE_HAIL].effect == EFFECT_HAIL); + ASSUME(gMovesInfo[MOVE_LEECH_SEED].effect == EFFECT_LEECH_SEED); + ASSUME(gMovesInfo[MOVE_MAGMA_STORM].additionalEffects[0].moveEffect == MOVE_EFFECT_WRAP); + ASSUME(gMovesInfo[MOVE_FLAME_BURST].additionalEffects[0].moveEffect == MOVE_EFFECT_FLAME_BURST); + PLAYER(SPECIES_WYNAUT) { Ability(ABILITY_SHADOW_TAG); HP(18); } + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_SHADOW_TAG); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_CLEFABLE) { Ability(ABILITY_MAGIC_GUARD); Level(1); } + OPPONENT(SPECIES_CLEFABLE) { Ability(ABILITY_MAGIC_GUARD); } + } WHEN { + TURN { MOVE(opponentRight, move2, target: moveTarget); MOVE(opponentLeft, move, target: moveTarget); MOVE(playerLeft, MOVE_CELEBRATE); SEND_OUT(playerLeft, 2); } + TURN { MOVE(opponentRight, MOVE_CELEBRATE, target: moveTarget); MOVE(playerLeft, MOVE_RETALIATE, target: opponentRight); } + TURN { MOVE(opponentRight, MOVE_CELEBRATE, target: moveTarget); MOVE(playerLeft, MOVE_RETALIATE, target: opponentRight); } + } SCENE { + if (move != MOVE_FLAME_BURST) + MESSAGE("Wynaut used Celebrate!"); + HP_BAR(opponentRight, captureDamage: &damage[0]); + HP_BAR(opponentRight, captureDamage: &damage[1]); + } THEN { + EXPECT_MUL_EQ(damage[1], Q_4_12(2), damage[0]); + } +} + +SINGLE_BATTLE_TEST("Retaliate works with Perish Song") +{ + s16 damage[2]; + GIVEN { + ASSUME(gMovesInfo[MOVE_PERISH_SONG].effect == EFFECT_PERISH_SONG); + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_KOMMO_O) { Ability(ABILITY_SOUNDPROOF); } + } WHEN { + TURN { MOVE(opponent, MOVE_PERISH_SONG); } + TURN { MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(opponent, MOVE_CELEBRATE); SEND_OUT(player, 1); } + TURN { MOVE(player, MOVE_RETALIATE); } + TURN { MOVE(player, MOVE_RETALIATE); } + } SCENE { + HP_BAR(opponent, captureDamage: &damage[0]); + HP_BAR(opponent, captureDamage: &damage[1]); + } THEN { + EXPECT_MUL_EQ(damage[1], Q_4_12(2), damage[0]); + } +} + +SINGLE_BATTLE_TEST("Retaliate works with self-inflicted fainting") +{ + s16 damage[2]; + GIVEN { + ASSUME(gMovesInfo[MOVE_HEALING_WISH].effect == EFFECT_HEALING_WISH); + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_HEALING_WISH); SEND_OUT(player, 1); } + TURN { MOVE(player, MOVE_RETALIATE); } + TURN { MOVE(player, MOVE_RETALIATE); } + } SCENE { + HP_BAR(opponent, captureDamage: &damage[0]); + HP_BAR(opponent, captureDamage: &damage[1]); + } THEN { + EXPECT_MUL_EQ(damage[1], Q_4_12(2), damage[0]); + } +} diff --git a/test/battle/move_effect/revelation_dance.c b/test/battle/move_effect/revelation_dance.c new file mode 100644 index 0000000000..9ab5d4a8e2 --- /dev/null +++ b/test/battle/move_effect/revelation_dance.c @@ -0,0 +1,149 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_REVELATION_DANCE].effect == EFFECT_REVELATION_DANCE); + ASSUME(gMovesInfo[MOVE_REVELATION_DANCE].danceMove == TRUE); + ASSUME(MoveHasAdditionalEffectSelfArg(MOVE_BURN_UP, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE)); + ASSUME(gMovesInfo[MOVE_FORESTS_CURSE].effect == EFFECT_THIRD_TYPE); + ASSUME(gMovesInfo[MOVE_FORESTS_CURSE].argument == TYPE_GRASS); + ASSUME(gMovesInfo[MOVE_ROOST].effect == EFFECT_ROOST); +} + +SINGLE_BATTLE_TEST("Revelation Dance changes its type depending on the user's 1st Type") +{ + u16 speciesPlayer; + u16 speciesOpponent; + + PARAMETRIZE { speciesPlayer = SPECIES_ORICORIO_POM_POM; speciesOpponent = SPECIES_DUGTRIO; } + PARAMETRIZE { speciesPlayer = SPECIES_ORICORIO_BAILE; speciesOpponent = SPECIES_BLASTOISE; } + PARAMETRIZE { speciesPlayer = SPECIES_ORICORIO_PAU; speciesOpponent = SPECIES_LIEPARD; } + PARAMETRIZE { speciesPlayer = SPECIES_ORICORIO_SENSU; speciesOpponent = SPECIES_PERSIAN; } + + GIVEN { + PLAYER(speciesPlayer); + OPPONENT(speciesOpponent); + } WHEN { + TURN { MOVE(player, MOVE_REVELATION_DANCE); } + } SCENE { + if (speciesPlayer == SPECIES_ORICORIO_BAILE) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVELATION_DANCE, player); + HP_BAR(opponent); + MESSAGE("It's not very effective…"); + } + else { + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVELATION_DANCE, player); + HP_BAR(opponent); + MESSAGE("It's not very effective…"); + } + } + } +} + +SINGLE_BATTLE_TEST("Revelation Dance changes its type depending on the user's 2nd Type if it has no 1st type") +{ + GIVEN { + PLAYER(SPECIES_ORICORIO_BAILE); + OPPONENT(SPECIES_EMPOLEON); + } WHEN { + TURN { MOVE(player, MOVE_BURN_UP); } + TURN { MOVE(player, MOVE_REVELATION_DANCE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, player); + HP_BAR(opponent); + NONE_OF { + MESSAGE("It's not very effective…"); + MESSAGE("It's super effective!"); + } + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVELATION_DANCE, player); + HP_BAR(opponent); + MESSAGE("It's not very effective…"); + } +} + +SINGLE_BATTLE_TEST("Revelation Dance changes its type depending on the user's 3rd Type if it has no 1st or 2nd type") +{ + GIVEN { + PLAYER(SPECIES_GROWLITHE); + OPPONENT(SPECIES_TREVENANT); + } WHEN { + TURN { MOVE(player, MOVE_BURN_UP); MOVE(opponent, MOVE_FORESTS_CURSE); } + TURN { MOVE(player, MOVE_REVELATION_DANCE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, player); + HP_BAR(opponent); + MESSAGE("It's super effective!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FORESTS_CURSE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVELATION_DANCE, player); + HP_BAR(opponent); + MESSAGE("It's not very effective…"); + } +} + +SINGLE_BATTLE_TEST("Revelation Dance becomes Typeless if its user is Typeless") +{ + u16 speciesOpponent; + + PARAMETRIZE { speciesOpponent = SPECIES_BLISSEY; } + PARAMETRIZE { speciesOpponent = SPECIES_BLASTOISE; } + PARAMETRIZE { speciesOpponent = SPECIES_CHARIZARD; } + PARAMETRIZE { speciesOpponent = SPECIES_VENUSAUR; } + PARAMETRIZE { speciesOpponent = SPECIES_GOLEM; } + PARAMETRIZE { speciesOpponent = SPECIES_AEGISLASH; } + + GIVEN { + PLAYER(SPECIES_GROWLITHE); + OPPONENT(speciesOpponent); + } WHEN { + TURN { MOVE(player, MOVE_BURN_UP); } + TURN { MOVE(player, MOVE_REVELATION_DANCE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, player); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVELATION_DANCE, player); + HP_BAR(opponent); + NONE_OF { + MESSAGE("It's not very effective…"); + MESSAGE("It's super effective!"); + } + } +} + +SINGLE_BATTLE_TEST("Revelation Dance becomes Normal type if used by a Typeless Pokemon due to Roost") +{ + u16 speciesOpponent; + + PARAMETRIZE { speciesOpponent = SPECIES_SABLEYE; } + PARAMETRIZE { speciesOpponent = SPECIES_AGGRON; } + + ASSUME(B_ROOST_PURE_FLYING >= GEN_5); + + GIVEN { + PLAYER(SPECIES_ORICORIO_BAILE) { Ability(ABILITY_DANCER); } + OPPONENT(speciesOpponent); + } WHEN { + TURN { MOVE(player, MOVE_BURN_UP); MOVE(opponent, MOVE_TACKLE); } + TURN { MOVE(player, MOVE_ROOST); MOVE(opponent, MOVE_REVELATION_DANCE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, player); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROOST, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVELATION_DANCE, opponent); + HP_BAR(player); + ABILITY_POPUP(player, ABILITY_DANCER); + if (speciesOpponent == SPECIES_AGGRON) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVELATION_DANCE, player); + HP_BAR(opponent); + MESSAGE("It's not very effective…"); + } + else { + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVELATION_DANCE, player); + HP_BAR(opponent); + MESSAGE("It's not very effective…"); + } + } + } +} diff --git a/test/battle/move_effect/round.c b/test/battle/move_effect/round.c new file mode 100644 index 0000000000..c911c96b63 --- /dev/null +++ b/test/battle/move_effect/round.c @@ -0,0 +1,115 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_ROUND].effect == EFFECT_ROUND); +} + +DOUBLE_BATTLE_TEST("Round allows other battlers which also selected the moves to immediately use the move, ignoring turn order") +{ + GIVEN { + ASSUME(gItemsInfo[ITEM_LAGGING_TAIL].holdEffect == HOLD_EFFECT_LAGGING_TAIL); + ASSUME(gMovesInfo[MOVE_IRON_HEAD].additionalEffects[0].moveEffect == MOVE_EFFECT_FLINCH); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LAGGING_TAIL); } + } WHEN { + TURN { + MOVE(playerRight, MOVE_CELEBRATE); + MOVE(opponentLeft, MOVE_ROUND, target: playerLeft); + MOVE(playerLeft, MOVE_IRON_HEAD, target: opponentRight); + MOVE(opponentRight, MOVE_ROUND, target: playerLeft); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, opponentLeft); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_IRON_HEAD, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_IRON_HEAD, playerLeft); + } +} + +DOUBLE_BATTLE_TEST("Round usages beyond the first one has double base power") +{ + s16 damage[2]; + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + MOVE(opponentLeft, MOVE_ROUND, target: playerLeft); + MOVE(opponentRight, MOVE_ROUND, target: playerLeft); + } + } SCENE { + HP_BAR(playerLeft, captureDamage: &damage[0]); + HP_BAR(playerLeft, captureDamage: &damage[1]); + } THEN { + EXPECT_MUL_EQ(damage[0], Q_4_12(2.0), damage[1]); + } +} + +DOUBLE_BATTLE_TEST("Round still preserves the turn order outside of the other Round users moving immediately") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + MOVE(opponentLeft, MOVE_ROUND, target: playerLeft); + MOVE(playerRight, MOVE_CELEBRATE); + MOVE(playerLeft, MOVE_CELEBRATE); + MOVE(opponentRight, MOVE_ROUND, target: playerLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerLeft); + } +} +DOUBLE_BATTLE_TEST("Round still preserves the turn order outside of the other Round users moving immediately with switch") +{ + KNOWN_FAILING; // #5148 + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + SWITCH(playerRight, 2); + MOVE(opponentLeft, MOVE_ROUND, target: playerLeft); + MOVE(playerLeft, MOVE_CELEBRATE); + MOVE(opponentRight, MOVE_ROUND, target: playerLeft); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerLeft); + } +} + +DOUBLE_BATTLE_TEST("Round causes opposing pokemon to use Round immediately") +{ + GIVEN { + ASSUME(gItemsInfo[ITEM_LAGGING_TAIL].holdEffect == HOLD_EFFECT_LAGGING_TAIL); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LAGGING_TAIL); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_CELEBRATE); MOVE(playerRight, MOVE_ROUND, target: opponentLeft); MOVE(playerLeft, MOVE_CELEBRATE, target: opponentRight); MOVE(opponentRight, MOVE_ROUND, target: playerLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, playerRight); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROUND, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerLeft); + } +} diff --git a/test/battle/move_effect/sleep_talk.c b/test/battle/move_effect/sleep_talk.c index 0a42eb90e9..8ecd600f36 100644 --- a/test/battle/move_effect/sleep_talk.c +++ b/test/battle/move_effect/sleep_talk.c @@ -14,7 +14,7 @@ SINGLE_BATTLE_TEST("Sleep Talk fails if not asleep") u32 status; PARAMETRIZE { status = STATUS1_SLEEP; } PARAMETRIZE { status = STATUS1_NONE; } - + GIVEN { PLAYER(SPECIES_WOBBUFFET) { Status1(status); Moves(MOVE_SLEEP_TALK, MOVE_TACKLE, MOVE_POUND, MOVE_SCRATCH); } OPPONENT(SPECIES_WOBBUFFET); @@ -35,7 +35,7 @@ SINGLE_BATTLE_TEST("Sleep Talk fails if not asleep") SINGLE_BATTLE_TEST("Sleep Talk works if user has Comatose") { - + GIVEN { PLAYER(SPECIES_KOMALA) { Moves(MOVE_SLEEP_TALK, MOVE_TACKLE, MOVE_POUND, MOVE_SCRATCH); } OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/stomping_tantrum.c b/test/battle/move_effect/stomping_tantrum.c new file mode 100644 index 0000000000..1a5870fdd0 --- /dev/null +++ b/test/battle/move_effect/stomping_tantrum.c @@ -0,0 +1,134 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_STOMPING_TANTRUM].effect == EFFECT_STOMPING_TANTRUM); +} + +SINGLE_BATTLE_TEST("Stomping Tatrum will deal double damage if user flinched on the previous turn") +{ + s16 damage[3]; + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_STOMPING_TANTRUM); SWITCH(opponent, 1); } + TURN { MOVE(opponent, MOVE_FAKE_OUT); MOVE(player, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_STOMPING_TANTRUM); } + TURN { MOVE(player, MOVE_STOMPING_TANTRUM); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STOMPING_TANTRUM, player); + HP_BAR(opponent, captureDamage: &damage[0]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_FAKE_OUT, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_STOMPING_TANTRUM, player); + HP_BAR(opponent, captureDamage: &damage[1]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_STOMPING_TANTRUM, player); + HP_BAR(opponent, captureDamage: &damage[2]); + } THEN { + EXPECT_MUL_EQ(damage[0], Q_4_12(2.0), damage[1]); + EXPECT_EQ(damage[0], damage[2]); + } +} + +SINGLE_BATTLE_TEST("Stomping Tatrum will deal double damage if user failed to attack due to paralysis") +{ + s16 damage[3]; + PASSES_RANDOMLY(25, 100, RNG_PARALYSIS); + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(100); Item(ITEM_POTION); }; + OPPONENT(SPECIES_WOBBUFFET) { Speed(10); Item(ITEM_LUM_BERRY); }; + } WHEN { + TURN { MOVE(player, MOVE_STOMPING_TANTRUM); MOVE(opponent, MOVE_THUNDER_WAVE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_TRICK); } + TURN { MOVE(player, MOVE_STOMPING_TANTRUM); } + TURN { MOVE(player, MOVE_STOMPING_TANTRUM); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STOMPING_TANTRUM, player); + HP_BAR(opponent, captureDamage: &damage[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_WAVE, opponent); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_TRICK, opponent); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_STOMPING_TANTRUM, player); + HP_BAR(opponent, captureDamage: &damage[1]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_STOMPING_TANTRUM, player); + HP_BAR(opponent, captureDamage: &damage[2]); + } THEN { + EXPECT_MUL_EQ(damage[0], Q_4_12(2.0), damage[1]); + EXPECT_EQ(damage[0], damage[2]); + } +} + +SINGLE_BATTLE_TEST("Stomping Tatrum will not deal double damage if target protects") +{ + s16 damage[2]; + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_STOMPING_TANTRUM); } + TURN { MOVE(opponent, MOVE_PROTECT); MOVE(player, MOVE_STOMPING_TANTRUM); } + TURN { MOVE(player, MOVE_STOMPING_TANTRUM); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STOMPING_TANTRUM, player); + HP_BAR(opponent, captureDamage: &damage[0]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponent); + MESSAGE("Foe Wobbuffet protected itself!"); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_STOMPING_TANTRUM, player); + HP_BAR(opponent, captureDamage: &damage[1]); + } THEN { + EXPECT_EQ(damage[0], damage[1]); + } +} + +SINGLE_BATTLE_TEST("Stomping Tatrum will not deal double damage if it failed on the previous turn cause of Protect") +{ + s16 damage[2]; + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_BRIGHTPOWDER); }; + } WHEN { + TURN { MOVE(player, MOVE_STOMPING_TANTRUM); } + TURN { MOVE(player, MOVE_STOMPING_TANTRUM, hit: FALSE); } + TURN { MOVE(player, MOVE_STOMPING_TANTRUM); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STOMPING_TANTRUM, player); + HP_BAR(opponent, captureDamage: &damage[0]); + MESSAGE("Wobbuffet's attack missed!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STOMPING_TANTRUM, player); + HP_BAR(opponent, captureDamage: &damage[1]); + } THEN { + EXPECT_EQ(damage[0], damage[1]); + } +} + +SINGLE_BATTLE_TEST("Stomping Tatrum will deal double damage if user was immune to previous move") +{ + s16 damage[2]; + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_PIDGEY); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_STOMPING_TANTRUM); SWITCH(opponent, 1); } + TURN { MOVE(player, MOVE_STOMPING_TANTRUM); SWITCH(opponent, 0); } + TURN { MOVE(player, MOVE_STOMPING_TANTRUM); SWITCH(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STOMPING_TANTRUM, player); + HP_BAR(opponent, captureDamage: &damage[0]); + MESSAGE("It doesn't affect Foe Pidgey…"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STOMPING_TANTRUM, player); + HP_BAR(opponent, captureDamage: &damage[1]); + } THEN { + EXPECT_MUL_EQ(damage[0], Q_4_12(2.0), damage[1]); + } +} diff --git a/test/battle/move_effect/telekinesis.c b/test/battle/move_effect/telekinesis.c index 4210b1865b..3da96a08b9 100644 --- a/test/battle/move_effect/telekinesis.c +++ b/test/battle/move_effect/telekinesis.c @@ -71,4 +71,4 @@ SINGLE_BATTLE_TEST("Telekinesis makes the target immune to Ground-type attacks") TO_DO_BATTLE_TEST("Baton Pass passes Telekinesis' effect"); //Bulbapedia doesn't confirm what happens with Diglett, Dugtrio, Sandygast and Palossand, so it needs to be tested in-game. -TO_DO_BATTLE_TEST("Baton Pass removes Telekinesis' effect disappears if the switching-in mon is Mega Gengar"); +TO_DO_BATTLE_TEST("Baton Pass removes Telekinesis' effect disappears if the switching-in mon is Mega Gengar"); diff --git a/test/battle/move_effect/weather_ball.c b/test/battle/move_effect/weather_ball.c index 1656b60d87..432e5f79f7 100644 --- a/test/battle/move_effect/weather_ball.c +++ b/test/battle/move_effect/weather_ball.c @@ -78,3 +78,5 @@ SINGLE_BATTLE_TEST("Weather Ball doubles its power and turns to an Ice-type move EXPECT_MUL_EQ(results[0].damage, Q_4_12(4.0), results[1].damage); // double base power + type effectiveness. } } + +TO_DO_BATTLE_TEST("Weather Ball doesn't double its power or change type if Cloud Nine/Air Lock is on the field"); diff --git a/test/battle/weather/hail.c b/test/battle/weather/hail.c index 5caeb84891..4210a22d9e 100644 --- a/test/battle/weather/hail.c +++ b/test/battle/weather/hail.c @@ -70,3 +70,15 @@ DOUBLE_BATTLE_TEST("Hail deals damage based on turn order") HP_BAR(playerRight); } } + +SINGLE_BATTLE_TEST("Hail damage rounds properly when maxHP < 16") +{ + GIVEN { + PLAYER(SPECIES_MAGIKARP) { Level(1); MaxHP(11); HP(11); } + OPPONENT(SPECIES_GLALIE); + } WHEN { + TURN { MOVE(opponent, MOVE_HAIL); } + } SCENE { + HP_BAR(player, damage: 1); + } +} diff --git a/test/battle/weather/sandstorm.c b/test/battle/weather/sandstorm.c index 63b24afd7e..1673c26f99 100644 --- a/test/battle/weather/sandstorm.c +++ b/test/battle/weather/sandstorm.c @@ -82,3 +82,15 @@ DOUBLE_BATTLE_TEST("Sandstorm deals damage based on turn order") HP_BAR(playerRight); } } + +SINGLE_BATTLE_TEST("Sandstorm damage rounds properly when maxHP < 16") +{ + GIVEN { + PLAYER(SPECIES_MAGIKARP) { Level(1); MaxHP(11); HP(11); } + OPPONENT(SPECIES_SANDSLASH); + } WHEN { + TURN { MOVE(opponent, MOVE_SANDSTORM); } + } SCENE { + HP_BAR(player, damage: 1); + } +} diff --git a/test/random.c b/test/random.c index 0232ff1547..238a76467e 100644 --- a/test/random.c +++ b/test/random.c @@ -196,13 +196,8 @@ TEST("RandomElement generates a uniform distribution") TEST("RandomUniform mul-based faster than mod-based (compile-time)") { - #if HQ_RANDOM == TRUE - const u32 expectedMulSum = 6; - const u32 expectedModSum = 4; - #else - const u32 expectedMulSum = 3; - const u32 expectedModSum = 4; - #endif + const u32 expectedMulSum = 6; + const u32 expectedModSum = 4; struct Benchmark mulBenchmark, modBenchmark; u32 mulSum = 0, modSum = 0; @@ -234,13 +229,8 @@ TEST("RandomUniform mul-based faster than mod-based (compile-time)") TEST("RandomUniform mul-based faster than mod-based (run-time)") { - #if HQ_RANDOM == TRUE - const u32 expectedMulSum = 289; - const u32 expectedModSum = 205; - #else - const u32 expectedMulSum = 232; - const u32 expectedModSum = 249; - #endif + const u32 expectedMulSum = 289; + const u32 expectedModSum = 205; u32 i; struct Benchmark mulBenchmark, modBenchmark; u32 mulSum = 0, modSum = 0; @@ -264,7 +254,6 @@ TEST("RandomUniform mul-based faster than mod-based (run-time)") EXPECT_EQ(modSum, expectedModSum); } -#if HQ_RANDOM == TRUE TEST("Thumb and C SFC32 implementations produce the same results") { u32 thumbSum; @@ -285,5 +274,4 @@ TEST("Thumb and C SFC32 implementations produce the same results") } EXPECT_EQ(thumbSum, cSum); -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 11432bd12b..9a1ad8d708 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -35,20 +35,12 @@ #define STATE gBattleTestRunnerState #define DATA gBattleTestRunnerState->data -#if HQ_RANDOM == TRUE #define RNG_SEED_DEFAULT {0, 0, 0, 0} static inline bool32 RngSeedNotDefault(const rng_value_t *seed) { return (seed->a | seed->b | seed->c | seed->ctr) != 0; } -#else -#define RNG_SEED_DEFAULT 0x00000000 -static inline bool32 RngSeedNotDefault(const rng_value_t *seed) -{ - return *seed != RNG_SEED_DEFAULT; -} -#endif #undef Q_4_12 #define Q_4_12(n) (s32)((n) * 4096) @@ -410,7 +402,7 @@ u32 RandomUniformExcept(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32 if (STATE->trials == 1) { u32 n = 0, i; - for (i = lo; i < hi; i++) + for (i = lo; i <= hi; i++) if (!reject(i)) n++; STATE->trials = n; @@ -769,7 +761,7 @@ static u32 CountAiExpectMoves(struct ExpectedAIAction *expectedAction, u32 battl u32 i, countExpected = 0; for (i = 0; i < MAX_MON_MOVES; i++) { - if (gBitTable[i] & expectedAction->moveSlots) + if ((1u << i) & expectedAction->moveSlots) { if (printLog) PrintAiMoveLog(battlerId, i, gBattleMons[battlerId].moves[i], gBattleStruct->aiFinalScore[battlerId][expectedAction->target][i]); @@ -801,7 +793,7 @@ void TestRunner_Battle_CheckChosenMove(u32 battlerId, u32 moveId, u32 target) for (i = 0; i < MAX_MON_MOVES; i++) { - if (gBitTable[i] & expectedAction->moveSlots) + if ((1u << i) & expectedAction->moveSlots) { expectedMoveId = gBattleMons[battlerId].moves[i]; if (!expectedAction->notMove) @@ -917,8 +909,8 @@ static void CheckIfMaxScoreEqualExpectMove(u32 battlerId, s32 target, struct Exp // We expect move 'i', but it has the same best score as another move that we didn't expect. if (scores[i] == scores[bestScoreId] && !aiAction->notMove - && (aiAction->moveSlots & gBitTable[i]) - && !(aiAction->moveSlots & gBitTable[bestScoreId])) + && (aiAction->moveSlots & (1u << i)) + && !(aiAction->moveSlots & (1u << bestScoreId))) { Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: EXPECT_MOVE %S has the same best score(%d) as not expected MOVE %S", filename, aiAction->sourceLine, GetMoveName(moves[i]), scores[i], GetMoveName(moves[bestScoreId])); @@ -926,8 +918,8 @@ static void CheckIfMaxScoreEqualExpectMove(u32 battlerId, s32 target, struct Exp // We DO NOT expect move 'i', but it has the same best score as another move. if (scores[i] == scores[bestScoreId] && aiAction->notMove - && (aiAction->moveSlots & gBitTable[i]) - && !(aiAction->moveSlots & gBitTable[bestScoreId])) + && (aiAction->moveSlots & (1u << i)) + && !(aiAction->moveSlots & (1u << bestScoreId))) { Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: NOT_EXPECT_MOVE %S has the same best score(%d) as MOVE %S", filename, aiAction->sourceLine, GetMoveName(moves[i]), scores[i], GetMoveName(moves[bestScoreId])); @@ -940,9 +932,9 @@ static void PrintAiMoveLog(u32 battlerId, u32 moveSlot, u32 moveId, s32 totalSco s32 i, scoreFromLogs = 0; if (!DATA.logAI) return; - if (DATA.aiLogPrintedForMove[battlerId] & gBitTable[moveSlot]) return; + if (DATA.aiLogPrintedForMove[battlerId] & (1u << moveSlot)) return; - DATA.aiLogPrintedForMove[battlerId] |= gBitTable[moveSlot]; + DATA.aiLogPrintedForMove[battlerId] |= 1u << moveSlot; Test_MgbaPrintf("Score Log for move %S:\n", GetMoveName(moveId)); for (i = 0; i < MAX_AI_LOG_LINES; i++) { @@ -1327,7 +1319,7 @@ void TestRunner_Battle_AfterLastTurn(void) } STATE->runThen = TRUE; - STATE->runFinally = STATE->runParameter + 1 == STATE->parameters; + STATE->runFinally = STATE->runParameter + 1 == STATE->parameters && STATE->runTrial + 1 >= STATE->trials; InvokeTestFunction(test); STATE->runThen = FALSE; STATE->runFinally = FALSE; @@ -1357,18 +1349,15 @@ static void CB2_BattleTest_NextParameter(void) static inline rng_value_t MakeRngValue(const u16 seed) { - #if HQ_RANDOM == TRUE - int i; - rng_value_t result = {0, 0, seed, 1}; - for (i = 0; i < 16; i++) - { + int i; + rng_value_t result = {0, 0, seed, 1}; + for (i = 0; i < 16; i++) + { _SFC32_Next(&result); - } - return result; - #else - return ISO_RANDOMIZE1(seed); - #endif + } + return result; } + static void CB2_BattleTest_NextTrial(void) { ClearFlagAfterTest(); @@ -1452,7 +1441,7 @@ void Randomly(u32 sourceLine, u32 passes, u32 trials, struct RandomlyContext ctx { const struct BattleTest *test = GetBattleTest(); INVALID_IF(STATE->trials != 0, "PASSES_RANDOMLY can only be used once per test"); - INVALID_IF(test->resultsSize > 0, "PASSES_RANDOMLY is incompatible with results"); + INVALID_IF(test->resultsSize > 0 && STATE->parametersCount > 1, "PASSES_RANDOMLY is incompatible with results"); INVALID_IF(passes > trials, "%d passes specified, but only %d trials", passes, trials); STATE->rngTag = ctx.tag; STATE->rngTrialOffset = 0; @@ -2186,7 +2175,7 @@ static void TryMarkExpectMove(u32 sourceLine, struct BattlePokemon *battler, str id = DATA.expectedAiActionIndex[battlerId]; DATA.expectedAiActions[battlerId][id].type = B_ACTION_USE_MOVE; - DATA.expectedAiActions[battlerId][id].moveSlots |= gBitTable[moveSlot]; + DATA.expectedAiActions[battlerId][id].moveSlots |= 1 << moveSlot; DATA.expectedAiActions[battlerId][id].target = target; DATA.expectedAiActions[battlerId][id].explicitTarget = ctx->explicitTarget; DATA.expectedAiActions[battlerId][id].sourceLine = sourceLine; diff --git a/tools/learnset_helpers/teachable.py b/tools/learnset_helpers/teachable.py index 92ed8562d8..eb109e7a46 100644 --- a/tools/learnset_helpers/teachable.py +++ b/tools/learnset_helpers/teachable.py @@ -13,7 +13,7 @@ with open("./include/config/pokemon.h", "r") as file: def parse_mon_name(name): return re.sub(r'(?!^)([A-Z]+)', r'_\1', name).upper() - + tm_moves = [] tutor_moves = [] @@ -196,7 +196,7 @@ for move in tm_moves: header += "// " + longest_move_name * "*" + " //\n" header_print(tutor_title) tutor_moves.sort() # alphabetically sort tutor moves for easier referencing -for move in tutor_moves: +for move in tutor_moves: header_print("- " + move) header += "// " + longest_move_name * "*" + " //\n" header_print(universal_title) diff --git a/tools/preproc/asm_file.cpp b/tools/preproc/asm_file.cpp index ca8b8cc4ae..39d352bbd7 100644 --- a/tools/preproc/asm_file.cpp +++ b/tools/preproc/asm_file.cpp @@ -673,14 +673,14 @@ int AsmFile::FindLastLineNumber(std::string& filename) if (pos < 0) RaiseError("line indicator for header file not found before `enum`"); - + pos++; while (m_buffer[pos] == ' ' || m_buffer[pos] == '\t') pos++; if (!IsAsciiDigit(m_buffer[pos])) RaiseError("malformatted line indicator found before `enum`, expected line number"); - + unsigned n = 0; int digit = 0; while ((digit = ConvertDigit(m_buffer[pos++], 10)) != -1) @@ -715,7 +715,7 @@ int AsmFile::FindLastLineNumber(std::string& filename) filename += c; } - + return n + linebreaks - 1; }